90 lines
2.9 KiB
Rust
90 lines
2.9 KiB
Rust
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<Chunk>; 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
|
|
}
|
|
}
|
|
}
|