diff --git a/docs/DATA-MODEL.md b/docs/DATA-MODEL.md index 01dd99e..893af8f 100644 --- a/docs/DATA-MODEL.md +++ b/docs/DATA-MODEL.md @@ -40,7 +40,6 @@ Recommended global ID families: - `commanderId` - `systemId` - `anchorId` -- `localspaceId` - `stationId` - `shipId` - `moduleId` @@ -59,15 +58,14 @@ The intended core entities are: 2. `Commander` 3. `System` 4. `Anchor` -5. `Localspace` -6. `Station` -7. `Ship` -8. `ModuleInstance` -9. `Claim` -10. `ConstructionSite` -11. `MarketOrder` -12. `Recipe` -13. `PolicySet` +5. `Station` +6. `Ship` +7. `ModuleInstance` +8. `Claim` +9. `ConstructionSite` +10. `MarketOrder` +11. `Recipe` +12. `PolicySet` ## Faction @@ -120,12 +118,12 @@ Suggested fields: - `label` - `galaxyPosition` - `star definition` -- `nodeIds` +- `anchorIds` - `faction influence later` ## Anchor -An anchor is a meaningful location in a system that owns a localspace. +An anchor is a meaningful location in a system. Suggested fields: @@ -133,7 +131,7 @@ Suggested fields: - `systemId` - `kind` - `systemPosition` -- `localspaceId` +- `localspaceRadius` - `parentAnchorId?` - `orbital metadata?` - `constructionIds?` @@ -146,25 +144,9 @@ Recommended anchor kinds: - `lagrange-point` - `resource-node` -## Localspace - -A localspace is the tactical simulation context attached to one anchor. - -Suggested fields: - -- `localspaceId` -- `anchorId` -- `systemId` -- `radius` -- `occupantShipIds` -- `occupantStationIds` -- `occupantClaimIds` -- `occupantConstructionSiteIds` -- `serverAuthorityId later` - ## Station -A station is a constructed structure that lives inside one localspace. +A station is a constructed structure that lives at one anchor. Suggested fields: @@ -173,7 +155,6 @@ Suggested fields: - `commanderId?` - `anchorId` - `systemId` -- `localspaceId` - `moduleIds` - `inventory` - `population` @@ -236,7 +217,6 @@ Suggested fields: - `commanderId?` - `systemId` - `anchorId` -- `localspaceId` - `placedAt` - `activatesAt` - `state` @@ -258,7 +238,6 @@ Suggested fields: - `constructionSiteId` - `ownerFactionId` - `anchorId` -- `localspaceId` - `targetKind` - `targetDefinitionId` - `requiredItems` @@ -351,7 +330,6 @@ Recommended ship spatial state fields: - `spaceLayer` - `currentSystemId` - `currentAnchorId?` -- `currentLocalspaceId?` - `localPosition?` - `systemPosition?` - `movementRegime` diff --git a/docs/EVENTS.md b/docs/EVENTS.md index 71a8cd3..8357af3 100644 --- a/docs/EVENTS.md +++ b/docs/EVENTS.md @@ -34,7 +34,6 @@ Every event should conceptually have: - `kind` - `spaceLayer` - `systemId?` -- `localspaceId?` - `anchorId?` - `primaryEntityKind` - `primaryEntityId` diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index 19d5856..dba77cb 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -73,7 +73,7 @@ Current state: Primary gaps: -- [`RuntimeModels.cs`](/home/jbourdon/repos/space-game/apps/backend/Simulation/RuntimeModels.cs) has no `AnchorRuntime`, `LocalspaceRuntime`, `ClaimRuntime`, or `ConstructionSiteRuntime`. +- [`RuntimeModels.cs`](/home/jbourdon/repos/space-game/apps/backend/Simulation/RuntimeModels.cs) has no first-class `AnchorRuntime` aligned with the target design, plus no fully anchor-native `ClaimRuntime` or `ConstructionSiteRuntime`. - [`ScenarioLoader.cs`](/home/jbourdon/repos/space-game/apps/backend/Simulation/ScenarioLoader.cs) computes station positions directly instead of creating anchor-backed placement. - [`SimulationEngine.cs`](/home/jbourdon/repos/space-game/apps/backend/Simulation/SimulationEngine.cs) still treats travel as raw coordinate movement rather than anchor-to-anchor transit between spaces. @@ -247,7 +247,6 @@ Work: - extend [`RuntimeModels.cs`](/home/jbourdon/repos/space-game/apps/backend/Simulation/RuntimeModels.cs) with: - `AnchorRuntime` - - `LocalspaceRuntime` - `CommanderRuntime` - `ClaimRuntime` - `ConstructionSiteRuntime` @@ -262,7 +261,6 @@ Work: - add structured ship spatial state: - current space layer - current anchor - - current localspace - current transit Why first: diff --git a/docs/UNIVERSE-MODEL-MIGRATION-WORKSHEET.md b/docs/UNIVERSE-MODEL-MIGRATION-WORKSHEET.md new file mode 100644 index 0000000..94be8c5 --- /dev/null +++ b/docs/UNIVERSE-MODEL-MIGRATION-WORKSHEET.md @@ -0,0 +1,398 @@ +# Universe Model Migration Worksheet + +This worksheet is the implementation-facing companion to [UNIVERSE-MODEL.md](/home/jbourdon/repos/space-game/docs/UNIVERSE-MODEL.md). + +It exists to drive the migration from the current runtime model to the target spatial model without turning the work into a blind rewrite. + +This is not a new design authority. If this worksheet conflicts with [UNIVERSE-MODEL.md](/home/jbourdon/repos/space-game/docs/UNIVERSE-MODEL.md), the universe model wins. + +## Goal + +Move the simulation and viewer from the current flatter `system + coordinates + node/celestial overlays` model to: + +- `system` +- `anchor` +- `localspace` as the tactical space around an anchor +- ships and constructions living at one anchor +- intra-system travel represented as anchor-to-anchor warp transit + +## Scope + +### Required + +- Introduce first-class `Anchor` runtime concepts. +- Treat `localspace` as the tactical space around an anchor, not a separately identified entity. +- Rebind ships, stations, claims, construction sites, and resource nodes to anchors. +- Make intra-system travel anchor-to-anchor instead of raw free coordinate travel. +- Expose anchor-based spatial truth in backend contracts. +- Update the viewer to consume anchors as the primary spatial model. + +### Recommended + +- Preserve current authored content and scenario data where possible. +- Migrate incrementally behind compatibility adapters instead of a big-bang rewrite. +- Keep galaxy/system/local presentation working throughout the migration. +- Prefer additive contract changes first, then remove old fields once the stack is stable. +- Make every compatibility bridge loud, temporary, and easy to delete. + +### Optional + +- Rename every old `node` term immediately. +- Rework the full event streaming model during the first spatial pass. +- Rebuild AI/commander architecture in the same pass. + +## Current Reality + +The codebase already has partial pieces of the target model: + +- celestials and Lagrange points exist +- resource nodes already behave like anchored locations +- ships already carry transit and space-layer state +- claims, construction sites, market orders, and policies already exist +- the viewer already has galaxy/system/local presentation logic + +The real problem is that these are still layered on top of a flatter simulation core. + +## Main Gaps + +### 1. No First-Class Anchor Entity + +Current code spreads the concept across: + +- `CelestialRuntime` +- `ResourceNodeRuntime` +- `SystemId` +- raw positions +- `CurrentCelestialId` +- `DestinationNodeId` + +This is the biggest structural gap. + +### 2. Stations And Construction Are Still Celestial-Centric + +Current contracts and runtime bind station-like structures to `CelestialId`. + +That does not match the target model where: + +- anchors are generic +- not all anchors are celestials +- construction happens at valid construction anchors + +### 3. Movement Truth Is Still Coordinate-First + +Ships still fundamentally operate through: + +- local positions +- target positions +- system IDs + +Transit exists, but the simulation still thinks in free coordinates first. + +The target model wants: + +- localspace movement inside an anchor-owned tactical bubble +- explicit anchor-to-anchor warp state inside a system + +### 4. Viewer Contracts Still Mirror The Old World + +The viewer still consumes: + +- systems +- celestials +- resource nodes +- stations +- ships + +It does not consume: + +- anchors +- localspaces +- anchor topology as the primary graph + +### 5. Localspace Is Not Yet The Simulation Boundary + +The docs assume localspace is the natural tactical partition. + +The code still treats the system as the practical runtime container, with local context layered on top. + +### 6. Units And Coordinate Separation Are Not Explicit Enough + +The target model assumes separate spatial units by layer: + +- galaxy in `ly` +- system in `AU` +- localspace in `m` and `m/s` + +The codebase currently mixes spatial concerns more freely than the target model allows. + +That creates risk of accidental cross-layer coordinate coupling. + +## Migration Strategy + +Do this in seams. + +Do not try to land the whole universe model in one rewrite. + +## Units And Coordinate Rules + +The migration must preserve separate native units by layer. + +### Required + +- Galaxy space uses `ly`. +- System space uses `AU`. +- Localspace uses `m` and `m/s`. +- Do not introduce a universal shared coordinate model spanning all layers. +- Cross-layer movement should use references and travel state, not coordinate projection. + +### Recommended + +- Keep unit-specific types or field names obvious in code and contracts. +- Keep conversion logic local to presentation helpers when a client animation needs it. +- Treat viewer zoom transitions as presentation-only effects. + +### Disallowed + +- Treating localspace offsets as meaningful system-space coordinates. +- Treating system-space offsets as meaningful galaxy coordinates. +- Building migration helpers that silently convert all positions into one synthetic global frame. + +## Compatibility Rules + +Compatibility bridges are allowed only as explicit migration tools. + +They must not become silent permanent architecture. + +### Required + +- Every compatibility field, mapper, and adapter must be clearly marked. +- In C#, use `[Obsolete]` with a concrete migration reason when possible. +- In TypeScript/Vue, use an explicit `OBSOLETE` or `COMPATIBILITY BRIDGE` comment. +- Compatibility names should be obvious: + - `Legacy...` + - `Compat...` + - `...CompatibilityAdapter` +- Compatibility code should stay at seams: + - contracts + - mapping + - serialization + - viewer ingestion + +### Recommended + +- Avoid compatibility logic in the core simulation path unless there is no safer seam. +- Every compatibility bridge should have a removal condition. +- When a compatibility bridge stops being necessary, remove it in the same migration branch if practical. + +### Disallowed + +- Silent fallback fields with no marker. +- Compatibility helpers with neutral names that look permanent. +- New feature work that depends on deprecated spatial fields without an explicit exception. + +## Compatibility Inventory + +This section should remain in the worksheet during the migration and be kept current. + +Each entry should be removed from this list when the compatibility bridge is removed from the codebase. + +| Status | Area | Compatibility Item | Reason | Removal Condition | +| --- | --- | --- | --- | --- | +| Planned | Backend contracts | Legacy `CelestialId` placement fields alongside `anchorId` | Preserve contract compatibility while moving structures and ships to anchor-based placement truth | Remove once backend and viewer both consume anchor placement directly | +| Planned | Backend ship state | Legacy `DestinationNodeId` / node-based transit naming during anchor migration | Preserve existing travel wiring while renaming and rebinding spatial state | Remove once runtime and contracts use anchor terminology end-to-end | +| Planned | Viewer ingestion | Compatibility mapping from legacy world snapshot fields into anchor-based view models | Allow incremental frontend migration without blocking backend progress | Remove once viewer contracts expose anchors as primary data | + +## Phase 1. Stabilize Vocabulary + +### Objective + +Introduce the target terms and IDs without breaking current gameplay. + +### Required + +- Add runtime `Anchor` models. +- Add contract snapshots/deltas for anchors. +- Add `anchorId` to: + - ships + - stations + - claims + - construction sites + - resource nodes +- Keep existing `CelestialId` and `NodeId` compatibility fields temporarily where needed. + +### Success Criteria + +- world snapshot can describe anchors directly +- old code still runs through compatibility mapping + +## Phase 2. Make Scenario Loading Anchor-First + +### Objective + +Make scenario/spatial generation create anchors as first-class data. + +### Required + +- Treat stars, planets, moons, Lagrange points, and resource nodes as anchor-generation inputs. +- Define the localspace around each anchor. +- Stop treating station placement as a direct system-coordinate choice. +- Resolve starter stations and spawned stations through valid anchors. + +### Recommended + +- Preserve `planetIndex` and `lagrangeSide` authored hints by translating them into anchor selection. + +### Success Criteria + +- every meaningful location is represented as an anchor +- every anchor has a localspace around it +- station spawn/founding resolves to an anchor, not a raw point + +## Phase 3. Rebind Structures And Sites + +### Objective + +Make infrastructure belong to anchors instead of generic system/celestial placement. + +### Required + +- Stations reference `anchorId`. +- Claims reference `anchorId`. +- Construction sites reference `anchorId`. +- Resource nodes reference `anchorId`. + +### Recommended + +- Keep `CelestialId` only as a derived convenience when the anchor is a celestial. + +### Success Criteria + +- no structure requires `CelestialId` as its primary placement key + +## Phase 4. Replace Free Intra-System Travel + +### Objective + +Make intra-system travel obey the universe model. + +### Required + +- Ships in tactical state belong to one anchor's localspace. +- Ships leaving a localspace enter explicit warp transit. +- Transit stores: + - origin anchor + - destination anchor + - started at + - arrival due at + - progress +- Arrival resolves at the destination anchor. + +### Recommended + +- Keep current vector movement only for local tactical motion. + +### Success Criteria + +- ships no longer “just move across the whole system” as the primary truth +- warp is anchor-to-anchor by model, not just by UI + +## Phase 5. Update Viewer Contracts + +### Objective + +Expose the new world truth cleanly to the frontend. + +### Required + +- Add anchor snapshots/deltas. +- Update ship snapshots to reference anchor-based state explicitly. +- Update station/claim/construction snapshots similarly. + +### Recommended + +- Keep a short compatibility window where old viewer fields still exist. + +### Success Criteria + +- the viewer no longer has to infer the world model from mixed legacy fields + +## Phase 6. Update Viewer Presentation + +### Objective + +Make the viewer's tactical style align with the new simulation model. + +### Required + +- System view uses anchors as the primary navigable graph. +- Local view resolves the localspace around one anchor. +- Ships in warp display as transit-state entities between anchors. +- Construction and claims render at valid anchors. + +### Recommended + +- Keep a tactical-style presentation; do not regress into cinematic free-flight assumptions. + +### Success Criteria + +- viewer hierarchy matches `galaxy -> system -> localspace` + +## What Can Stay + +These areas are worth preserving: + +- data-driven item/module/recipe definitions +- current snapshot/delta transport pattern +- current tactical-style visual direction +- current claims/construction/policy/market-order runtime concepts +- current player onboarding and per-player faction work + +## What Must Change First + +If implementation starts immediately, start here: + +1. add `Anchor` runtime models +2. add backend contracts for them +3. make `SpatialBuilder` produce them +4. add `anchorId` to ships and structures +5. only then refactor movement and viewer logic + +This is the smallest seam that changes the model without exploding the whole codebase. + +## Risks + +### High Risk + +- changing movement and placement truth at the same time +- trying to rename everything in one pass +- mixing commander/AI refactors into the first spatial migration + +### Medium Risk + +- stale viewer assumptions around `systemId + celestialId` +- hidden GM/player tooling that assumes node/celestial placement +- compatibility bugs during contract overlap + +### Lower Risk + +- doc drift, now that `UNIVERSE-MODEL.md` is canonical + +## Non-Goals For The First Migration Pass + +- full commander architecture rewrite +- full event streaming redesign +- full economy redesign +- sovereignty redesign +- fleet hierarchy implementation + +Those systems should adapt to the new spatial model, not block it. + +## Exit Condition + +This worksheet is complete when the codebase can truthfully say: + +- every meaningful place in a system is an anchor +- every anchor has a localspace around it +- ships and constructions live at anchors +- intra-system travel is anchor-to-anchor warp +- the viewer consumes anchors directly diff --git a/docs/UNIVERSE-MODEL.md b/docs/UNIVERSE-MODEL.md index 0a9ef64..977c00c 100644 --- a/docs/UNIVERSE-MODEL.md +++ b/docs/UNIVERSE-MODEL.md @@ -8,7 +8,7 @@ It is the canonical reference for: - solar systems - celestials - anchors -- localspaces +- localspaces as the tactical space around anchors - ship and station placement - intra-system travel - inter-system travel @@ -27,14 +27,13 @@ The structure can be understood as a tree: - the galaxy contains solar systems - each solar system contains celestials and other derived locations - each meaningful location is an anchor -- each anchor owns one localspace +- each anchor has a localspace around it The intended structure is: 1. `galaxy` 2. `solar system` 3. `anchor` -4. `localspace` Ships and stations do not live in arbitrary free-floating "system local space". @@ -99,7 +98,7 @@ Systems remain important for: ## Anchors -An anchor is a meaningful object in a system that owns a localspace. +An anchor is a meaningful object in a system. Anchors are first-class world entities. @@ -120,7 +119,7 @@ Each anchor should have: - an anchor type - a position in system space - optional orbital metadata -- an associated localspace definition +- a localspace around it - optional parent/child relationships Examples: @@ -131,7 +130,7 @@ Examples: - a resource node is an anchor but not a celestial - a Lagrange point can be the child of a moon, which is the child of a planet, which is the child of a star -Every anchor has exactly one localspace. +Every anchor has exactly one localspace around it. ## Celestials @@ -147,9 +146,9 @@ Celestials exist for three reasons: 1. they structure the solar system visually and strategically 2. they define orbital relationships -3. they provide valid anchors for localspaces and derived locations such as Lagrange points +3. they provide valid anchors and derived locations such as Lagrange points -Every star, planet, and moon gets a localspace. +Every star, planet, and moon has a localspace around it. Not all anchors are celestials, but all celestials are anchors. @@ -165,7 +164,7 @@ Initial assumptions: - major orbitals can expose `L1` through `L5` - each exposed Lagrange point is its own anchor -- each exposed Lagrange point has its own localspace +- each exposed Lagrange point has its own localspace around it - Lagrange points are valid construction sites For now, all five may exist for supported orbitals, but the intended direction is that only major planets should necessarily expose all five. @@ -186,7 +185,7 @@ That means a resource node can have: - a stable identity - a place in a solar system -- its own localspace +- its own localspace around it This is desirable because it allows resources to exist anywhere meaningful in a system while still fitting the anchored localspace model. @@ -212,7 +211,7 @@ Use: - `localspace` -Each localspace belongs to exactly one anchor. +Each localspace is the tactical space around exactly one anchor. Examples: @@ -237,12 +236,12 @@ Ships and constructions do not exist directly in system space. They exist in one ## Ship Placement -A ship always belongs to exactly one localspace unless it is actively transitioning between anchors. +A ship always belongs to exactly one anchor unless it is actively transitioning between anchors. Normal ship state should be one of: -- in a localspace -- traveling between localspaces in the same system +- at an anchor +- traveling between anchors in the same system - traveling between systems Inside a localspace, ships use tactical movement with thrusters. @@ -444,6 +443,82 @@ Localspace view should show: The viewer should not imply that the full solar system is one continuous local battlefield. +Viewer zoom transitions are a client-side presentation effect. + +That means: + +- zooming from galaxy to system does not imply one shared coordinate space +- zooming from system to localspace does not imply one shared coordinate space +- the client may animate or blend between views for readability +- those effects do not define simulation truth + +## Scales And Units + +Each spatial layer owns its own units. + +Those units should be native to that layer, not projections of one universal master coordinate system. + +### Galaxy + +The galaxy layer uses: + +- `light-years` + +This is the scale for: + +- system positions +- inter-system distances +- strategic map layout + +### System + +The system layer uses: + +- `AU` + +This is the scale for: + +- anchor positions inside a system +- orbital relationships +- intra-system routing and warp travel + +Variation at localspace scale is intentionally insignificant at this layer. + +### Localspace + +The localspace layer uses: + +- `meters` +- `m/s` + +This is the scale for: + +- tactical movement +- combat +- docking +- mining +- construction + +Variation at system scale is intentionally insignificant at this layer. + +## Cross-Layer Rule + +The simulation should not try to preserve one continuous coordinate frame across galaxy, system, and localspace. + +Cross-layer relationships should be modeled through: + +- containment +- references +- travel state + +Not through: + +- universal coordinate conversion +- raw projection of localspace offsets into system space +- raw projection of system offsets into galaxy space + +The viewer may animate transitions between layers, but that is presentation only. It does not mean the simulation uses one continuous spatial frame. + ## Ownership And Sovereignty Ownership and sovereignty should primarily be tracked at system level. @@ -451,7 +526,7 @@ Ownership and sovereignty should primarily be tracked at system level. This is not fully defined yet, but the current design direction is: - systems are the main sovereignty unit -- localspaces and constructions exist inside systems +- anchors and constructions exist inside systems - local conflicts and control still matter tactically ## Simulation Implications @@ -466,7 +541,7 @@ This model supports: It also gives a cleaner authority boundary for later scaling: -- one localspace can become one simulation partition +- one anchor can become one tactical simulation partition - one system can remain a higher-level strategic container This supports: @@ -493,8 +568,8 @@ Until the implementation is updated, the following terms should be used consiste - `galaxy`: the top-level strategic star map - `system`: the solar system container - `celestial`: star, planet, or moon -- `anchor`: anything that owns a localspace -- `localspace`: the tactical simulation bubble attached to one anchor +- `anchor`: a meaningful location in a system and the primary tactical simulation container +- `localspace`: the tactical simulation space around an anchor, not a separately identified entity - `intra-system warp`: movement between anchors in the same system - `inter-system FTL`: movement between systems