Grid/Base/GridSpawner.cs
using Sandbox;
using Sandbox.Grid.Base;
using Sandbox.Sboku;
using Sandbox.Sboku.Arena;
using System;
using System.Collections.Generic;
using System.Net.NetworkInformation;
using System.Numerics;
using System.Runtime.CompilerServices;

// =========================
//  GRID SPAWNER
//Stone trim
//Stone altar, stone pickaxe, ´stone fire pit, stone spear, medieval wood door, wooden chair re4, wood market stand, short sword, gmod skeleton
//ceramic column, torch 2
// =========================

/// <summary>
/// GridSpawner – pääluokka, joka orkestroi gridin spawnaamisen s&box-maailmaan.
/// Säilyttää yhteiset propertyt ja kentät, delegoi varsinaisen spawnauksen
/// WallSpawner-, FloorSpawner- ja GridObjectSpawner-luokille.
/// </summary>
public sealed class GridSpawner : Component
{
    // talo-id per grid-ruutu
    internal int[,] HouseIds;

    // talokohtainen materiaali
    internal Dictionary<int, Material> HouseWallMaterials = new();

    [Property] public DebrisVisualPool DebrisPool { get; set; }
    [Property] public GameObject DustPrefab { get; set; }
    [Property] public List<string> WallMaterials { get; set; }

    [Property] public List<string> FloorOutdoorMaterials { get; set; }
    [Property] public List<string> FloorIndoorMaterials { get; set; }

    [Property] public List<string> IndoorModels { get; set; }

    [Property] public List<string> OutdoorModels { get; set; }

    private const int itemsPerRoom = 5;
    private string SnowCapModelPath { get; set; } = "models/dev/box.vmdl";

    private const float BorderUVFactor = 2.5f;
    private string SnowCapMaterialPath { get; set; } = "materials/snow1.vmat";
    [Sync] public int WallMaterialOuterIndex { get; private set; }

    [Sync] public int WallMaterialHouseIndex { get; private set; }

    [Sync] public int FloorIndoorMaterialIndex { get; private set; }
    [Sync] public int FloorOutdoorMaterialIndex { get; private set; }

    [Property] public GameObject InteriorFog { get; set; }

    [Property] public int WallHeight { get; set; } = 3;

    internal string WallModelPath { get; set; } = "models/dev/box.vmdl";

    private string FloorModelPath { get; set; } = "models/floorplane.vmdl";
    internal string ButtonModelPath { get; set; } = "models/buildings/stone/floor_128_a.vmdl";

    internal string TrapModelEmptyPath { get; set; } = "deggassets/models/fantasy/map/trap_empty.vmdl";
    internal string TrapModelPath { get; set; } = "deggassets/models/fantasy/map/trap_spikes.vmdl";

    internal string DoorModelPath { get; set; } = "materials/zombieworld/woodendoor01_pixel.vmat";

    [Property] public float SpawnHeight { get; set; } = 32f;
    //lattian YLÄPINTA maailmassa
    internal float FloorZ => SpawnHeight;

    public string gridText { get; set; } =
        "####\n#0+0#\n####";

    public GridMap Map { get; private set; }
    internal Model BoxModel;
    internal Material WallMaterialHouse;
    internal Material WallMaterialOuter;

    internal Material FloorIndoorMaterial;
    internal Material FloorOutdoorMaterial;

    private int ChunkSize { get; set; } = 16;

    private WallSpawner wallSpawner;
    private FloorSpawner floorSpawner;
    private GridObjectSpawner objectSpawner;

    /// <summary>
    /// Käytetäänkö vankila-generaattoria (true) vai tavallista talogeneraattoria (false).
    /// </summary>
    [Property] public bool UsePrisonLayout { get; set; } = false;

    protected override void OnStart()
    {
        if (IsProxy)
            return; // ❗ Client EI saa spawnaa gridin maailmaa

        if (UsePrisonLayout)
        {
            var prisonGen = new PrisonGenerator();
            prisonGen.Generate();
            gridText = prisonGen.Serialize();
        }
        else
        {
            var gridGenerator = new GridGenerator();
            gridGenerator.Generate();
            gridText = gridGenerator.Serialize();
        }
        
        if (string.IsNullOrEmpty(gridText))
        {
            Log.Error("[GridSpawner] GridText not set!");
            Enabled = false;
            return;
        }

        Map = new GridMap(gridText);

        if (UsePrisonLayout)
        {
            Log.Info("[GridSpawner] Prison layout active - skipping procedural wall/floor/object spawn.");
            return;
        }

        BoxModel = Model.Load(WallModelPath);

        WallMaterialOuterIndex = 0;
        WallMaterialHouseIndex = 1;
        WallMaterialOuter = Material.Load(WallMaterials[WallMaterialOuterIndex]);
        WallMaterialHouse = Material.Load(WallMaterials[WallMaterialHouseIndex]);

        // Luodaan helper-luokat
        wallSpawner = new WallSpawner(this);
        floorSpawner = new FloorSpawner(this);
        objectSpawner = new GridObjectSpawner(this);

        // 🔑 RAKENNA TALOT
        wallSpawner.BuildHouseIds();

        // Spawn seinät ja ovet
        for (int y = 0; y < Map.Height; y++)
        {
            for (int x = 0; x < Map.Width; x++)
            {
                if (Map.IsWallLike(x, y))
                    wallSpawner.SpawnWallsAndDoors(x, y);
            }
        }

        wallSpawner.SpawnBorderWalls();

        FloorIndoorMaterialIndex = Game.Random.Int(0, FloorIndoorMaterials.Count - 1);
        FloorIndoorMaterial = Material.Load(FloorIndoorMaterials[FloorIndoorMaterialIndex]);

        FloorOutdoorMaterialIndex = Game.Random.Int(0, FloorOutdoorMaterials.Count - 1);
        FloorOutdoorMaterial = Material.Load(FloorOutdoorMaterials[FloorOutdoorMaterialIndex]);

        floorSpawner.SpawnFloorSingle();
        /*for (int y = 0; y < Map.Height; y++)
        {
            for (int x = 0; x < Map.Width; x++)
            {
                floorSpawner.SpawnFloorTile(x, y);
            }
        }*/
        floorSpawner.SpawnSingleFloorCollider();

        // Spawn painikkeet
        objectSpawner.SpawnButtons();

        objectSpawner.SpawnTraps();

        // Props disabled — no random indoor/outdoor item spawning
        // var rooms = Map.FindRooms();
        // objectSpawner.SpawnIndoorItems(this.Map);
        // objectSpawner.SpawnOutdoorItems(this.Map,20);
    }
}