using Godot; namespace IslaApocalypse.Core { public class ChunkData { public Vector2I ChunkPosition; // The X/Z coordinate of this chunk (e.g., 0,0 or 1,0) // We need Width+1 and Depth+1 so the Marching Cubes mesh connects seamlessly to the neighbor chunks! // public float[,,] Densities = new float[Constants.CHUNK_SIZE_X + 1, Constants.CHUNK_HEIGHT, Constants.CHUNK_SIZE_Z + 1]; // public byte[,,] BlockIDs = new byte[Constants.CHUNK_SIZE_X + 1, Constants.CHUNK_HEIGHT, Constants.CHUNK_SIZE_Z + 1]; // OLD: // Densities = new float[Constants.CHUNK_SIZE_X, Constants.CHUNK_HEIGHT, Constants.CHUNK_SIZE_Z]; // BlockIDs = new int[Constants.CHUNK_SIZE_X, Constants.CHUNK_HEIGHT, Constants.CHUNK_SIZE_Z]; // NEW (Fix 3): We expand by 1 to sample the neighbor's border perfectly without seams! public float[,,] Densities = new float[Constants.CHUNK_SIZE_X + 1, Constants.CHUNK_HEIGHT + 1, Constants.CHUNK_SIZE_Z + 1]; public byte[,,] BlockIDs = new byte[Constants.CHUNK_SIZE_X + 1, Constants.CHUNK_HEIGHT + 1, Constants.CHUNK_SIZE_Z + 1]; // --- PER-COLUMN DATA, FOR VERTEX COLOURING ONLY ---------------------- // One entry per X/Z column of this chunk (same +1 padding as above). // // Why these exist: BlockIDs are classified against a ROUNDED surface // height, which is fine for storage but makes the rendered colour jump // in whole-metre steps (the "contour band" artefact). The renderer // instead reads the TRUE, unrounded surface height from here, so the // material fade follows the real ground. // // These are read by the mesher only. Nothing about geometry, collision // or storage depends on them. public float[,] SurfaceHeights = new float[Constants.CHUNK_SIZE_X + 1, Constants.CHUNK_SIZE_Z + 1]; public Biome[,] ColumnBiomes = new Biome[Constants.CHUNK_SIZE_X + 1, Constants.CHUNK_SIZE_Z + 1]; // What this column's road surface is paved with — asphalt for highways, // dirt for trails, and 0 (BlockRegistry.AIR) for "not a road at all". // Carries the tier's material rather than a plain yes/no, so a footpath // doesn't get painted like a motorway. public byte[,] ColumnRoadMaterial = new byte[Constants.CHUNK_SIZE_X + 1, Constants.CHUNK_SIZE_Z + 1]; // --- WATER AT REST (terrain-water task 13) --------------------------- // Per column: the world-space Y of the water SURFACE, or Constants.NO_WATER // where the blueprint says this column is dry. Filled by the server from // the blueprint's WSRF/WBID/WBTB — the runtime never decides where water // is, it only draws what the blueprint already classified. // // WaterDepthM is the TRUE depth in metres (water level minus seabed, both // in blueprint units), kept separately because the rendered seabed is // clamped at Y=2 and would flatten every deep-ocean column to the same // value. Colour reads this; geometry reads WaterSurfaceY. public float[,] WaterSurfaceY = new float[Constants.CHUNK_SIZE_X + 1, Constants.CHUNK_SIZE_Z + 1]; public float[,] WaterDepthM = new float[Constants.CHUNK_SIZE_X + 1, Constants.CHUNK_SIZE_Z + 1]; /// True if any column in this chunk carries water — lets the /// renderer skip building a water mesh for the many inland chunks. public bool HasAnyWater = false; // For our future delta-save system public bool IsPlayerProtected = false; public bool NeedsSaving = false; public ChunkData(Vector2I position) { ChunkPosition = position; // float[,] defaults to 0, which is a legal-looking water height. Start // every column explicitly dry instead. for (int x = 0; x <= Constants.CHUNK_SIZE_X; x++) for (int z = 0; z <= Constants.CHUNK_SIZE_Z; z++) WaterSurfaceY[x, z] = Constants.NO_WATER; } } }