Runtime Chain: Nodes → Workflows → Services → State (5.1 → 6.0)
The most useful way to understand or debug GridPlacement is to follow a chain from the Godot-facing entrypoint down to the backend logic.
This page documents that chain for 5.1 (GDScript) and shows how the same mental model maps to 6.0 (C#).
Boundary
- Godot layer (engine/UI glue)
- Nodes, scenes, visuals, input, signals.
- Allowed to reference Godot types.
- Backend logic (workflow/services/state)
- The place where placement/manipulation rules live.
- In 6.0, this is the C# Core DLL (engine-agnostic).
The 5.1 chain (GDScript)
In 5.1, you will typically see a GDScript node call into a workflow/controller script that then calls deeper logic.
| |
5.1 input routing (no binding layer)
In the 5.1 GDScript track, the input boundary is intentionally direct:
| |
Rules:
- Adapters call orchestrators directly. There is no separate “binding” layer in 5.1.
- TargetingService2D is injected into adapters as the authoritative resolver for:
- mouse position → targeting snapshot
- current target → Node2D
- Effects are applied by workflow/services; adapters only translate input into workflow calls.
5.1 output effects (GBEffectApplier)
5.1 uses an explicit output/effects model to keep the workflow layer testable and to keep scene mutation in one place.
| |
Notes:
GBEffectApplieris not a C#-style “binding layer” for intent → backend services. In 5.1, adapters already call workflow orchestrators directly.GBEffectApplierexists to interpretGBOrchestratorEffectentries and broadcast them as signals; scene nodes decide how to render/apply them.
How to use this chain in practice
- Start at the node or autoload your gameplay code calls.
- Identify the workflow adapter it delegates to.
- Trace the call into the backend workflow.
- Identify the service(s) that actually execute the operation.
- Finally, identify which state object(s) are mutated/read.
Concrete examples from the 5.1 demo (evidence-based)
These examples are intended to help you follow the chain in real files.
Example A: world boot → container → registry → mode
File:
demos/grid_building_dev/godot/demos/shared/world/world.gd
Chain:
| |
This is a canonical example of the 5.1 composition-container / registry flow: even when you start from a normal scene node, you quickly land in the container/registry to reach backend services.
Example B: placement lifecycle test → BuildingSystem → PlacementService / TargetingService2D
File:
demos/grid_building_dev/godot/test/grid_building/systems/placement/integration/placement_lifecycle_tests.gd
Chain (high-level):
| |
This is a concrete example of why the “chain” model is useful: even when a high-level system node drives the flow, the authoritative lifecycle invariants (preview cleanup, collision exclusions) are enforced by backend services.
Example C: container → workflow factory → placement workflow adapter → placement workflow orchestrator
File:
demos/grid_building_dev/godot/addons/grid_building/resources/gb_composition_container.gd
Chain (high-level):
| |
Key point:
- The orchestrator now depends on a workflow adapter API, not on raw services.
- This keeps service wiring inside the factory/composition layer, and keeps the orchestrator focused on workflow state + decision logic.
The 6.0 chain (C#) you should be targeting
The 6.0 design makes the chain more explicit and consistent.
| |
For the canonical explanation, see:
../../v6-0/guides/service_architecture_and_adapters/../../v6-0/guides/core-godot-integration/
Ports / adapters (what to look for)
In 6.0, the “workflow boundary” is intentionally represented as a port interface, for example:
IPlacementWorkflowAdapter
…and a Core implementation:
PlacementWorkflowAdapter
Godot nodes should be thin adapters: they convert Godot types (like Vector2I) to Core value types and call the workflow port.
Identity & lifetime (why user scope root exists)
6.0 treats identity and lifetime as first-class integration concerns.
| |
Lifetime rules of thumb
- Per-project: composition root / service registry.
- Per-session: “current play session” scope (save/load boundary).
- Per-user: identity-specific scope for inputs, ownership, and persistence.
Testing alignment
- Prefer Core unit tests for deterministic logic.
- Prefer Core integration tests for wiring and workflow orchestration.
- Use Godot tests only for:
- resource loading
- input translation
- signal hookups / adapter behavior
If you are working on 6.0 wiring, the canonical Core test suite to extend is:
plugins/gameplay/GridPlacement/cs/Core/Tests/Core/GridBuilding.Core.Tests/PlacementWorkflowOrchestratorIntegrationTests.cs
What this page does NOT assert
- It does not guarantee the exact class names in 5.1 (GDScript) are stable.
- It does not promise a compatibility bridge between 5.1 and 6.0 at runtime.
- It does define the recommended debugging mental model and the forward architecture target.
Evolution: 5.0 → 5.1 → 6.0 (clean architecture)
This section explains how the architecture evolved so you can interpret older docs and older code correctly.
5.0: service-based principles (direction established)
The shipped 5.0.0 line is best understood as a composition-container / injector era.
- Composition was typically handled through
GBCompositionContainerandGBInjectorSystempatterns.
In other words: 5.0 was not the finalized “ports + adapters” service architecture yet.
Reference (legacy integration pattern):
../../v5-0/csharp-state-integration/
Note on docs:
../../v5-0/service-based-architecture/should be treated as a design direction / post-hoc architecture doc, not a guarantee that 5.0.0 shipped that fully in its runtime wiring.
What 5.0.0 did not standardize yet:
- A stable, explicit “workflow port” boundary (a single place to call that orchestrates services)
- Explicit identity/lifetime seams (project/session/user)
- A strict rule that Godot nodes only speak to narrow workflow ports (instead of a broad bridge/container surface)
5.1: stabilization + a traceable runtime chain
The 5.1 line keeps the plugin stable but makes it easier to reason about the runtime by encouraging a traceable chain:
| |
What got better in 5.1:
- A more repeatable “start from the node and trace downward” debugging workflow
- Clearer separation between “public Node API” and internal helpers
- A documented “do not break public API casually” stability contract
What is still not fully finalized in 5.1:
- The boundary is still primarily Node-shaped (public APIs are nodes, dictionaries, signals)
- Identity/lifetime is often still implicit (autoloads / singleton roots)
Naming + folder layout (5.1)
- Brand (docs): GridPlacement (5.1+)
- Godot addon folder:
res://addons/grid_building(kept for backward compatibility)
6.0: clean architecture final form (ports + adapters + explicit lifetimes)
6.0 finalizes the architecture by making the boundaries explicit and enforceable:
- Ports (Core interfaces) define the integration surface (example:
IPlacementWorkflowAdapter). - Adapters (engine layer) are thin nodes/bridges that convert Godot types to Core value types.
- Composition root + registry makes service lifetime explicit.
- User/session seams are first-class so multi-user or per-owner behaviors are testable.
Canonical docs:
../../v6-0/guides/service_architecture_and_adapters/../../v6-0/guides/core-godot-integration/
Rule of thumb:
- In 5.1 you can get work done by calling nodes.
- In 6.0 you keep things maintainable by tracing everything through:
- engine adapters → workflow ports → services → state.
Testing: where each behavior should live
This is the recommended split when you are trying to keep 5.1 stable but move architecture toward 6.0.
Core unit tests (fast, deterministic)
Use when you are proving:
- validation rules
- coordinate conversions (Core value types)
- state transition logic
Core integration tests (preferred for workflow wiring)
Use when you are proving:
- workflow orchestration calls the right internal components
- per-user session support behaves correctly
- readiness checks gate placement/manipulation correctly
Reference suite to extend:
plugins/gameplay/GridPlacement/cs/Core/Tests/Core/GridBuilding.Core.Tests/PlacementWorkflowOrchestratorIntegrationTests.cs
Godot tests (glue only)
Use only when you are proving:
- input translation (
InputEvent-> Core input events) - signal hookups / adapter nodes emitting the right Godot signals
- resource loading (catalogs, settings resources)
Avoid using Godot tests for core placement logic when a Core test is possible.