Status: implemented (see TODO.md for live Done/Open status) · 2026-06-19
Boarding a space station puts the player inside the station, floating in space as its own place — no planet visible, no weather, no clouds, constant interior lighting (no day-night), breathable (life support), walkable, with NPCs (vendor / quartermaster / dockhands). A station is modelled as its own location and boarded exactly like travelling to another body, so it reuses the proven world-transition path and is cleanly isolated from any planet.
- Void world type. A
Voidflag onPlanetTypemakesWorldGenerator.Generatereturn an all-air world immediately (no terrain, caves, ore, flora). - The
orbital_stationplanet type.Void=true,SpaceSky=true, breathable atmosphere (life support → no oxygen drain), zero flora/creatures, weather disabled, a fixed non-advancing time-of-day. The universe generator never assigns it to a celestial body — it is a code-defined type, not part of the planet pool. - Station environment. The station world's
WorldEnvironmentisSpaceSky=true, clear weather, cloud density 0, fixed time-of-day, breathable. The client gates clouds/weather/day-night onenv, so the black sky, constant light and lit interior fill follow from the env. As a belt-and-braces fallback,Sky.csalso still treats a non-emptyGame.StationNameas "boarded" → space sky, no day/night and lit interior (so a boarded station looks right even before its env arrives); the env path and thisStationNamecheck coexist. LoadWorldskips planet content for void worlds: no settlement/wreck stamping, no flora/fluids/creatures/landing-zone init; it sets the fixed station env instead.- Boarding = per-player travel into the station world.
BoardStationmirrorsHandleTravel: range/validation checks → leave the space instance → remember the return location →LoadWorld("orbital_station", "station:"+id)→ stamp the station onto a clean origin with a solid hangar floor + spawn the station NPCs (scoped to this world) → setCurrentLocationId, position andAboardShip=false→SentChunks.Clear()→ sendWorldReset+ player state + inventory + NPCs + environment. The client'sOnWorldResetclears chunks, nulls the spawn and re-snaps once chunks stream — the robust reposition. - Leaving = travel back.
LeaveStationloads the return planet world, restores the ship and position, re-snaps viaWorldReset, and unloads the station world if empty. It can undock back into space flight around the orbited planet rather than dropping to the surface. - Player-built stations reuse the same machinery:
StampPlayerStationstamps the player's own cells into theorbital_stationvoid world (spawn on a guaranteed floor pad), registers the build as a boardableCelestialBody, and persists it as aspace_structure. Stations are peaceful — void worlds hard-skip enemy/creature/flora ticks.
GameServerSpaceStations.cs—BoardStation,LeaveStation,StampStation,StampPlayerStation, station NPC spawning, multi-station iteration per system.WorldGenerator.Generate— early-out forVoidworlds.PlanetType(Voidflag) + theorbital_stationdefinition.LoadWorld(GameServer.cs) — void-world content skip (if (!planet.Void)), per-world NPC scoping.- Client
Sky.cs+OnWorldReset— env-driven space sky / lit interior (with aStationNamefallback), clean reposition. - Tests:
BoardStation_PutsPlayerInOwnVoidWorld_OnSolidGround_WithLifeSupport,LeaveStation_TravelsBackToThePlanet,LeaveStation_UndocksBackIntoSpaceFlight,VoidPlanet_GeneratesEmptySpace.
- The earlier bug was that
BoardStationstamped the station into the planet world at a high Y and teleported there without a real world transition — noWorldReset, noSentChunks.Clear(). The station chunks never streamed in time, so gravity pulled the player down until far-below planet terrain finally loaded: the "black → fall → planet" symptom, with weather/clouds/day-night bleeding in from the shared planet world. Modelling the station as its own location fixed both at once.
- Station-world edit persistence is intentionally light (regenerate on board; player-built stations
persist as
space_structure). - Residual "flora into space" on pre-fix persisted station worlds is hardened separately (structure-stamp enclosure checks + re-clearing old stamped worlds) — see TODO.md.