Project Architecture


The plugin architecture is layered to keep systems modular and testable while supporting flexible game integration.

Layer Overview

LayerContentsNotes
Core (C#)GridPlacement.Core / GridBuilding.Core services, state, validation logicEngine-agnostic. Prefer constructor injection inside Core services.
Composition (host-owned)ServiceRegistry + module registrationYour game registers ports (sessions, saving, etc.) then registers GridPlacement modules.
User ScopesIUserScope / GPUserId-keyed lifetimesEnables per-user/per-session isolation without global singletons.
Godot IntegrationGPUserScopeRoot (optional composition root), adapter nodes/bridgesGodot nodes should resolve services/adapters from the registry rather than owning composition rules.
UI & GameplayGame-owned UI and input layers calling workflow adaptersPrefer depending on workflow adapters (stable contracts) rather than concrete internals.
TestingCore unit tests + targeted Godot integration testsPush logic into Core. Keep Godot tests focused on adapter wiring and engine glue.

Dependency Injection Model

In 6.0, composition is registry-based, not injector-based.

Benefits:

  • Multitenancy (multiple users/sessions)
  • Clear test seams (swap in a fresh registry / fake ports)
  • Explicit host ownership (your game controls what gets registered and when)

If you are looking for the previous (5.1 injector-era) dependency injection model, treat these as canonical legacy references:

  • docs/content/grid-placement/v5-1/guides/runtime-chain.md
  • docs/content/grid-placement/v5-1/guides/user-scope-root-and-lifetime.md

🎯 GridTargetingState: Authoritative targeting state

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 targetmove_copy to 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() and get_active_root()

This eliminates semantic confusion and reinforces GridTargetingState as the authoritative source 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:

  1. You pick something to build: Click a placeable in the UI
  2. BuildingSystem wakes up: enter_build_mode() gets called with your choice
  3. GridPositioner2D handles targeting: Processes mouse/keyboard input to track where you’re pointing on the grid
  4. TargetingShapeCast2D detects collisions: Updates collision state based on GridPositioner2D position
  5. IndicatorManager provides live feedback: Sets up indicators that follow your cursor and show placement validity
  6. PlacementValidator checks rules: Runs tile-based rules as you move the cursor around
  7. IndicatorManager shows visual feedback: Colors/animations appear to show valid/invalid spots in real-time
  8. ManipulationSystem (optional): If enabled, lets you move/rotate the preview before placing
  9. You confirm placement: BuildingSystem.try_build() runs full validation (including non-tile rules)
  10. Object gets created: If everything checks out, your building appears in the world as a PlaceableInstance
  11. 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

  1. UI Selection → User selects placeable from UI → BuildingSystem.enter_build_mode(placeable) is called
  2. Build Mode Initialization: BuildingSystem prepares preview with selected placeable
  3. Input Processing: GridPositioner2D processes mouse/keyboard input and converts to grid coordinates
  4. Collision Detection: TargetingShapeCast2D updates collision state based on positioner position
  5. Live Validation: PlacementValidator runs tile rules, IndicatorManager shows live feedback via rule indicators
  6. Preview Manipulation: If enabled in placeable settings, ManipulationSystem can move/rotate preview instances during placement
  7. Confirmation: User confirms placement, BuildingSystem.try_build() runs full rule validation (including non-tile rules)
  8. Instantiation: If valid, BuildingSystem spawns PlaceableInstance with metadata for manipulation & save/load
  9. 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

  • docs/content/grid-placement/v5-1/guides/runtime-chain.md
  • docs/content/grid-placement/v5-1/guides/user-scope-root-and-lifetime.md

High-Level System Architecture

6.0 components (conceptual):

  • Core services: engine-agnostic placement, targeting, validation, and state logic.
  • Service registry: host-owned composition boundary (ServiceRegistry) where game ports and plugin modules are registered.
  • User scope: per-user lifetime (identity + disposable scope) used to isolate state and dependencies.
  • Adapters/bridges: small Godot-facing nodes that translate engine types and forward to Core/workflows.
  • Workflow adapters: stable game-facing orchestration contracts (select → validate → execute).

For the service/adapters boundary, see:

  • core-godot-integration.md
  • service_architecture_and_adapters.md

Last updated: 2025-08-20