Development ⚠️ GridPlacement 6.0 documentation is in active development. APIs and content may change, and the site may be temporarily unstable.

Core/Godot DLL Integration Guide

This guide covers the new 6.0.0 architecture where GridBuilding’s core logic is separated into an engine-agnostic C# DLL with a dedicated Godot integration layer.

Naming Note – GridBuilding → GridPlacement 6.0
In 5.x, the Godot plugin shipped as GridBuilding. For the C#‑based 6.0 line the plugin and Hugo docs are branded GridPlacement 6.0, while the compiled C# assemblies and namespaces stay under GridBuilding.* (for example GridBuilding.Core, GridBuilding.Godot). When this guide talks about the “core DLL” and “Godot integration layer”, it is describing the GridPlacement 6.0 C# plugin.

🏗️ Architecture Overview

Two-Layer Architecture

┌─────────────────────────────────────┐
│           Godot Layer               │
│  ┌─────────────────────────────────┐ │
│  │  Godot Systems & UI Nodes       │ │ ← Call services + listen to events
│  │  Adapter Nodes (optional)       │ │
│  └─────────────────────────────────┘ │
└─────────────────────────────────────┘
                    ↓
┌─────────────────────────────────────┐
│            Core DLL                 │
│  ┌─────────────────────────────────┐ │
│  │   Services & Domain Events      │ │ ← Engine-agnostic logic
│  │   BuildingState & other state   │ │
│  │   Validation & Error Handling   │ │
│  └─────────────────────────────────┘ │
└─────────────────────────────────────┘

Core DLL (GridBuilding.Core.dll)

  • Engine Agnostic: No Godot dependencies
  • Business Logic: Building placement, validation, state management
  • Event System: C# events for all building operations
  • Thread Safe: ReaderWriterLockSlim for concurrent access
  • Testable: Can be unit tested independently

Godot Integration Layer

  • Adapter / system nodes: Thin Godot nodes that resolve Core services via DI and forward domain events to Godot signals or local state.
  • Godot Systems: Engine-specific implementations that call into services.
  • UI Integration: GDScript-friendly wrappers around service APIs and events.
  • Resource Management: Godot-specific asset handling.

🚀 Quick Start

1. Project Setup

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# Your project structure
your_project/
├── addons/
│   └── grid_building/
│       ├── plugin.cfg
│       ├── GridBuilding.csproj
│       ├── Systems/
│       │   └── [Godot systems]
│       └── addons/
│           └── grid_building/
│               └── bin/
│                   └── GridBuilding.Core.dll  ← Compiled Core DLL

2. Basic Usage

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// In your Godot C# script (6.0 service-based integration)
using Godot;
using GridBuilding.Core.Services.Building;
using GridBuilding.Bootstrap; // ServiceCompositionRoot

public partial class BuildingController : Node
{
    private IBuildingService? _buildingService;

    public override void _Ready()
    {
        // Resolve services from the shared ServiceRegistry
        var registry = ServiceCompositionRoot.GetGlobalRegistry();
        _buildingService = registry.GetService<IBuildingService>();

        // Subscribe to domain events if needed
        _buildingService.BuildingPlaced += OnBuildingPlaced;
        _buildingService.BuildingRemoved += OnBuildingRemoved;
    }

    private void OnBuildingPlaced(string buildingType, Vector2I position, string instanceId)
    {
        GD.Print($"Building {buildingType} placed at {position}");
        // Update UI, play sounds, etc.
    }

    public void PlaceBuilding(string type, Vector2I position)
    {
        if (_buildingService == null)
        {
            GD.PrintErr("IBuildingService not available");
            return;
        }

        _buildingService.PlaceBuilding(type, position);
    }
}

3. GDScript Integration

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# In your GDScript (via a thin C# adapter node)
extends Node

@onready var building_system = $BuildingSystemNode

func _ready():
    # Connect to signals raised by your C# system node
    building_system.building_placed.connect(_on_building_placed)
    building_system.building_removed.connect(_on_building_removed)

func _on_building_placed(building_type, position, instance_id):
    print("Building placed: ", building_type, " at ", position)

func place_tower():
    # Adapter node forwards to the underlying IBuildingService
    building_system.place_building("tower", Vector2i(5, 5))

🔄 Event System Integration

