Skip to content

Bang integration

sw2102-bang is the standalone universe generator that produces a fresh galaxy. The gameserver consumes its output to bootstrap (or rebuild) the world. This page documents the contract between the two repos.

The generator lives at https://github.com/.../sw2102-bang. The gameserver is services/gameserver/ inside the Sectorwars2102 repo. The two communicate by writing to and reading from the shared PostgreSQL database; there is no HTTP coupling.

Two execution modes

sw2102-bang supports two entry points. Both produce the same Universe shape internally; they differ in where the result goes.

CLI mode — JSON to disk or stdout

bigbang [options]

The CLI writes the generated universe as JSON to stdout, an output file, or as a human summary. Use this for review, reproducibility checks, and offline tooling.

Source: sw2102-bang/src/cli.ts

Flag Default Meaning
--sectors, -s <n> 1000 Total sectors (clamped 20-20000)
--seed <n> random RNG seed; same seed + same config = same universe
--density <n> 20 Max course length, controls overall density (3-50)
--two-way-warps <n> 30 Two-way warp percentage (5-100)
--one-way-warps <n> 5 One-way warp percentage (0-25)
--max-warps <n> 6 Max warps per sector (2-10)
--port-percent <n> 50 Sectors with ports (0-80)
--planet-percent <n> 20 Sectors with planets (0-60)
--nebula-percent <n> 5 Sectors in nebulae (0-30)
--fedspace <n> 10 Federation-protected sectors (2-20)
--stardock <n> 0 (auto) Stardock sector ID; 0 means auto-pick
--output, -o <file> stdout Write JSON to file
--summary off Print a human-readable summary
--compact off Compact JSON (no formatting)
--quiet, -q off Suppress progress output

The same options resolve through resolveConfig() (sw2102-bang/src/config.ts), which clamps inputs and auto-picks a seed when seed === 0.

Service mode — write directly to PostgreSQL

The generator can also run as a one-shot container that writes to a database and exits. This is the integration path with the gameserver.

docker compose up generator

Source: sw2102-bang/src/db-writer.ts, sw2102-bang/Dockerfile.generator, sw2102-bang/docker-compose.yml

Configuration is via environment variables:

Env var Default Meaning
DATABASE_URL postgresql://tw2102:tw2102@localhost:5432/tw2102 Connection string
UNIVERSE_NAME default Identifier; reuse to overwrite
TW_SECTORS 1000 Total sectors
TW_SEED random RNG seed
TW_PORT_PERCENT 50 Port density
TW_PLANET_PERCENT 20 Planet density

The container waits for the database to accept connections, generates a universe, deletes any existing universe with the same name, and writes the new one in a single transaction.

Output shape — JSON

The CLI emits the Universe interface from sw2102-bang/src/types.ts, with the internal sectors map serialized as a keyed object:

{
  "version": "1.0.0",
  "seed": 42,
  "totalSectors": 1000,
  "sectors": {
    "1": {
      "id": 1,
      "warps": [2, 3, 7],
      "port": {
        "name": "Sol Station",
        "class": 1,
        "commodities": {
          "fuel_ore":  {"action": "B", "quantity": 1000, "capacity": 5000, "regenRate": 100},
          "organics":  {"action": "B", "quantity": 800,  "capacity": 3000, "regenRate": 80},
          "equipment": {"action": "S", "quantity": 500,  "capacity": 2000, "regenRate": 50}
        }
      },
      "planets": [
        {
          "name": "Terra",
          "type": "earth",
          "owner": null,
          "fuelOre": 0,
          "organics": 0,
          "equipment": 0,
          "colonists": 0,
          "citadel": null
        }
      ],
      "navHazards": [],
      "nebula": null,
      "beacon": null,
      "explored": true
    }
  },
  "warps": [
    {"from": 1, "to": 2, "oneWay": false}
  ],
  "specialLocations": [
    {"type": "terra",      "sectorId": 1},
    {"type": "stardock",   "sectorId": 173},
    {"type": "rylos",      "sectorId": 401},
    {"type": "alpha_centauri", "sectorId": 9},
    {"type": "ferrengi",   "sectorId": 600}
  ],
  "fedspaceSectors": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
  "config": { "...": "the BigBangConfig used to generate this universe" },
  "createdAt": "2026-04-30T18:00:00.000Z"
}

