Project Architecture
The plugin architecture is layered to keep systems modular and testable while supporting flexible game integration.
Layer Overview
| Layer | Contents | Notes |
|---|---|---|
| Resource Configuration | GBConfig, GBSettings, GBTemplates, GBMessages, rule resources | Editable in inspector; serialized with project |
| Composition & Injection | GBCompositionContainer, GBInjectorSystem | Provides dependency injection & lazy construction |
| Core Systems | Placement, Targeting, Building, Manipulation, Validation, Indicator | Each focuses on a single domain concern |
| State Containers | GBStates (mode, targeting, building, manipulation) | Shared by injected nodes; supports multi-context |
| Contexts | GBContexts (placement, systems, owner, level) | Encapsulate environment dependencies |
| UI & Interaction | Action bar, selection lists, info displays | Driven by states & actions resources |
| Testing Utilities | Factories, reports, test setups | Facilitate GdUnit coverage & deterministic assertions |
Dependency Injection Model
Instead of global singletons, systems resolve dependencies from the injected composition container. Benefits:
- Multitenancy (multiple players/levels)
- Clear test seams (swap in a fresh container)
- Lazy provisioning (logger/settings only built when required)
Nodes optβin via resolve_gb_dependencies pattern. See the Dependency Injection document.
π― GridTargetingState: Single Source of Truth
6.0.0 Architectural Principle: GridTargetingState is the authoritative, centralized source for what is actively targeted in the entire Grid Building System.
What it manages:
- BUILD mode: The placement preview being positioned
- MOVE mode: The manipulation copy during object manipulation
- Normal gameplay: The node detected by TargetingShapeCast2D
Why this matters:
- Consistency: All systems query the same targeting source
- Sync issues eliminated: No more state divergence between different components
- Simpler integrations: Third-party systems can rely on a single API for targeting info
- Clear responsibilities: Other systems (ManipulationState, BuildingState) focus on their domains; targeting is GridTargetingState’s job
6.0.0 API Improvement: ManipulationData was refactored to support this principle:
- Renamed
targetβmove_copyto clearly distinguish the manipulation preview from GridTargetingState’s target - Removed
ManipulationState.active_target_node(redundant with GridTargetingState) - Added safe helper methods:
get_move_copy_root()andget_active_root()
This eliminates semantic confusion and reinforces GridTargetingState as the single source of truth for targeting.
See GridTargetingState API for detailed targeting methods, Grid Targeting Guide for architectural details, and Breaking Changes - 6.0.0 for migration guidance.
How the Systems Work Together
Instead of a complex diagram, let’s walk through how the Grid Building system works in simple steps:
The Basic Flow:
- You pick something to build: Click a placeable in the UI
- BuildingSystem wakes up:
enter_build_mode()gets called with your choice - GridPositioner2D handles targeting: Processes mouse/keyboard input to track where you’re pointing on the grid
- TargetingShapeCast2D detects collisions: Updates collision state based on GridPositioner2D position
- IndicatorManager provides live feedback: Sets up indicators that follow your cursor and show placement validity
- PlacementValidator checks rules: Runs tile-based rules as you move the cursor around
- IndicatorManager shows visual feedback: Colors/animations appear to show valid/invalid spots in real-time
- ManipulationSystem (optional): If enabled, lets you move/rotate the preview before placing
- You confirm placement:
BuildingSystem.try_build()runs full validation (including non-tile rules) - Object gets created: If everything checks out, your building appears in the world as a PlaceableInstance
- ManipulationSystem (post-placement): Now you can select, move, rotate, or delete the placed object
v5.0.0 Architectural Improvements:
Clean System Boundaries:
GridPositioner2D β Pure input handling & positioning
βββ TargetingShapeCast2D β Dedicated collision detection
βββ ManipulationParent β Transform handling container
βββ IndicatorManager β Visual feedback & validation manager
β βββ RuleCheckIndicator β Individual rule indicators
β βββ RuleCheckIndicator β Individual rule indicators
βββ PreviewObject β Object being manipulated
Benefits:
- Unit testable components - Each system tested in isolation
- Composable collision strategies - Swap targeting implementations
- Eliminated race conditions - No hidden coupling between systems
- Reliable test execution - Consistent behavior in all environments
Key Points to Remember:
- BuildingSystem orchestrates the entire build workflow - from mode entry to final placement
- GridPositioner2D handles all input processing and grid coordinate conversion
- IndicatorManager manages the visual feedback system (creates and parents rule indicators)
- ManipulationParent serves as transform container for preview objects and indicators
- ManipulationSystem has two jobs: preview adjustment (if enabled) and post-placement editing
- Validation happens twice: quick tile rules during preview, full rule validation on confirmation
- Each component has a single responsibility but they work together seamlessly
Key Data Flows
- UI Selection β User selects placeable from UI β
BuildingSystem.enter_build_mode(placeable)is called - Build Mode Initialization: BuildingSystem prepares preview with selected placeable
- Input Processing: GridPositioner2D processes mouse/keyboard input and converts to grid coordinates
- Collision Detection: TargetingShapeCast2D updates collision state based on positioner position
- Live Validation: PlacementValidator runs tile rules, IndicatorManager shows live feedback via rule indicators
- Preview Manipulation: If enabled in placeable settings, ManipulationSystem can move/rotate preview instances during placement
- Confirmation: User confirms placement,
BuildingSystem.try_build()runs full rule validation (including non-tile rules) - Instantiation: If valid, BuildingSystem spawns PlaceableInstance with metadata for manipulation & save/load
- Post-Placement: ManipulationSystem handles move/rotate/delete operations on placed instances
Save / Load Considerations
PlaceableInstance holds references back to originating Placeable enabling reconstruction. Systems should avoid storing raw scene node references across sessions; rely on IDs or resource paths.
Logging & Debug Controls
GBDebugSettings gates verbosity. High verbosity surfaces:
- Injection operations
- Indicator setup summaries
- Rule validation traces (future extension)
{/* Testing Strategy moved to internal/testing_strategy.md */}
Extensibility Guidelines
- Favor composition (create a new rule resource) over conditionals inside existing rules.
- Keep resource scripts lean; complex logic belongs in systems.
- Add new UI affordances by observing states rather than polling systems directly.
Planned Evolutions
- Cross-context synchronization primitives (multiplayer scenarios).
- Performance profiling hooks (duration_ms in reports).
- Rule documentation tooling.
Core Architecture References
- Context & State β Distinguishes longβlived context objects from frequently mutating state containers; essential for understanding rule evaluation purity.
- Placement Chain β Endβtoβend flow from input to instantiated object.
- Dependency Injection β Container pattern enabling multiβtenant/testable setup.
- Placement Rules Pipeline β Validation composition & indicator generation.
High-Level System Architecture
Core Components:
- Configuration & Templates: GBConfig, GBTemplates, GBMessages
- Composition: GBCompositionContainer, GBInjectorSystem
- Core Systems: BuildingSystem, PlacementValidator, IndicatorManager, GridTargetingSystem, ManipulationSystem
- State Management: ModeState, BuildingState, ManipulationState, GridTargetingState
- UI: Selection/Action UI
Data Flow:
- UI β BuildingSystem β PlacementValidator β IndicatorManager
- GridPositioner2D β TargetingShapeCast2D β GridTargetingState
- IndicatorManager β ManipulationParent (parent/child relationship)
- Configuration β CompositionContainer β InjectorSystem β All Systems
- State components manage respective system states (targeting, building, manipulation)
- ManipulationSystem handles preview objects and post-placement instances
Last updated: 2025-08-20