C# Events → Godot Signals

The Godot integration layer converts Core C# domain events to Godot signals via thin adapter/system nodes. In a typical setup, a dedicated C# node subscribes to Core events and emits Godot signals that your UI or GDScript code can listen to.

C# Event (Core DLL)Godot Signal (adapter node)Parameters
BuildingPlacedEventbuilding_placedbuilding_type: String, position: Vector2i, instance_id: String
BuildingRemovedEventbuilding_removedbuilding_type: String, position: Vector2i, instance_id: String
BuildingDamagedEventbuilding_damagedinstance_id: String, damage: float, current_health: float
BuildingDestroyedEventbuilding_destroyedinstance_id: String
BuildingRepairedEventbuilding_repairedinstance_id: String, repair_amount: float, new_health: float
BuildingHealthChangedEventbuilding_health_changedinstance_id: String, previous_health: float, current_health: float

Event Flow Example

User Action → Godot gameplay code calls a placement method (C# or GDScript)
         ↓
Core DLL IBuildingService.PlaceBuilding() handles the request
         ↓
Core DLL publishes BuildingPlacedEvent
         ↓
Adapter/system node receives the domain event
         ↓
Adapter/system node emits a building_placed Godot signal
         ↓
Godot signal system notifies connected GDScript/C# handlers

🛠️ Core DLL API Reference

BuildingService

Place Building

1
public BuildingState PlaceBuilding(string buildingType, Vector2I gridPosition, string ownerId = "")

Validation Rules:

  • Position coordinates must be non-negative
  • Position must not be occupied
  • Building type must be valid
  • Special rules (towers: Y ≥ 5, walls: even coordinates)

Returns: BuildingState with generated InstanceId

Remove Building

1
public bool RemoveBuilding(string buildingId)

Returns: true if building was found and removed

Apply Damage

1
public bool ApplyDamage(string buildingId, float damageAmount)

Effects:

  • Reduces building health
  • Changes status to Damaged if health < max
  • Triggers BuildingDamagedEvent
  • Triggers BuildingDestroyedEvent if health ≤ 0

Repair Building

1
public bool RepairBuilding(string buildingId, float repairAmount)

Effects:

  • Increases building health (up to max)
  • Changes status from Damaged to Operational
  • Triggers BuildingRepairedEvent

BuildingState Properties

PropertyTypeDescription
BuildingTypestringType of building (basic, tower, wall, etc.)
GridPositionVector2IPosition on the grid
InstanceIdstringUnique identifier (GUID)
OwnerIdstringOwner of the building
StatusBuildingStatusCurrent state (Placed, Damaged, Destroyed, etc.)
HealthfloatCurrent health points
MaxHealthfloatMaximum health points

BuildingStatus Enum

1
2
3
4
5
6
7
8
9
public enum BuildingStatus
{
    Placed,
    UnderConstruction,
    Operational,
    Damaged,
    Destroyed,
    Repairing
}

🧪 Testing Integration

Unit Testing Core DLL

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
[Test]
public void BuildingService_CanPlaceAndRemoveBuilding()
{
    var service = new BuildingService();
    var building = service.PlaceBuilding("basic", new Vector2I(5, 10));
    
    Assert.NotNull(building);
    Assert.Equal("basic", building.BuildingType);
    Assert.Equal(1, service.GetAllBuildings().Count());
    
    var removed = service.RemoveBuilding(building.InstanceId);
    Assert.True(removed);
    Assert.Equal(0, service.GetAllBuildings().Count());
}

Integration Testing with Godot

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// Pseudo-code: adapter node converts Core events to Godot signals
// (replace `BuildingEventsAdapter` with your own adapter implementation)
var adapter = new BuildingEventsAdapter(service);
var signalReceived = false;

// Adapter exposes a Godot-style signal/event
adapter.BuildingPlaced += () => signalReceived = true;

// Trigger Core DLL event
var building = service.PlaceBuilding("tower", new Vector2I(3, 7));

Assert.True(signalReceived);

🔧 Advanced Configuration

Custom Validation Rules

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
// Extend BuildingService validation
public class CustomBuildingService : BuildingService
{
    protected override List<string> ValidateBuildingPlacement(Vector2I position, string buildingType)
    {
        var errors = base.ValidateBuildingPlacement(position, buildingType);
        
        // Add custom rules
        if (buildingType == "special" && position.X < 10)
        {
            errors.Add("Special buildings must be placed at X ≥ 10");
        }
        
        return errors;
    }
}

Custom Event Handlers

1
2
3
4
5
6
7
8
9
// In StateBridge
protected override void OnBuildingPlaced(object? sender, BuildingPlacedEvent e)
{
    base.OnBuildingPlaced(sender, e);
    
    // Add custom logic
    LogBuildingPlacement(e.Building);
    UpdateStatistics(e.Building);
}

Thread Safety Considerations

The Core DLL uses ReaderWriterLockSlim for thread safety:

1
2
3
4
5
// Thread-safe operations are automatic
Parallel.ForEach(positions, pos => {
    var building = service.PlaceBuilding("basic", pos);
    // No additional synchronization needed
});

🚨 Error Handling

Exception Types

ExceptionWhen ThrownHow to Handle
BuildingPlacementExceptionValidation failsShow error message to user
ArgumentExceptionInvalid parametersValidate user input
InvalidOperationExceptionDuplicate placementCheck position first

Error Handling Pattern

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
try
{
    var building = _stateBridge.PlaceBuilding(buildingType, position);
    // Success - update UI
}
catch (BuildingPlacementException ex)
{
    // Show validation error to user
    ShowError($"Cannot place building: {ex.Message}");
}
catch (Exception ex)
{
    // Log unexpected errors
    GD.PrintErr($"Unexpected error: {ex.Message}");
    ShowError("An unexpected error occurred");
}

📊 Performance Considerations

Memory Management

  • Core DLL uses efficient Dictionary-based lookup
  • Event subscriptions are automatically cleaned up
  • Building states are lightweight structs

Thread Performance

  • Read operations use read locks (concurrent access)
  • Write operations use write locks (exclusive access)
  • Event publishing creates handler copies to avoid deadlocks

Optimization Tips

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// Good: Batch operations
var buildings = new List<BuildingState>();
foreach (var pos in positions)
{
    buildings.Add(service.PlaceBuilding("basic", pos));
}

// Avoid: Excessive individual calls
// foreach (var pos in positions)
// {
//     service.PlaceBuilding("basic", pos); // Creates many events
// }

🔍 Debugging

Core DLL Debugging

1
2
3
4
5
6
// Enable console logging
Console.WriteLine($"[BuildingService] Placed {buildingType} at {position}");

// Check event subscriptions
var subscriberCount = EventDispatcher.Instance.GetSubscriberCount<BuildingPlacedEvent>();
GD.Print($"BuildingPlacedEvent subscribers: {subscriberCount}");

Godot Integration Debugging

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// Check signal connections
if (!stateBridge.IsConnected("building_placed", Callable(OnBuildingPlaced)))
{
    GD.PrintErr("Building placed signal not connected!");
}

// Verify Core DLL is loaded
if (!File.Exists("res://addons/grid_building/bin/GridBuilding.Core.dll"))
{
    GD.PrintErr("Core DLL not found!");
}

✅ Integration Checklist

Setup

  • Core DLL copied to addons/grid_building/bin/
  • Godot project references Core DLL
  • Adapter/system nodes that subscribe to Core services are added to the scene tree (no monolithic StateBridge node required)
  • Plugin configuration updated

Testing

  • Core DLL builds successfully
  • Building placement works
  • Events convert to signals
  • Error handling works
  • Thread safety verified

Performance

  • No memory leaks in event system
  • Acceptable placement performance
  • UI remains responsive during operations

Documentation

  • API documentation updated
  • Integration examples provided
  • Troubleshooting guide created

🎉 Success!

Your GridBuilding plugin is now using the new Core/Godot DLL architecture! You have:

  • Engine-agnostic core logic that can be tested independently
  • Robust event system with automatic signal conversion
  • Thread-safe operations for concurrent access
  • Comprehensive error handling with detailed validation
  • Better performance with optimized C# implementation

Next Steps

  1. Explore the Core DLL - Try unit testing your building logic
  2. Custom validation - Add game-specific building rules
  3. Performance optimization - Profile and optimize for your use case
  4. Contribute back - Share improvements with the community

Need help? Check the troubleshooting section or create an issue on GitHub.