Got a simple retrieve to pass

This commit is contained in:
Nicholas Novak 2023-10-02 15:56:33 -07:00
parent 914290fe9e
commit e5547477fc
4 changed files with 97 additions and 38 deletions

View File

@ -1,20 +1,21 @@
use crate::storage::world::{BlockID, BlockPos, BlockRange, ChunkData, ChunkPos}; use crate::storage::world::{BlockID, BlockPos, BlockRange, ChunkData, ChunkPos};
use crate::storage_server::StorageServer; use crate::storage_server::StorageServer;
#[derive(Clone)] #[derive(Debug, Clone)]
struct SingleBlock { struct SingleBlock {
id: BlockID, id: BlockID,
position: BlockPos, position: BlockPos,
} }
#[derive(Debug)]
struct MultipleBlocks { struct MultipleBlocks {
id: BlockID, id: BlockID,
range: BlockRange, range: BlockRange,
} }
#[derive(Debug)]
pub struct SimpleServer { pub struct SimpleServer {
chunks: Vec<ChunkData>, chunks: Vec<ChunkData>,
single_blocks: Vec<SingleBlock>,
block_ranges: Vec<MultipleBlocks>, block_ranges: Vec<MultipleBlocks>,
} }
@ -22,44 +23,79 @@ impl SimpleServer {
pub fn new() -> Self { pub fn new() -> Self {
SimpleServer { SimpleServer {
chunks: Vec::new(), chunks: Vec::new(),
single_blocks: Vec::new(),
block_ranges: Vec::new(), block_ranges: Vec::new(),
} }
} }
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);
// Find the chunk with the correct index
for chunk in self.chunks.iter_mut() {
if chunk.pos == chunk_pos {
return Some(chunk);
}
}
None
}
fn chunk_at(&self, block_pos: &BlockPos) -> Option<&ChunkData> {
let chunk_pos = ChunkPos::from(block_pos);
for chunk in self.chunks.iter() {
if chunk.pos == chunk_pos {
return Some(chunk);
}
}
None
}
fn create_chunk_at(&mut self, chunk_pos: &ChunkPos) {
let new_chunk = ChunkData::new(chunk_pos);
self.chunks.push(new_chunk);
}
} }
impl StorageServer for SimpleServer { impl StorageServer for SimpleServer {
fn change_block(&mut self, target_state: BlockID, world_position: BlockPos) { fn change_block(&mut self, target_state: BlockID, world_position: &BlockPos) {
let chunk_pos = ChunkPos::from(&world_position); let mut chunk = self.chunk_at_block_mut(world_position);
println!("Chunk position: {:?}", chunk_pos); // Test if there is a chunk that already exists
if chunk.is_none() {
for chunk in self.chunks.iter_mut() { self.create_chunk_at(&ChunkPos::from(world_position));
if chunk.pos.same_location(&chunk_pos) { chunk = self.chunk_at_block_mut(world_position);
let current_section = &mut chunk.sections[world_position.y / 16];
let chunk_array_index = current_section.index_of_block(&world_position);
current_section.update_block_at_index(&target_state, chunk_array_index);
}
} }
self.single_blocks.push(SingleBlock { let chunk = chunk.expect("Could not find chunk");
id: target_state,
position: world_position, // 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
let chunk_array_index = current_section.index_of_block(&world_position);
current_section.update_block_at_index(&target_state, chunk_array_index);
} }
fn change_block_range(&mut self, target_stage: BlockID, start: BlockPos, end: BlockPos) { fn change_block_range(&mut self, target_stage: BlockID, start: &BlockPos, end: &BlockPos) {
self.block_ranges.push(MultipleBlocks { self.block_ranges.push(MultipleBlocks {
id: target_stage, id: target_stage,
range: BlockRange { start, end }, range: BlockRange {
start: start.clone(),
end: end.clone(),
},
}) })
} }
fn read_block_at(&self, pos: BlockPos) -> BlockID { fn read_block_at(&self, pos: &BlockPos) -> BlockID {
for block in self.single_blocks.iter() { let chunk = self.chunk_at(pos);
if block.position == pos {
return block.id.clone(); if let Some(chunk) = chunk {
} let chunk_section = chunk.section_for(pos);
return chunk_section.get_block_at_index(pos).clone();
} }
for blocks in self.block_ranges.iter() { for blocks in self.block_ranges.iter() {

View File

@ -3,7 +3,7 @@ use std::cmp::{max, min};
const SECTIONS_PER_CHUNK: usize = 16; const SECTIONS_PER_CHUNK: usize = 16;
const SLICE_SIZE: usize = 16 * 16; const SLICE_SIZE: usize = 16 * 16;
#[derive(Debug)] #[derive(Debug, Clone, PartialEq)]
pub struct ChunkPos { pub struct ChunkPos {
pub x: isize, pub x: isize,
pub z: isize, pub z: isize,
@ -18,18 +18,27 @@ impl From<&BlockPos> for ChunkPos {
} }
} }
impl ChunkPos { #[derive(Debug)]
pub fn same_location(&self, other: &ChunkPos) -> bool {
self.x == other.x && self.z == other.z
}
}
pub struct ChunkData { pub struct ChunkData {
pub pos: ChunkPos, pub pos: ChunkPos,
pub sections: [ChunkSection; SECTIONS_PER_CHUNK], pub sections: [ChunkSection; SECTIONS_PER_CHUNK],
} }
impl ChunkData {
pub fn new(pos: &ChunkPos) -> Self {
ChunkData {
pos: pos.clone(),
sections: [ChunkSection::new(); SECTIONS_PER_CHUNK],
}
}
pub fn section_for(&self, block_pos: &BlockPos) -> &ChunkSection {
&self.sections[block_pos.y % 16]
}
}
// https://wiki.vg/Chunk_Format // https://wiki.vg/Chunk_Format
#[derive(Debug, Clone, Copy)]
pub struct ChunkSection { pub struct ChunkSection {
/// The number of non-empty blocks in the section. If completely full, the /// 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 /// section contains a 16 x 16 x 16 cube of blocks = 4096 blocks
@ -42,6 +51,13 @@ pub struct ChunkSection {
} }
impl ChunkSection { impl ChunkSection {
pub fn new() -> Self {
ChunkSection {
block_count: 0,
block_states: [BlockID::Empty; 16 * 16 * 16],
}
}
pub fn index_of_block(&self, pos: &BlockPos) -> usize { pub fn index_of_block(&self, pos: &BlockPos) -> usize {
let base_x = pos.x.rem_euclid(16) as usize; let base_x = pos.x.rem_euclid(16) as usize;
let base_y = pos.y.rem_euclid(16) as usize; let base_y = pos.y.rem_euclid(16) as usize;
@ -74,6 +90,12 @@ impl ChunkSection {
self.block_states[index] = id.clone(); self.block_states[index] = id.clone();
} }
pub fn get_block_at_index(&self, pos: &BlockPos) -> &BlockID {
let array_index = self.index_of_block(pos);
&self.block_states[array_index]
}
} }
/// `BlockPos` represents the location of a block in world space /// `BlockPos` represents the location of a block in world space
@ -91,6 +113,7 @@ impl BlockPos {
} }
/// BlockRange represents a range of blocks that have been updated /// BlockRange represents a range of blocks that have been updated
#[derive(Debug)]
pub struct BlockRange { pub struct BlockRange {
pub start: BlockPos, pub start: BlockPos,
pub end: BlockPos, pub end: BlockPos,
@ -131,7 +154,7 @@ impl BlockRange {
/// BlockID represents the type of block stored /// BlockID represents the type of block stored
#[repr(u8)] #[repr(u8)]
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub enum BlockID { pub enum BlockID {
Empty, Empty,
Generic, Generic,

View File

@ -4,12 +4,12 @@ use axum::{routing::get, Router};
pub trait StorageServer { pub trait StorageServer {
/// `change_block` changes the block at the world position given by `world_position` to the /// `change_block` changes the block at the world position given by `world_position` to the
/// target block id `BlockID` /// target block id `BlockID`
fn change_block(&mut self, target_state: BlockID, world_position: BlockPos); fn change_block(&mut self, target_state: BlockID, world_position: &BlockPos);
fn change_block_range(&mut self, target_stage: BlockID, start: BlockPos, end: BlockPos); fn change_block_range(&mut self, target_stage: BlockID, start: &BlockPos, end: &BlockPos);
/// `read_block_at` returns the id of the block at the location specified /// `read_block_at` returns the id of the block at the location specified
/// If no block is present, the returned id will be of the empty type /// If no block is present, the returned id will be of the empty type
fn read_block_at(&self, pos: BlockPos) -> BlockID; fn read_block_at(&self, pos: &BlockPos) -> BlockID;
} }
#[tokio::main] #[tokio::main]

View File

@ -26,7 +26,7 @@ mod tests {
assert!(range.within_range(&test4)); assert!(range.within_range(&test4));
assert!(range.within_range(&test5)); assert!(range.within_range(&test5));
let test6 = BlockPos::new(-1, -1, 0); let test6 = BlockPos::new(-1, 0, 0);
assert!(!range.within_range(&test6)); assert!(!range.within_range(&test6));
} }
@ -35,10 +35,10 @@ mod tests {
fn test_simple_insert() { fn test_simple_insert() {
let mut server = SimpleServer::new(); let mut server = SimpleServer::new();
server.change_block(BlockID::Generic, BlockPos::new(0, 0, 0)); server.change_block(BlockID::Generic, &BlockPos::new(0, 0, 0));
assert_eq!( assert_eq!(
server.read_block_at(BlockPos::new(0, 0, 0)), server.read_block_at(&BlockPos::new(0, 0, 0)),
BlockID::Generic BlockID::Generic
); );
} }