docs(@projects/@magic-civilization): 🛤️ Rail-1 design — narrow the dual-model fork (cities ~done, units are the hold-out)
Verified the live city-projection path: api-gdext/city_slot.rs is a full ops module over presentation_cities (rich mc_city::City) + GdCity wraps it; CityScript is a hybrid proxy already routing to the Rust slot. So cities are largely Rust-authoritative — the GDScript residue is just the city-centre queue + placed_buildings. UNITS are the real Phase-1 hold-out (UnitScript fully GDScript-authoritative, no Rust slot). Rails: bench CityState/MapUnit and the live game are sanctioned-separate contexts (code-layering #3), so the live view must project the RICH city / a new live-unit store — NOT the bench types. Refines the Phase-1 plan accordingly. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
8c3e7b8a27
commit
081cddcab3
1 changed files with 22 additions and 3 deletions
|
|
@ -95,9 +95,28 @@ field; animation deltas / VFX (render-only, never sim state).
|
|||
### Phase 1 — Rust holds the LIVE state (the SOT flip; render-gated)
|
||||
Make `GdGameState.inner` (+ `presentation_cities`) the authoritative live state, synced on every
|
||||
mutation — i.e. route live input through `act()` so there is no GDScript-only mutation to diverge.
|
||||
Widen the bench model where the live game needs fields it lacks (unit XP, per-building queues,
|
||||
placed-buildings) so Phase-0 projections carry real live data. This is the dual-model unification
|
||||
(p3-25 step 6, p3-26 B7) generalised from cities to units.
|
||||
|
||||
**Refinement (verified 2026-06-27 — the dual-model "fork" is narrower than p3-25 framed):**
|
||||
- **CITIES are already largely Rust-authoritative.** `api-gdext/src/city_slot.rs` is a full
|
||||
operations module over `presentation_cities: Vec<Vec<mc_city::City>>` (the *rich* city: spawn,
|
||||
growth, culture, production, per-building queues, citizens, borders, yields, focus, take_damage),
|
||||
and `GdCity` (lib.rs:2056) wraps it. The GDScript `CityScript` (`city.gd`) is a **hybrid proxy** —
|
||||
`get_population`/`get_hp`/`owned_tiles` already route to the Rust slot. The GDScript-only city
|
||||
residue is small: the **city-centre `construction_queue`/`production_progress`** + `placed_buildings`
|
||||
tile positions. So city work = move that residue into `mc_city::City` + project the rich city for
|
||||
the live view (NOT "unify two city types" — `presentation_cities` IS the rich type).
|
||||
- **UNITS are the real hold-out.** `UnitScript` (`unit.gd`) is **fully GDScript-authoritative** with
|
||||
**no Rust slot parallel** (audit). There is no live Rust unit store; the bench `MapUnit` is a
|
||||
separate (self-play) context. The heavy Phase-1 lift is giving the live game a **Rust-authoritative
|
||||
unit store** (the units analogue of `presentation_cities`) so unit state (position, hp, movement,
|
||||
XP, posture) lives in Rust and the GDScript `UnitScript` becomes a proxy/view.
|
||||
- **Rails note:** the lean bench `CityState`/`MapUnit` (fast self-play) and the live game are
|
||||
*sanctioned-separate contexts* (code-layering principle 3 — different programs sharing logic
|
||||
crates, not state). So "widen the bench model" is the WRONG framing for the live view: the live
|
||||
view projects the **rich** `mc_city::City` / the new live unit store, not the bench types. The
|
||||
Phase-0 bench-`CityState`→`CityView` projection I enriched serves the headless harness; the live
|
||||
game needs a rich-City + live-unit projection. (Bench unit XP is still worth porting so the
|
||||
headless sim has veterancy — tracked separately, fork-independent.)
|
||||
|
||||
### Phase 2 — Live turn = `end_turn()` (render-gated; p3-29 steps 3-5)
|
||||
`turn_manager.end_turn()` calls `GdTurnProcessor.step(GdGameState)` once instead of the per-player
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue