Skip to content

Grid Placement v6.0.2

Composition & Injection

How Grid Placement 6.0 services are composed and wired into a scene.

Status
Current
Version
v6.0.2
Source updated
2026-09-04
Generated on
2026-09-11

Grid Placement separates runtime logic from scene/game context. This is the canonical guide for host/session composition beyond the starter setup.

You usually interact with three layers:

  1. GridPlacementHost — routes the active interaction and composes runtime services.
  2. PlacementSession — stores per-player/controller state and configuration references.
  3. Context/provider adapters — connect the current level, player, and game facts to placement validation/services.

Default path

For new 6.0 scenes, use the host/session path directly:

  1. Add a GridPlacementHost to the scene root or systems scene.
  2. Assign GridPlacementHost.grid_placement_bundle.
  3. Assign each GridPositioner2D.session to the PlacementSession owned by that player/controller.
  4. Author PlacementLevelContext and PlacementOwner in the scene.

When GridPositioner2D.session is assigned, the positioner configures itself from that session and registers it with the nearest GridPlacementHost at runtime. You do not need an injector for a normal new setup.

A normal project also does not need to instantiate every placement service manually. The host composes the configured service group from the bundle/session.

Explicit host configuration

Use explicit configuration when code owns the session lifecycle rather than a scene-authored positioner:

host.configure(session)

For independent controllers:

host.register_session(controller_root, session, device_id)

Unregister the controller/session when its owning scene or controller leaves. Keep one session per independent interaction; players that need separate selection, targeting, coordinate mode, or pending manipulation state should not share a session.

Consumers should use supported host/service entry points instead of depending on internal scene paths.

Compatibility: PlacementInjectorSystem

PlacementInjectorSystem remains a compatibility path for older/editor-composed scenes that still depend on injection. Do not choose it as the architecture for a new 6.0 integration.

If you maintain an injector-based scene:

  • scope injection to the intended runtime subtree;
  • keep the injector and host on the same PlacementSession/bundle configuration;
  • do not let injector auto-registration compete with explicit host.configure() or host.register_session() ownership.

Prefer converging actively maintained scenes toward the host/session path instead of adding new injector dependencies.

Context injection

Use contexts/providers for facts that come from the current game scene, for example:

  • target TileMapLayer or GridMap surface;
  • placed-object parent;
  • placement owner/controller;
  • game-owned reserved/occupied zones;
  • inventory, cost, or world-state facts used by custom rules.

Do not copy those facts into long-lived plugin globals when their lifetime belongs to a level, session, or game system.

Shared placement world

Dimension-specific services still need to agree on the same committed placement world.

This matters for:

  • GRID vs SMOOTH conflicts;
  • CELL/EDGE/FACE/CORNER/TOP mount occupancy;
  • SMOOTH socket occupancy;
  • multiple sessions;
  • save/restore.

Do not build a second occupancy registry that can commit conflicting placement state.

When to inject a custom service/provider

Add custom composition only when the project needs a real policy or integration point. Examples:

  • a game-owned world-facts provider;
  • custom placement validation rule;
  • inventory/refund bridge;
  • custom input/controller/session setup.

PlacementInjectable receives a PlacementSession directly. Do not write new integration code around removed PlacementContainer compatibility types.

Avoid replacing plugin services only to change naming or add logging.

Troubleshooting composition

Check these before changing plugin code:

  1. GridPlacementHost exists in the relevant scene/systems tree.
  2. GridPositioner2D.session is assigned for scene-authored controller wiring.
  3. The host and session use the intended GridPlacementBundle.
  4. PlacementLevelContext and PlacementOwner belong to the active level/controller lifetime.
  5. Only if maintaining a legacy injector scene: verify injector scope and registration ownership.