Composition & Injection

What the Container Actually Owns

GBCompositionContainer is the canonical composition root for one runtime grid-building context. It exposes:

  • config — exported GBConfig property (direct property, not a helper method)
  • get_settings() — returns GBSettings
  • get_templates() — returns GBTemplates
  • get_actions() — returns GBActions
  • get_logger() — returns GBLogger
  • get_contexts() — returns GBContexts
  • get_states() — returns GBStates

Use one container per active runtime context.


What the Injector Actually Does

GBInjectorSystem:

  • Requires composition_container.
  • Injects any node that implements resolve_gb_dependencies(...).
  • Performs initial recursive injection.
  • Injects newly added nodes inside the injection scope.
  • Runs editor validation automatically.

Important runtime detail:

  • The injector helps with wiring.
  • Runtime validation is only meaningful once GBLevelContext and GBOwner have populated the contexts/states your systems depend on.

Canonical Scene Wiring

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
MainLevel
  -> World
      -> TileMapLayer
      -> ObjectsRoot
      -> GBLevelContext
  -> Systems
      -> GBInjectorSystem
      -> BuildingSystem
      -> GridTargetingSystem
      -> ManipulationSystem
  -> GridPositioner2D
      -> TargetingShapeCast2D
      -> ManipulationParent
  -> Player
      -> GBOwner
  -> UI

Required Scene Contracts

  • GBInjectorSystem.composition_container must be assigned.
  • GBLevelContext.target_map must be assigned.
  • GBLevelContext.objects_parent must be assigned.
  • GBOwner.owner_root must be assigned.
  • Any node that needs plugin dependencies must implement resolve_gb_dependencies(container: GBCompositionContainer).

What resolve_gb_dependencies(...) Means

There is no formal interface keyword here. The injector simply checks whether a node has the method and, if so, calls it.

Typical runtime patterns:

  • GBOwner.resolve_gb_dependencies(...) registers the active owner into owner context.
  • GBLevelContext.resolve_gb_dependencies(...) applies level maps and placement parent into the states.
  • UI and helper nodes read state/context references from the container.
  • Systems register themselves via GBSystemsContext.set_system() — this is separate from the injection pattern.

1
2
3
4
5
6
@onready var injector: GBInjectorSystem = $Systems/GBInjectorSystem

func _ready() -> void:
    var container: GBCompositionContainer = preload("res://path/to/my_container.tres")
    injector.composition_container = container
    injector.run_validation()

What Should Be in the Container Resource

  • config.settings.building
  • config.settings.manipulation
  • config.settings.targeting
  • config.settings.placement_rules
  • config.templates
  • config.actions

\n5.0.4 update: Base placement_rules should reference external .tres files, not embedded subresources. See Web Export Guide for why this matters in exported builds.


Example Injection Target

1
2
3
4
5
6
7
extends Node2D

func resolve_gb_dependencies(container: GBCompositionContainer) -> void:
    var states: GBStates = container.get_states()
    var systems: GBSystemsContext = container.get_systems_context()
    var logger: GBLogger = container.get_logger()
    var targeting_settings: GridTargetingSettings = container.get_settings().targeting

What Is Not Automatic

  • The injector does not invent a GBLevelContext for you.
  • The injector does not invent a GBOwner for you.
  • The injector does not make placement work if target_map, objects_parent, or owner wiring are missing.
  • The injector does not replace calling real system entry points like enter_build_mode(placeable).

Plugin-User Checklist

  • Create a GBCompositionContainer resource.
  • Assign a valid GBConfig.
  • Add GBInjectorSystem to your scene.
  • Assign composition_container.
  • Add GBLevelContext.
  • Assign target_map and objects_parent.
  • Add GBOwner.
  • Assign owner_root.
  • Add the systems/nodes you want to use.
  • Trigger placement through the system API or injected UI.