Table of Contents

Class PlacementInjectorSystem

Namespace
GridPlacement.GDScript
Assembly
MoonBark.GridPlacement.GDScript.dll

Dependency injection system for the Grid Building Plugin.\n\nThis system automatically handles: 1. Dependency Injection: Wires the PlacementContainer into all nodes that implement resolve_placement_dependencies(p_config: PlacementContainer) 2. Automatic Validation: Validates the complete setup after injection and reports any configuration issues via the container's logger\n\nNo manual validation calls are required - the injector handles everything automatically after dependency injection is complete.\n\n[b]Modes[/b]\n\n[b]Global mode[/b] (default, no [code]scope_root[/code]): injects the entire scene tree. Connects to [code]tree.node_added[/code] to catch dynamically added nodes. Falls back to [code][tree.root][/code] when [code]injection_roots[/code] is empty. Session auto-registration with the host is enabled by default.\n\n[b]Scoped mode[/b] ([code]scope_root[/code] set via [code]set_session_scope()[/code]): injects only the subtree under [code]scope_root[/code]. Does NOT connect to the global [code]node_added[/code] signal. The controller/bootstrap is responsible for explicitly registering the session with the host (see [code]host_created[/code] signal). This is the preferred path for split-screen, per-controller, and explicit code-built setups.\n\n[b]Responsibility Boundaries[/b]\n\n- [code]PlacementSession[/code]: owns mutable state, config, contexts, logger (SSOT) - [code]GridPlacementHost[/code]: owns stateless runtime services and dispatch - [code]PlacementInjectorSystem[/code]: wires scene-authored nodes around a session subtree; does NOT own the container, the session, or runtime logic\n\n[b]Setup Requirements:[/b] - Assign a PlacementContainer resource to this injector - Ensure PlacementLevelContext and PlacementOwner are properly configured before the injector runs (usually in _ready() methods) - The injector will automatically validate after injection and log any issues\n\nUsage Example: gdscript # In your scene node: func resolve_placement_dependencies(p_config: PlacementContainer) -> void: _composition_container = p_config _logger = p_config.get_logger() # No validation call needed - injector handles it automatically \n\n[i]Nodes that implement resolve_placement_dependencies(p_config: PlacementContainer) will be injected automatically by this system.[/i]

class PlacementInjectorSystem extends PlacementSystemBase
PlacementInjectorSystem

Fields

INJECTION_META_KEY

const INJECTION_META_KEY: String = "gb_injection_meta"

RESOLVE_METHOD

const RESOLVE_METHOD: StringName = "resolve_placement_dependencies"

RESOLVE_METHOD_LEGACY

@deprecated Legacy 5.0 name. Nodes implementing only this method still get injected: the injector dispatches to it when the canonical method is absent.

const RESOLVE_METHOD_LEGACY: StringName = "resolve_gb_dependencies"

ORPHAN_MESSAGE

const ORPHAN_MESSAGE: String = "[ORPHANED NODE]"

Properties

session

Optional [PlacementSession] — when set, the injector creates a minimal [PlacementContainer] that delegates through the session. This is the preferred path for code-built/explicit setups.\n\n6.0.0-S Phase 5: when the injector creates a [GridPlacementHost] host, this session is auto-registered with the host's per-controller session registry (single-player convenience; controllers can register additional sessions for split-screen).

@export var session: PlacementSession

composition_container

Container services as the single source of truth for settings within it's scope for systems and other nodes concerned with grid building operations. [br][br]\n\n[b]Dependencies are injected out of this container by the PlacementInjectorSystem[/b]

@export var composition_container: PlacementContainer

injection_roots

Debug settings for logging and warnings. Note: runtime validation is intentionally NOT auto-run on _ready() because other game-level dependencies (GB level context, PlacementOwner, etc.) may not be fully settled. Call run_validation() from your world/initializer script after those dependencies are created and injected. Root nodes for injection. These nodes and any children node added will be injected by the PlacementInjectorSystem. Use this for scoping injection. If left empty, all nodes in the scene tree will be injected.

@export var injection_roots: Array[Node] = []

scope_root

Optional explicit scope root for session-scoped injection.

@export var scope_root: Node

auto_register_host_session

