public static void GenerateRuin(VoxelChunk Chunk, ChunkGeneratorSettings Settings) { // Todo: Support ruins deep underground - empty out their interiors. LoadRuinTemplates(); var noiseVector = Chunk.Origin.ToVector3() * Settings.CaveNoiseScale; var ruinsNoise = Settings.CaveNoise.GetValue(noiseVector.X, noiseVector.Y, noiseVector.Z); if (Math.Abs(ruinsNoise) > GameSettings.Current.GenerationRuinsRate) { return; } var avgHeight = GetAverageHeight(Chunk.Origin.X, Chunk.Origin.Z, 16, 16, Settings); var ruinWallType = Library.GetVoxelType("Cobble"); // Todo: Should make this data so this doesn't break if tile names change? var ruinFloorType = Library.GetVoxelType("Blue Tile"); if (Settings.Overworld.Map.GetBiomeAt(Chunk.Origin.ToVector3(), Settings.Overworld.InstanceSettings.Origin).HasValue(out var biome)) { ruinWallType = Library.GetVoxelType(biome.RuinWallType); ruinFloorType = Library.GetVoxelType(biome.RuinFloorType); } if (!ruinWallType.HasValue() || !ruinFloorType.HasValue()) { return; } int wallHeight = MathFunctions.RandInt(2, 6); var template = RuinTemplates[MathFunctions.RandInt(0, RuinTemplates.Count)]; var rotations = MathFunctions.RandInt(0, 3); for (var i = 0; i < rotations; ++i) { template = TextureTool.RotatedCopy(template); } for (int dx = 0; dx < 16; dx++) { for (int dz = 0; dz < 16; dz++) { var worldPos = new Vector3(Chunk.Origin.X + dx, avgHeight, Chunk.Origin.Z + dz); var baseVoxel = Settings.World.ChunkManager.CreateVoxelHandle(GlobalVoxelCoordinate.FromVector3(worldPos)); var underVoxel = VoxelHelpers.FindFirstVoxelBelow(Settings.World.ChunkManager.CreateVoxelHandle(GlobalVoxelCoordinate.FromVector3(worldPos))); var decay = Settings.NoiseGenerator.Generate(worldPos.X * 0.05f, worldPos.Y * 0.05f, worldPos.Z * 0.05f); if (decay > 0.7f) { continue; } if (!baseVoxel.IsValid) { continue; } if (baseVoxel.Coordinate.Y == (Settings.WorldSizeInChunks.Y * VoxelConstants.ChunkSizeY) - 1) { continue; } if (!underVoxel.IsValid) { continue; } var templateColor = template.Data[template.Index(dx, dz)]; if (templateColor == new Color(0, 0, 255, 255)) // Border { continue; } else if (templateColor == new Color(0, 0, 0, 255)) // Space { continue; } else if (templateColor == new Color(255, 0, 0, 255)) // Wall { baseVoxel.RawSetType(ruinWallType); FillBelowRuins(Settings, ruinWallType, baseVoxel, underVoxel); FillRuinColumn(Settings, ruinWallType, 1, wallHeight, baseVoxel, decay); } else if (templateColor == new Color(128, 128, 0, 255)) // Door { baseVoxel.RawSetType(ruinWallType); FillBelowRuins(Settings, ruinWallType, baseVoxel, underVoxel); FillRuinColumn(Settings, ruinWallType, 3, wallHeight, baseVoxel, decay); } else if (templateColor == new Color(128, 0, 0, 255)) // Floor { FillBelowRuins(Settings, ruinWallType, baseVoxel, underVoxel); baseVoxel.RawSetType(ruinFloorType); } } } }