use std::time::Instant; use flate2::Compression; use flate2::write::DeflateEncoder; use flate2::read::DeflateDecoder; use byteorder::LittleEndian; use byteorder::ByteOrder; use cgmath::Point3; use std::io::Write; use std::convert::TryInto; use std::io::Read; use crate::game::world::{WorldBlock, block}; pub const SIZE: usize = 32; const SIZE_SQ: usize = SIZE*SIZE; const SIZE_QB: usize = SIZE*SIZE*SIZE; pub struct WorldChunk { nodes: Box<[u32]>, blocks: Vec } impl WorldChunk { pub fn new() -> Self { Self { nodes: vec![0_u32; SIZE_QB as usize].into_boxed_slice(), blocks: Vec::new() } } pub fn from_bytes(bytes: Vec) -> Self { let mut instance = Self::new(); let (node_bytes, block_bytes) = bytes.split_at((SIZE_QB*4) as usize); // Nodes let mut num_blocks = 0; for i in 0..SIZE_QB { let idx = (i*4) as usize; let val = u32::from_le_bytes([node_bytes[idx], node_bytes[idx+1], node_bytes[idx+2], node_bytes[idx+3]]); instance.nodes[i as usize] = val; if val > 0 { num_blocks+=1; } } // Blocks let mut decoder = DeflateDecoder::new(block_bytes); let mut block_bytes = Vec::with_capacity(SIZE_QB); decoder.read_to_end(&mut block_bytes).expect("Failed to decode"); for i in 0..num_blocks { let mut block = WorldBlock::new(); let idx = i * block::SIZE_QB; block.materials.clone_from_slice(&block_bytes[idx..idx+block::SIZE_QB]); instance.blocks.push(block); } instance } pub fn all_blocks(&self) -> Vec<(Point3, &WorldBlock)> { self.nodes.iter().enumerate() .filter(|(_, n)| **n != 0) .map(|(index, node)| { let mut idx = index; let z = idx / SIZE_SQ; idx -= z * SIZE_SQ; let y = idx / SIZE; let x = idx % SIZE; let pos = Point3{x: x as u32, y: y as u32, z: z as u32}; let block = &self.blocks[(*node-1) as usize]; (pos, block) }) .collect() } pub fn get_block(&mut self, block_pos: &Point3) -> &mut WorldBlock { // Get block index let index = (block_pos.x + SIZE as u32 * (block_pos.y + SIZE as u32 * block_pos.z)) as usize; let mut value = self.nodes[index]; // Allocate new block if value == 0 { value = (self.blocks.len() + 1) as u32; self.nodes[index] = value; self.blocks.push(WorldBlock::new()); } // Return block reference &mut self.blocks[(value-1) as usize] } pub fn to_bytes(&self) -> Vec { let mut bytes = Vec::with_capacity(self.nodes.len()*4 + self.blocks.len()* 32*32*32); // Nodes let mut node_bytes = [0_u8; (SIZE_QB*4) as usize]; LittleEndian::write_u32_into(&self.nodes, &mut node_bytes); bytes.extend(node_bytes.iter()); // Blocks let mut encoder = DeflateEncoder::new(Vec::new(), Compression::fast()); for block in self.blocks.iter() { encoder.write_all(&block.materials).unwrap(); } bytes.extend(encoder.finish().unwrap()); bytes } }