Architecture overview (5.0)
Mental model for GridBuilding 5.0: node-first integration, injector/container era, and state-first wiring.
5.0 is best understood as a node-first plugin with a composition-container / injector integration style.
Boundary (5.0)
- Godot nodes + scripts
- Own most runtime behavior.
- Public API is primarily node exports + signals.
- Handle keyboard/mouse input through Godot’s input system.
- Systems
- Manage all input and functionality except keyboard/mouse input.
- Process building, manipulation, targeting, and placement logic.
- Coordinate state changes and workflow orchestration.
- Composition container + injector
- Wiring layer that assigns settings/services/state into nodes.
- State-first coordination
- All signals are delivered through state objects which also manage the active data.
- State objects act as both data containers and signal emitters.
- 5.0 does not separate event payloads from state management.
High-level shape
| |
What 5.0 optimized for
- Fast adoption: add nodes to a scene, connect signals, configure exports.
- Direct debuggability in the editor: follow node references in the inspector.
- Clear input separation: keyboard/mouse handled by Godot, building logic by systems.
Input handling in 5.0
Keyboard/Mouse Input (Godot Nodes)
- Handled through Godot’s standard input system (
_input,_unhandled_input) - Processed by scene nodes using
Input.is_action_pressed() - Converted to system calls (e.g.,
building_system.start_placement()) - UI elements handle their own input through Godot controls
Building/Manipulation Input (Systems)
- BuildingSystem: Processes placement requests, validation, and execution
- ManipulationSystem: Handles object selection, movement, and deletion
- GridTargetingSystem: Manages grid targeting and coordinate conversion
- IndicatorManager: Controls visual feedback and preview indicators
Input Flow Example
| |
This separation allows:
- Standard Godot input mapping and customization
- Clean testing of system logic without input handling
- Reusable building logic across different input schemes
- Easy integration with different UI frameworks
State Objects in 5.0
How 5.0 State Objects Work
In 5.0, state objects serve as both data containers and signal emitters:
| |
Signal Consumption Pattern
| |
Benefits of 5.0 Approach
- Simple to understand: State and signals in one place
- Direct access: Listeners can read any state property
- Immediate consistency: State changes and signals happen together
- Easy debugging: State objects are inspectable in the debugger
Limitations of 5.0 Approach
- Tight coupling: Listeners depend on state object structure
- Testing complexity: Need to mock entire state objects
- Privacy concerns: All state data is publicly accessible
- Signal payload ambiguity: Unclear what data the signal carries
What 5.0 did not standardize (later improved in 5.1/6.0)
- A strict, explicit split between:
- service-owned state
- event payloads
- diagnostics snapshots
Signal Delivery: 5.0 vs 5.1/6.0
5.0 Approach - State Objects as Signal Emitters:
| |
5.1/6.0 Approach - Separated Concerns:
| |
Key Differences
5.0 Pattern:
- State objects are public and emit signals
- Signals carry references to state objects
- Listeners access live state directly
- No separation between data and events
5.1/6.0 Pattern:
- Internal state stays private to services
- Event bus delivers EventData payloads
- Snapshot objects provide diagnostic access
- Clear separation between state, events, and diagnostics
5.1/6.0 improve this by introducing a clearer boundary where:
- signals/events carry small payload objects (EventData)
- snapshots exist for diagnostics/tests
- internal state stays private to services
- event bus/presenter patterns coordinate communication
5.0 projects typically wire GridBuilding through a composition container and an injector pattern.
Critical Integration: All 5.0 systems require a properly configured LevelContext to bind grid operations to specific TileMapLayers and object containers. Without LevelContext, targeting and placement systems will not function.
The intent (5.0)
- Centralize dependency wiring (settings, state, references) so scene nodes do not hand-wire everything.
- Allow test environments to stand up “the whole stack” by instantiating a known scene.
Common 5.0 wiring pattern
| |
Testing implication (5.0)
Some features require a full environment scene to exist (not a minimal unit harness).
Example from the 5.0-era manipulation architecture notes:
- Minimal collision test scenes are good for geometry/collision math.
- But manipulation workflow tests require an “all systems” environment so that:
ManipulationSystemexistsManipulationParentexists- targeting/building/indicator systems are present
This is one of the reasons the later 5.1/6.0 architecture tries to push more logic into testable services and shrink the engine glue surface.