GridPlacement 6.0 separates Core (pure C#, no engine dependencies) from Godot (engine-specific adapters). This gives you a clean boundary for testing, headless operation, and porting.

The Four Layers

┌─────────────────────────────────────────────────────────────────┐
│  Addon Layer (demos/addons/grid_placement/)                     │
│  - [GlobalClass] types the consumer wires in scenes             │
│  - PlaceableDefinition, RuleSettings, IndicatorSettings         │
│  - RuleCheckIndicator, TileBuildabilityIndicator                │
│  - GridPlacementPlugin (EditorPlugin)                           │
└────────────────────────────┬────────────────────────────────────┘
                             │ symlinked UI/ → Godot/UI/
                             ▼
┌─────────────────────────────────────────────────────────────────┐
│  Godot Layer (MoonBark.GridPlacement.Godot)                     │
│  - PlacementBootstrap (Resource) — coordinator & signal buses   │
│  - PlacementRuntimeCoordinator — per-frame update loop          │
│  - TileMapSyncManager — ECS → TileMap sync                     │
│  - PlacementProvider — tilemap/objects parent contract          │
│  - PlacementInputHandler — input processing (plain C# class)   │
│  - Godot Events → ECS Events bridge                            │
└────────────────────────────┬────────────────────────────────────┘
                             │ calls
                             ▼
┌─────────────────────────────────────────────────────────────────┐
│  ECS Layer (MoonBark.GridPlacement.ECS)                         │
│  - GridPlacementEcsPlugin (IEcsPlugin entry point)             │
│  - GridOccupancySystem, ManipulationSystem                      │
│  - Friflo.Engine.ECS Entity/Component                          │
│  - Pure C#, no Godot dependency                                │
└────────────────────────────┬────────────────────────────────────┘
                             │ uses
                             ▼
┌─────────────────────────────────────────────────────────────────┐
│  Core Layer (MoonBark.GridPlacement.Core)                       │
│  - Interfaces: IPlacementCoreService, IGridOccupancy,           │
│    ITargetingService, IManipulationRuntimeCatalog               │
│  - Validation: PlacementRuleRegistry, IPlacementRule             │
│  - Events: PlacementEventBus, ManipulationEventBus              │
│  - Pure C#, no Godot dependency                                │
└─────────────────────────────────────────────────────────────────┘

Note: ECS types live in MoonBark.GridPlacement.ECS.csproj (a separate project from Core). The "ECS layer" is a logical grouping with its own csproj. GridPlacementEcsPlugin lives in the ECS project and implements IEcsPlugin.

Key Types by Layer

Layer Primary Types Purpose
Godot PlacementBootstrap (in PlacementCoordinator.cs), PlacementRuntimeCoordinator, TileMapSyncManager Scene wiring, input, ECS ↔ TileMap sync
ECS GridPlacementEcsPlugin, GridOccupancySystem, ManipulationSystem Authoritative occupancy, move/demolish operations
Core PlacementEventBus, ManipulationEventBus, IGridOccupancy, ITargetingService, PlacementRuleRegistry Business logic interfaces, validation, events

Plugin Architecture Pattern

GridPlacement uses the IEcsPlugin pattern for ECS integration:

public sealed class GridPlacementEcsPlugin : IEcsPlugin
{
    public void RegisterSystems(EcsWorld world, SystemRunner runner)
    {
        var group = new EcsSystemGroup("GridPlacement");
        group.Add(new EcsSystemAdapter("GridOccupancy", _occupancySystem.Update));
        runner.Add(group);
        runner.Add(_manipulationSystem);
    }
}

Godot calls plugin.Install(world) and uses ECS types directly via IGridPlacementOperations.

Multiplayer Topologies

GridPlacement supports four topologies:

Topology Description Server
Single-player All systems run in one process N/A
Listen-server One player is also the host Host process
Dedicated server Headless authoritative host Dedicated process
Local multiplayer Same device, multiple input sources N/A

The Four Seams (Listen-Server / Dedicated)

Seam What Where you code
Catalog All peers load same placeable assets Lobby / loading
Intent Client → Server: (placeableId, gridPos) RPC call
Authority Only host runs placement pipeline Guard with Multiplayer.IsServer()
Event Relay Server → All: placement outcome rpc() broadcast

What the Plugin Provides

Capability Type
Authoritative occupancy IGridOccupancy
Conflict detection PlacementValidator
Headless loop PlacementExecutionSystem
Concurrent placers OwnerKey
ECS events IEcsBackendEvents
Save/restore ECS serialization

What the Plugin Does Not Provide

  • Network transport (ENet, WebSocket, Steam, etc.)
  • Lobby / matchmaking
  • Clock synchronization
  • Lag compensation
  • [Composition + Injection]({{% ref "composition-and-injection" %}}) — How PlacementBootstrap wires services
  • [Settings Architecture]({{% ref "settings" %}}) — Configuration resource hierarchy
  • [Manipulation]({{% ref "manipulation" %}}) — Move/rotate/demolish orchestration

**Last Updated: 2026-05-31