Dependency Injection System
Version boundary (5.1 vs 6.0)
- GridPlacement 5.1 (GDScript):
GBCompositionContainer+GBInjectorSystemare the primary integration pattern. - GridPlacement 6.0 (C#): the canonical composition model is service-based (service registry + user scopes). Use
GPUserScopeRoot(Godot) +ServiceRegistry(Core) for new integrations.
This page is retained primarily for maintaining or migrating legacy 5.1 GDScript-era DI. For 6.0 projects, prefer the service/adapters guides and the Godot-facing 6.0 composition root patterns.
For clarity:
- The 6.0 (C#) integration point is
ServiceRegistry(see the section above) and the Godot-facing entry point isGPUserScopeRoot. - The 5.1 (GDScript) injector model is documented below for legacy maintenance and migration only.
6.0 game integration (what you actually integrate with)
Integration point (Core)
In GridPlacement 6.0, the core-side integration point is ServiceRegistry.
- The registry is where your game registers its own services (identity, saving, audio, analytics, other plugins).
- GridPlacement registers its core services and workflow services into that same registry.
- Your gameplay code resolves what it needs from the registry (either pure services or a workflow bridge).
What “workflows” are in 6.0
In 6.0, “workflow” types are also services that live in the registry.
- Workflow adapters (e.g.
IPlacementWorkflowAdapter) are the stable game-facing contract for “what happens next”. - Workflow bridges (Godot) are optional wrappers that translate engine types and expose a Godot-friendly surface.
- Workflow factories are composition helpers used during registration. Your game typically should not depend on them.
Godot integration point (engine)
In Godot, GPUserScopeRoot is a convenient Node composition root that:
- ensures a
ServiceRegistryexists - registers GridPlacement services/workflows via modules
- optionally configures input routing
Your game can either:
- Use
GPUserScopeRootas-is (fastest path) - Or use a game-owned composition route that registers GridPlacement modules into a registry your game owns.
Guideline: your gameplay code should depend on the registry (or resolved services), not on GPUserScopeRoot.
Custom composition route (recommended for real games)
Each game should have a single, explicit composition route.
This is the layer your codebase owns (often a GameScopeRoot, CompositionRoot, or similar). It should be responsible for:
- Creating the
ServiceRegistry - Registering game ports (identity/session, save/load, audio, telemetry)
- Registering plugin modules (GridPlacement services/workflows)
- Exposing only resolved services/adapters to the rest of your game
Recommended pattern:
- Create a
ServiceRegistry - Register game-wide dependencies (identity/session, save/load, audio, etc.)
- Register GridPlacement core services (Godot module)
- Register GridPlacement workflow layer (Godot module)
- Resolve the workflow bridge/adapter from the registry and bind it to your gameplay/UI
Avoid making unrelated gameplay systems call GPUserScopeRoot.Configure(...) directly. If you are not instantiating GPUserScopeRoot in your actual game scene tree, then it is not a good public integration surface.
GPUserScopeRoot.Configure(registry) exists for advanced composition/testing scenarios where you are using GPUserScopeRoot, but want the registry to be host-owned (for example in integration tests).
Rule of thumb:
- If you want pure logic: resolve the core service interfaces.
- If you want gameplay orchestration (select → validate → execute) with fewer moving parts: resolve the workflow bridge/adapter.
Host-provided services (ports)
GridPlacement does not require you to implement a single “registration interface”.
Instead, the integration seam is:
- Your game registers implementations of specific interfaces (“ports”) into
ServiceRegistry. - GridPlacement resolves those interfaces at runtime.
Common ports in 6.0:
IGridBuildingSession- Required by
PlacementWorkflowAdapterto support per-user placement (GPUserId→IUserScope). - If you are using
GPUserScopeRoot, the shipped Godot services module provides a minimal default session implementation. - If your game already has its own session/identity system, register your own
IGridBuildingSessionbefore GridPlacement workflow registration.
- Required by
IUserScope(returned byIGridBuildingSession.GetUserScope)- Represents per-user lifetime and identity.
ICoreInputActionSettingsProvider(Godot)- Optional. If provided,
GPUserScopeRootuses it to resolveCoreInputActionSettings. - Otherwise,
GPUserScopeRootwill register a default provider from its exported settings.
- Optional. If provided,
Rule: register game-owned ports first, then call GridPlacement module registration.
Related (6.0):
service_architecture_and_adapters.md(service + adapter boundary)core-godot-integration.md(Godot/C# integration entry points)
5.1 legacy injector DI (GDScript)
Everything below this heading applies to the 5.1 GDScript injector pattern (GBCompositionContainer + GBInjectorSystem).
In 6.0, this model is replaced by service-based composition (ServiceRegistry + user scopes + adapters). If you are integrating 6.0 C#, you can ignore legacy injector details.
5.1 architecture (TL;DR)
- Composition root: a
GBCompositionContainerresource acts as the “container” for configuration + cached runtime wiring. - Injection mechanism:
GBInjectorSystemwalks a subtree and callsresolve_gb_dependencies(container)on nodes. - Primary reason it existed: multi-context support (multiple independent grid-building instances) and testability without global singletons.
Canonical legacy references (5.1)
docs/content/grid-placement/v5-1/guides/runtime-chain.mddocs/content/grid-placement/v5-1/guides/user-scope-root-and-lifetime.md
Injector deep-dive (legacy)
The 5.1 injector model is the same family of architecture as 5.0. If you need the full injector/GBCompositionContainer documentation (contracts, scoping, validation), use the legacy v5.0 guide:
/v5-0/guides/dependency_injection/