using Godot; using System; using System.Collections.Generic; using System.Linq; using static GameData; public partial class World : Node3D { public Dictionary tileMeshes; public Dictionary decorationMeshes; public Dictionary> tilePlaceholders; PackedScene layerPrefab = ResourceLoader.LoadLayerPrefab(); private Dictionary multiMeshes = new(); private Dictionary meshLibrary = new(); Layer[] map; Layer layerNode; private MultiMeshHandler multiMeshHandler; public override void _Ready() { WFC.FillAdjacencies(); tileMeshes = ResourceLoader.LoadTiles(); decorationMeshes = ResourceLoader.LoadDecorations(); tilePlaceholders = new Dictionary>(); foreach (var kvp in tileMeshes) { tilePlaceholders[kvp.Key] = new List(); foreach (MeshInstance3D child in kvp.Value.GetChildren()) { tilePlaceholders[kvp.Key].Add(new Placeholder(child.Name, child.Transform.Origin)); } meshLibrary[kvp.Key] = kvp.Value.Mesh; kvp.Value.QueueFree(); } multiMeshes = CreateMultiMeshes(meshLibrary); multiMeshHandler = new MultiMeshHandler(multiMeshes); map = new Layer[ruinSize]; GenerateWorld(); GD.Print("World generated"); HandleRenderData(BuildRenderData(0)); } private Dictionary CreateMultiMeshes(Dictionary meshLibrary) { var result = new Dictionary(); foreach (var kvp in meshLibrary) { var mm = new MultiMesh { Mesh = kvp.Value, TransformFormat = MultiMesh.TransformFormatEnum.Transform3D }; var instance = new MultiMeshInstance3D { Multimesh = mm }; AddChild(instance); result[kvp.Key] = instance; } return result; } // Called every frame. 'delta' is the elapsed time since the previous frame. public override void _Process(double delta) { if (Input.IsActionJustPressed("layer_up") && currentLayer > 0) currentLayer--; if (Input.IsActionJustPressed("layer_down") && currentLayer < ruinSize - 1) currentLayer++; if (currentLayer != visibleLayer) { map[visibleLayer].ClearDecorations(); HandleRenderData(BuildRenderData(currentLayer)); visibleLayer = currentLayer; } if (Input.IsActionJustPressed("spawn_robot")) { Robot robot = ResourceLoader.LoadRobotPrefab().Instantiate(); robot.Position = map[0].tiles[1,1].Position; AddChild(robot); } } private void GenerateWorld() { DateTime now = DateTime.Now; for (int layer = 0; layer < ruinSize; layer++) { layerNode = layerPrefab.Instantiate(); AddChild(layerNode); layerNode.SetupLayer(layerSize, layer, tileMeshes); map[layer] = layerNode; } GD.Print("Time for map generation: " + (DateTime.Now - now).Seconds); } private List BuildRenderData(int layerIndex) { var result = new List(); Layer layer = map[layerIndex]; layer.ClearDecorations(); for (int x = 0; x < layerSize; x++) { for (int y = 0; y < layerSize; y++) { Tile tile = layer.tiles[x, y]; result.Add(new TileRenderData { Tile = tile, MeshKey = tile.collapsedMesh, Transform = new Transform3D(Basis.Identity, tile.Position), Placeholders = tilePlaceholders[tile.collapsedMesh] }); } } return result; } private void HandleRenderData(List renderData) { multiMeshHandler.Build(renderData); DecorationHandler.Spawn(renderData, decorationMeshes); } }