Field reference (from sw2102-bang/src/types.ts):

  • Sectors. Each sector has warps (an array of destination sector IDs), an optional port, an array of planets, an array of navHazards, an optional nebula, an optional beacon, and an explored flag.
  • Ports. Class 0 is reserved for special ports (Stardock); classes 1-8 encode buy/sell combinations across the three core commodities. Each commodity tracks action (B for buying, S for selling), quantity, capacity, and regenRate.
  • Planets. Six types (barren, earth, mountainous, oceanic, glacial, volcanic); generator output starts with empty stockpiles and no citadel.
  • Nav hazards. mine (Armid), limpet, or fighter (deployed); each carries an owner ID and quantity.
  • Nebulae. normal (hides contents) or magnetic (disrupts navigation); 1-100 density.
  • Warps. A flat list paralleling each sector's warps array; each entry specifies from, to, and oneWay.
  • Special locations. Terra, Stardock, Rylos, Alpha Centauri, Ferrengi homeworld; the generator places each one once.
  • Fedspace. Sectors 1 through fedspaceSize; protected from PvP.

Output shape — PostgreSQL

When run in service mode, the generator writes to the bang schema defined in sw2102-bang/db/init.sql:

Table Purpose Key columns
universes One row per generated universe. id PK, name UNIQUE, version, seed, total_sectors, config (JSONB)
sectors One row per sector. id PK, universe_id FK, sector_number, beacon, explored
warps Connections between sectors. id PK, universe_id FK, from_sector, to_sector, one_way
ports One row per port. id PK, sector_id FK, name, class, fuel_ore (JSONB), organics (JSONB), equipment (JSONB)
planets One row per planet. id PK, sector_id FK, name, type, owner, commodity columns, citadel_level, citadel_fighters
nebulae One row per nebula sector. id PK, sector_id FK, type, density
nav_hazards One row per hazard placement. id PK, sector_id FK, type, quantity, owner
special_locations Terra/Stardock/etc. id PK, universe_id FK, type, sector_number

The writer deletes any prior universes row with the same name (cascading to all dependent rows) and writes the new universe in a single BEGIN/COMMIT transaction with batched inserts (500 rows per batch).

Gameserver consumption

The bang schema does not match the gameserver's domain schema. The gameserver expects Galaxy, Region, Cluster, Zone, Sector, Planet, Station, WarpTunnel rows with multi-region scaffolding (Central Nexus, Terran Space, player-owned regions), faction influence values, security/development/traffic levels, and the Sectorwars-specific eight-commodity catalog.

The translation algorithm — sixteen numbered steps with explicit per-entity translation tables, JSONB defaults, idempotency rules, and failure modes — is specified in ../SYSTEMS/bang-import-pipeline.md. All three operational paths below invoke the same translator pipeline; they differ only in how the bang payload reaches the translator and where the trigger comes from.

Path A — admin-triggered import

The admin endpoint POST /admin/galaxy/import-bang (see Swagger at <api-host>/docs) is the operator-facing trigger. The handler:

  1. Receives the admin's parameters (target region context, sector count, seed, density, faction balance, optional overrides).
  2. Invokes the generator out-of-process (CLI mode with the requested params), capturing the JSON.
  3. Hands the captured JSON plus the target region context to the translator pipeline.
  4. Returns the new Galaxy.id and Region.id to the admin.

