diff --git a/DECISIONS.md b/DECISIONS.md index 79806a0ed..38618d324 100644 --- a/DECISIONS.md +++ b/DECISIONS.md @@ -217,6 +217,44 @@ This document tracks confirmed decisions, open questions, and rejected alternati - **Raised by:** Full team across Rounds 8-10. +### D-020: Engine and architecture selection — Godot client + Rust simulation via subprocess/IPC +- **Date:** 2026-02-09 +- **Decision:** The game uses a split architecture: **Godot 4** (GDScript) as the rendering client, **Rust** with **bevy_ecs standalone** as the simulation server. The two communicate via **subprocess/IPC** (local socket for single-player, TCP for multiplayer). **NOT via GDExtension.** +- **Architecture:** + - The Rust simulation is a standalone binary with zero Godot dependencies. It runs the ECS world, perception queries, AI, storyteller, combat — all game logic. + - The Godot client is a pure renderer: receives `ObserverSnapshot` data, draws tiles/sprites/fog, plays audio, shows UI, captures input. No game logic in GDScript. + - Single-player: Godot launches the Rust binary as a child process. Local Unix socket or localhost TCP. + - Multiplayer: Godot connects to a remote Rust server. Same protocol. The simulation binary doesn't know the difference. + - This IS the D-010 client-server architecture — literally, not simulated. +- **Serialization:** + - **MessagePack** for all client-facing communication (Rust↔Godot). Dynamic structure supports variable HUD composition driven by perception modes (D-017). Cross-language, debuggable. + - **bincode** reserved for future Rust↔Rust server-to-server sync (same binary, hot path, zero overhead). + - **protobuf** rejected — solves deployment/versioning problems we don't have, poor GDScript support. +- **Why subprocess over GDExtension:** + - Eliminates entire risk categories: gdext pre-1.0 API churn, Godot version ABI breakage, FFI thread safety (`Gd` is `!Send`), cross-boundary memory management. + - Decouples learning: build and test Rust simulation standalone, build Godot renderer standalone, connect when both work. + - Maps directly to D-010 client-server with no simulation — it IS client-server from day one. + - Either side can be upgraded, replaced, or scaled independently. + - Cost: ~1-5ms serialization latency per tick. Acceptable for a detective/strategy game, not a twitch shooter. +- **Key patterns:** + - `ObserverSnapshot`: the only data structure crossing the boundary. Contains visible entities, fog state, sound events, monologue triggers, HUD widget data. Variable shape per character build. + - `PlayerInput`: semantic actions (MoveNorth, Interact, UsePerceptionMode), not raw key events. Timestamped for deterministic processing. + - `SimBridge` trait: abstracts transport. `LocalBridge` (subprocess, channels) and `NetworkBridge` (TCP, MessagePack) implement the same interface. +- **Kill switch:** If no working prototype (character + fog + one NPC) exists by week 8 of development, pivot to pure Godot. If bridge/sync code exceeds game logic for 3 consecutive sprints, the architecture tax is too high. +- **Development sequence:** + 1. Build Rust simulation as standalone binary (testable via terminal/logs) + 2. Build Godot renderer as standalone project (hardcoded test data) + 3. Connect via MessagePack protocol +- **Project structure:** + ``` + simulation/ # Pure Rust, bevy_ecs, zero Godot deps + client/ # Godot 4 project, GDScript only + protocol/ # Shared message definitions (MessagePack schemas) + ``` +- **Evaluation reports:** `docs/architecture/eval-godot-rust-bridge.md` (Tyre), `docs/architecture/risk-godot-rust-bridge.md` (Troblum) +- **Raised by:** Team Leader (Jeroen) proposed Godot client + Rust backend. Tyre designed architecture. Troblum's risk assessment shifted integration from GDExtension to subprocess/IPC. Full team endorsed. +- **Dissent:** None. Troblum's CRITICAL risk flags on GDExtension were accepted; subprocess approach addresses them. + ### D-004: Team composition confirmed - **Date:** 2026-02-08 - **Decision:** Team of 8 agents + Team Leader. @@ -238,12 +276,7 @@ This document tracks confirmed decisions, open questions, and rejected alternati ## OPEN QUESTIONS ### Q-001: Game engine selection -- **Status:** Not yet discussed - NEXT PRIORITY -- **Options under consideration:** Godot, Bevy (Rust), custom lightweight engine, others TBD -- **Key factors:** 2D/2.5D presentation, strong event/simulation systems, UI framework quality, AI-assisted dev friendliness, Team Leader's comfort -- **Hard requirements from decisions:** Client-server friendly (D-010), chunk-based map loading (D-012), LOS shadowcasting (D-011), deterministic simulation (D-010) -- **Context update:** Rimworld-style systems-driven game. No 3D engine needed. Godot is front-runner. -- **Assigned to:** Tyre to lead discussion, full team input +- **Status:** Resolved → D-020 ### Q-002: Scope of v0.1 playable prototype - **Status:** Map spec resolved (D-014). Remaining: mechanics, characters, interactions for minimum playable build. @@ -308,6 +341,34 @@ This document tracks confirmed decisions, open questions, and rejected alternati - **Rejected:** 2026-02-08 - **Reason:** Each captures at most 40% of what's needed. Smaller modding communities, less mature tools, and none solve the core CK3+Stellaris hybrid requirement. +### R-004: Pure Bevy (Rust) — no Godot +- **Rejected:** 2026-02-09 +- **Reason:** No visual editor (level design is code-only). UI framework in flux. API breaks significantly between versions. For a solo developer who needs visual tools for hand-crafted buildings (D-014), Godot's editor is a massive productivity advantage. Bevy's ECS is used — just not its renderer. + +### R-005: Pure Godot (GDScript or C#) +- **Rejected:** 2026-02-09 +- **Reason:** Scene tree paradigm fights ECS-style simulation. Perception queries (D-017) and information boundaries (D-010) map naturally to ECS component queries, not scene tree traversal. Multi-core scaling for expanded content impossible in GDScript. Kept as kill-switch fallback if Rust architecture exceeds time budget. + +### R-006: Godot + Rust via GDExtension +- **Rejected:** 2026-02-09 +- **Reason:** gdext is pre-1.0 with breaking API changes. Godot version upgrades break GDExtension ABI. Thread safety at FFI boundary is CRITICAL risk (`Gd` is `!Send`/`!Sync`). Couples Rust and Godot learning curves. Subprocess/IPC achieves the same architecture without the FFI risk surface, and maps directly to D-010 client-server. See `docs/architecture/risk-godot-rust-bridge.md` for full analysis. + +### R-007: Godot + C++ via GDExtension +- **Rejected:** 2026-02-09 +- **Reason:** More mature bindings than gdext, but trades Rust's safety guarantees for C++ memory unsafety. No advantage over subprocess/IPC approach. Developer not experienced in C++. + +### R-008: Fyrox (pure Rust engine) +- **Rejected:** 2026-02-09 +- **Reason:** Single maintainer. ~1/50th of Godot's community. Less documentation, fewer tutorials, weaker AI training data for Claude Code. Single-maintainer risk unacceptable for multi-year project. + +### R-009: Custom framework (Rust + raylib/macroquad) +- **Rejected:** 2026-02-09 +- **Reason:** Maximum control but you build everything — tilemap rendering, camera, UI, audio, input, asset pipeline. Months before testing a mechanic. The game's hard problems are simulation, not rendering — don't reinvent the rendering wheel. + +### R-010: protobuf for client-server serialization +- **Rejected:** 2026-02-09 +- **Reason:** Schema evolution across independent deployments is a problem we don't have (one developer, client and server ship together). Poor GDScript support. Rigid schema fights dynamic HUD composition driven by perception modes (D-017). MessagePack's schema-optional nature fits better. + --- -*Document maintained by SCRIBE. Last updated: 2026-02-08* +*Document maintained by QATUX. Last updated: 2026-02-09*