When [code]true[/code] (default), the injector automatically registers its session with the host's per-controller registry as a single-player convenience. Set to [code]false[/code] in scoped mode and connect to the [code]host_configured[/code] signal for explicit controller-owned registration.

@export var auto_register_host_session: bool = true

roots

var roots = get_injection_roots()

issues

var issues = composition_container.get_runtime_issues()

container_issues

var container_issues = composition_container.get_runtime_issues()

ok

var ok = validate_runtime()

issues

var issues = composition_container.get_runtime_issues()

issues

var issues = composition_container.get_runtime_issues()

was_injected

var was_injected: bool = inject_node(p_node)

message

var message: String = "[scope-child_entered_tree] added=%s injected=%s" % [p_node, was_injected]

system

var system = PlacementInjectorSystem.new(container)

container

var container = PlacementContainer.new()

injector

var injector = from_session(p_parent, p_session)

rule_count

var rule_count = 0

existing

var existing = p_node.get_meta(INJECTION_META_KEY)

meta

var meta = p_node.get_meta(INJECTION_META_KEY)

node_path

var node_path = p_node.get_path() if p_node.is_inside_tree() else ORPHAN_MESSAGE

msg

var msg = "[PlacementInjectorSystem] Node exiting: %-25s at %s" % [p_node.name, node_path]

bound_cb

var bound_cb = meta["_child_entered_cb"]

meta

var meta = p_node.get_meta(INJECTION_META_KEY)

meta

var meta = p_node.get_meta(INJECTION_META_KEY)

bound_cb

var bound_cb = meta["_child_entered_cb"]

bound_exit_cb

var bound_exit_cb = meta["_tree_exiting_cb"]

meta

var meta = p_node.get_meta(INJECTION_META_KEY)

meta

var meta = p_node.get_meta(INJECTION_META_KEY)

bound_exit_cb

var bound_exit_cb = meta["_tree_exiting_cb"]

tree

var tree = get_tree()

issues

var issues = composition_container.get_runtime_issues()

host_session

var host_session: PlacementSession = self.session

host

var host = GridPlacementHost.new()

roots

var roots = get_injection_roots()

placement_system

var placement_system = find_placement_system()

ps

var ps = root.find_child("PlacementSystem", true, false) as PlacementSystem

Methods

get_injection_roots

func get_injection_roots() -> Array[Node]:

Returns

validate_runtime

func validate_runtime() -> bool:

Returns

run_validation

func run_validation() -> bool:

Returns

get_editor_issues

func get_editor_issues() -> Array[String]:

Returns

get_runtime_issues

func get_runtime_issues() -> Array[String]:

Returns

is_scoped

func is_scoped() -> bool:

Returns

create_with_injection

static func create_with_injection(p_parent : Node, container: PlacementContainer) -> PlacementInjectorSystem:

Parameters

p_parent
container

Returns

from_session

static func from_session(p_parent: Node, p_session: PlacementSession) -> PlacementInjectorSystem:

Parameters

p_parent
p_session

Returns

from_session_scoped

static func from_session_scoped(p_parent: Node, p_session: PlacementSession, p_scope_root: Node) -> PlacementInjectorSystem:

Parameters

p_parent
p_session
p_scope_root

Returns

set_session_scope

func set_session_scope(p_scope_root: Node, p_session: PlacementSession = null) -> void:

Parameters

p_scope_root
p_session

Returns

resolve_placement_dependencies

func resolve_placement_dependencies(p_config : PlacementContainer) -> void:

Parameters

p_config

Returns

inject_node

func inject_node(p_node: Node) -> bool:

Parameters

p_node

Returns

inject_recursive

func inject_recursive(p_node: Node) -> void:

Parameters

p_node

Returns

set_injection_meta

func set_injection_meta(p_node : Node) -> void:

Parameters

p_node

Returns

remove_injection_meta

func remove_injection_meta(p_node: Node) -> void:

Parameters

p_node

Returns

find_placement_system

func find_placement_system() -> PlacementSystem:

Returns

Events

initial_injection_completed

Emits when the initial scene injection is completed

signal initial_injection_completed()

node_injected

Emit whenever a node is injected

signal node_injected(node : Node)

host_configured

Emitted when the injector creates a [GridPlacementHost] host from its session. Controllers in scoped mode should connect to this signal to explicitly register their session with the host.

signal host_configured(host: GridPlacementHost)