use godot::classes::class_macros::private::virtuals::Os::Vector3i; use super::chunk::{CHUNK_SIZE, Chunk}; pub const CHUNKS_PER_COLUMN: usize = 8; pub struct ChunkColumn { // from bottom to top // TODO: replace with vec![] pub chunks: [Option; CHUNKS_PER_COLUMN], pub world_position: (i32, i32), // XZ pub chunk_size: Vector3i, } impl ChunkColumn { pub fn new(x: i32, z: i32, chunk_size: Vector3i) -> Self { ChunkColumn { chunks: [None, None, None, None, None, None, None, None], world_position: (x, z), chunk_size, } } #[inline] pub fn get_chunk_index(chunk_size_y: i32, world_y: i32) -> usize { (world_y / chunk_size_y) as usize } #[inline] pub fn get_local_y(chunk_size_y: i32, world_y: i32) -> i32 { world_y % chunk_size_y } #[inline] pub fn get_world_y(chunk_size_y: i32, chunk_index: i32, local_y: i32) -> i32 { (chunk_index * chunk_size_y) + local_y } pub fn get_or_create_chunk(&mut self, chunk_y_index: i32) -> &mut Chunk { if self.chunks[chunk_y_index as usize].is_none() { let (world_x, world_z) = self.world_position; self.chunks[chunk_y_index as usize] = Some(Chunk::new( world_x as f64, chunk_y_index as f64, world_z as f64, self.chunk_size, )); } self.chunks[chunk_y_index as usize].as_mut().unwrap() } pub fn get_chunk(&self, chunk_y_index: usize) -> Option<&Chunk> { self.chunks[chunk_y_index].as_ref() } pub fn get_chunk_mut(&mut self, chunk_y_index: usize) -> Option<&mut Chunk> { self.chunks[chunk_y_index].as_mut() } pub fn set_voxel(&mut self, world_pos: Vector3i, is_solid: bool) -> bool { let chunk_index = Self::get_chunk_index(self.chunk_size.y, world_pos.y); if chunk_index < CHUNKS_PER_COLUMN { let size = self.chunk_size.clone(); let chunk = self.get_or_create_chunk(chunk_index as i32); let local_x = world_pos.x.rem_euclid(size.x); let local_y = Self::get_local_y(size.y, world_pos.y); let local_z = world_pos.z.rem_euclid(size.z); chunk.set_voxel(Vector3i::new(local_x, local_y, local_z), is_solid, size); true } else { false } } pub fn get_voxel(&self, world_pos: Vector3i) -> bool { let chunk_index = Self::get_chunk_index(self.chunk_size.y, world_pos.y); if let Some(chunk) = self.get_chunk(chunk_index) { let local_x = world_pos.x.rem_euclid(CHUNK_SIZE); let local_y = Self::get_local_y(self.chunk_size.y, world_pos.y); let local_z = world_pos.z.rem_euclid(CHUNK_SIZE); chunk.get_voxel(Vector3i::new(local_x, local_y, local_z), self.chunk_size) } else { false // Air by default } } }