Composition + injection (5.0.3)

5.0.3 projects wire GridBuilding through a composition container and an injector pattern.

What the container actually owns

GBCompositionContainer is the canonical composition root for one runtime grid-building context. Through helper methods it provides:

  • GBConfig
  • GBSettings
  • GBTemplates
  • GBActions
  • GBLogger
  • GBContexts
  • 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
      -> GridPositioner2D
      -> TargetingShapeCast2D
      -> ManipulationSystem
      -> 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
  • systems such as BuildingSystem, GridTargetingSystem, and ManipulationSystem register themselves into GBSystemsContext
  • UI and helper nodes read state/context references from the container
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

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