Used for: post-launch region creation, admin-driven re-imports, and player-region provisioning. Because the import takes 60–120 seconds for a 5,000-sector Nexus, the admin endpoint runs the translator as an async background job and returns a job ID; the admin UI polls the job until completion.

Path B — bootstrap script

For first-time environment setup, the generator runs as a one-shot container that writes to a separate bang database (see "Service mode" above). A bootstrap script then reads bang.universes plus dependent rows, hands them to the translator pipeline, and exits. The script lives at services/gameserver/scripts/bootstrap_from_bang.py (target). It accepts a bang connection URL, a target Galaxy.name, and the target region context, and runs once per region during environment bring-up — typically twice on a fresh install (central_nexus then terran_space).

Used for: initial environment provisioning, full-galaxy re-rolls during major releases.

Path C — Alembic data migration

For test fixtures and CI environments, the generator output is checked in as a JSON artifact under services/gameserver/tests/fixtures/bang/ (target) and replayed via an Alembic data migration. The migration calls the same translator pipeline with the JSON loaded from disk. Suitable for deterministic tests; unsuitable for production-sized galaxies due to file size and migration time.

Used for: integration test fixtures, deterministic CI seeds.

Per-entity translation

The full per-entity translation (Sector, Warp, Port → Station, Planet, Nebula → Cluster nebula classification, NavHazard, SpecialLocation, fedspaceSectors) is documented in the appendices of ../SYSTEMS/bang-import-pipeline.md:

  • Appendix A — bang Commodity (3) → gameserver commodity (8) with default values for the synthesized five.
  • Appendix B — bang NebulaeType (2) → gameserver nebula classification (6) by zone bias and density.
  • Appendix C — bang PlanetType (6) → gameserver PlanetType enum.
  • Appendix D — bang SpecialLocationType → gameserver Sector special_features and associated rows.
  • Appendix E — bang Port class 0–8 → gameserver StationClass and StationType.

This operations doc does not duplicate the appendices; consult the SYSTEMS doc when implementing any of the three paths.

Reproducibility

Both modes are deterministic given a seed and a BigBangConfig. The same seed always produces the same universe regardless of when or where the generator runs. Operators wanting to reproduce a specific galaxy should record the seed and the full config from the universe row.

Versioning

The version field in the Universe and universes row is the generator schema version (currently 1.0.0). The gameserver's translator must check this version and refuse to import an unknown one. Schema changes to the generator increment this field; the translator should be updated in the same release.

Known gaps

🐛 Commodity coverage — Bang emits 3 of 7 core commodities

The Bang generator's port-class system uses a binary 2^3 = 8 encoding across three commodities only:

  • fuel_ore (maps to gameserver ore)
  • organics
  • equipment

The gameserver spec defines seven core commodities for procedural trade (../FEATURES/definitions.md, ../FEATURES/economy/trading.md):

Commodity In Bang?
ore ✅ (fuel_ore)
organics
equipment
gourmet_food
fuel
exotic_technology
luxury_goods

Effect: A Bang-bootstrapped universe has no procedural ports buying or selling 4 of the 7 core commodities. Players can only acquire those four through:

  • Special locations (Stardock at Sector 1, TradeDocks).
  • Refining or production from owned planets.
  • Random events.

This is not the intended Launch state.

Resolution paths:

  1. Expand Bang — extend sw2102-bang/src/types.ts Commodity enum to include all seven, and update the port-class generator to use a 2^7 = 128 encoding (or a curated subset). Higher fidelity but a real engineering effort.
  2. Post-process at import — keep Bang's 3-commodity output and inject the missing four during the bang-import-pipeline translator pass (see ../SYSTEMS/bang-import-pipeline.md). Cheaper, but risks divergence between Bang's deterministic output and the gameserver's post-injected state.

The design target is option (1); option (2) is the practical near-term workaround pending Bang refactor.

Tracking: This gap is also flagged at ../FEATURES/economy/trading.md under "Bang generator commodity gap". When resolved, update both docs.