diff --git a/src/simple_server/server.rs b/src/simple_server/server.rs index 182cf35..80db5bc 100644 --- a/src/simple_server/server.rs +++ b/src/simple_server/server.rs @@ -27,6 +27,10 @@ impl SimpleServer { } } + pub fn num_chunks(&self) -> usize { + self.chunks.len() + } + fn chunk_at_block_mut(&mut self, block_pos: &BlockPos) -> Option<&mut ChunkData> { // Find what chunk the block is in let chunk_pos = ChunkPos::from(block_pos); @@ -72,6 +76,8 @@ impl StorageServer for SimpleServer { let chunk = chunk.expect("Could not find chunk"); + println!("Chunk for {:?} is at {:?}", world_position, chunk.pos); + // Find the section that the block is located in let current_section = &mut chunk.sections[world_position.y / 16]; // Find the index that the block is at, and update its state diff --git a/src/storage/world.rs b/src/storage/world.rs index f02e632..3aa05ff 100644 --- a/src/storage/world.rs +++ b/src/storage/world.rs @@ -1,4 +1,8 @@ -use std::cmp::{max, min}; +use core::fmt; +use std::{ + cmp::{max, min}, + fmt::Debug, +}; const SECTIONS_PER_CHUNK: usize = 16; const SLICE_SIZE: usize = 16 * 16; @@ -12,8 +16,8 @@ pub struct ChunkPos { impl From<&BlockPos> for ChunkPos { fn from(value: &BlockPos) -> Self { ChunkPos { - x: value.x / 16, - z: value.z / 16, + x: value.x.rem_euclid(16), + z: value.z.rem_euclid(16), } } } @@ -38,7 +42,7 @@ impl ChunkData { } // https://wiki.vg/Chunk_Format -#[derive(Debug, Clone, Copy)] +#[derive(Clone, Copy)] pub struct ChunkSection { /// The number of non-empty blocks in the section. If completely full, the /// section contains a 16 x 16 x 16 cube of blocks = 4096 blocks @@ -50,6 +54,16 @@ pub struct ChunkSection { block_states: [BlockID; 16 * 16 * 16], } +impl Debug for ChunkSection { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "ChunkSection {{ blocks: {}, states: ", self.block_count)?; + if self.block_count > 0 { + write!(f, "{:?}", self.block_states)?; + } + write!(f, " }}") + } +} + impl ChunkSection { pub fn new() -> Self { ChunkSection { diff --git a/src/tests/insert_one.rs b/src/tests/insert_one.rs index 7a0c1b5..7907ac6 100644 --- a/src/tests/insert_one.rs +++ b/src/tests/insert_one.rs @@ -37,9 +37,72 @@ mod tests { server.change_block(BlockID::Generic, &BlockPos::new(0, 0, 0)); + // Make sure the server only creates one chunk + assert_eq!(server.num_chunks(), 1); + + // Retrieve one value assert_eq!( server.read_block_at(&BlockPos::new(0, 0, 0)), BlockID::Generic ); + + // Retrieve an empty value in the current chunk + assert_eq!( + server.read_block_at(&BlockPos::new(1, 1, 1)), + BlockID::Empty + ); + + // Retrieve a value in an empty chunk + assert_eq!( + server.read_block_at(&BlockPos::new(32, 32, 32)), + BlockID::Empty + ); + + // Make sure a chunk was not created on that read + assert_eq!(server.num_chunks(), 1); + } + + #[test] + fn test_remove_one_block() { + let mut server = SimpleServer::new(); + + let pos = BlockPos::new(0, 0, 0); + + server.change_block(BlockID::Generic, &pos); + + assert_eq!(server.num_chunks(), 1); + + assert_eq!(server.read_block_at(&pos), BlockID::Generic); + + server.change_block(BlockID::Empty, &pos); + + assert_eq!(server.read_block_at(&pos), BlockID::Empty); + } + + #[test] + fn test_insert_some_blocks() { + let mut server = SimpleServer::new(); + + let blocks = [ + BlockPos::new(0, 2, 0), + BlockPos::new(0, 2, 1), + BlockPos::new(0, 2, -1), + BlockPos::new(1, 2, 0), + BlockPos::new(-1, 2, 0), + BlockPos::new(0, 3, 0), + BlockPos::new(0, 0, 0), + ]; + + for pos in blocks.iter() { + server.change_block(BlockID::Generic, pos); + } + + assert_eq!(server.num_chunks(), 1); + + for pos in blocks.iter() { + let read = server.read_block_at(pos); + println!("Pos: {:?}, {:?}", pos, read); + assert_eq!(read, BlockID::Generic); + } } }