From d0b7a781b4818bf3539341f77ff1f7a9bb0bb479 Mon Sep 17 00:00:00 2001 From: Piotrek Date: Sat, 8 May 2021 22:55:25 +0200 Subject: [PATCH] Loading world, not working yet --- src/app/mod.rs | 27 ++++++++++++++----------- src/app/world/block.rs | 5 +++-- src/app/world/chunk.rs | 45 +++++++++++++++++++++++++++++++++++------- src/app/world/mod.rs | 34 +++++++++++++++++++++++++++++++ 4 files changed, 91 insertions(+), 20 deletions(-) diff --git a/src/app/mod.rs b/src/app/mod.rs index 1a77d8b..4af6e5c 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -27,19 +27,24 @@ impl App { world: World::new("default".to_string()) }; - let timer = Instant::now(); - for x in 0..16 { - for z in 0..16 { - let pos = &Point3{x,y:0,z}; - let block = app.world.gen_block(pos); - content.write(pos, block); - } - } - println!("Generated in {}", timer.elapsed().as_secs_f32()); + + // let timer = Instant::now(); + // for x in 0..16 { + // for z in 0..16 { + // let pos = &Point3{x,y:0,z}; + // let block = app.world.gen_block(pos); + // content.write(pos, block); + // } + // } + // println!("Generated in {}", timer.elapsed().as_secs_f32()); + // let timer = Instant::now(); + // app.world.save(); + // println!("Saved in {}", timer.elapsed().as_secs_f32()); + let timer = Instant::now(); - app.world.save(); - println!("Saved in {}", timer.elapsed().as_secs_f32()); + app.world.load(); + println!("Loaded in {}", timer.elapsed().as_secs_f32()); // let pos = &Point3{x:1,y:0,z:0}; // let block = app.world.gen_block(pos); diff --git a/src/app/world/block.rs b/src/app/world/block.rs index 8908e85..8d2a9e8 100644 --- a/src/app/world/block.rs +++ b/src/app/world/block.rs @@ -4,17 +4,18 @@ use std::io::Write; use flate2::{write::DeflateEncoder, Compression}; pub const SIZE: usize = 32; +pub const SIZE_QB: usize = SIZE*SIZE*SIZE; #[derive(Clone)] pub struct WorldBlock { - pub materials: [u8;(SIZE*SIZE*SIZE) as usize] + pub materials: [u8;SIZE_QB] } impl WorldBlock { pub fn new() -> Self { Self { - materials: [0_u8; (SIZE*SIZE*SIZE) as usize] + materials: [0_u8; SIZE_QB] } } diff --git a/src/app/world/chunk.rs b/src/app/world/chunk.rs index 799ea30..a527064 100644 --- a/src/app/world/chunk.rs +++ b/src/app/world/chunk.rs @@ -1,13 +1,15 @@ 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 crate::app::world::WorldBlock; +use std::convert::TryInto; +use crate::app::world::{WorldBlock, block}; pub const SIZE: u32 = 32; - +const SIZE_QB: u32 = SIZE*SIZE*SIZE; pub struct WorldChunk { nodes: Box<[u32]>, @@ -17,7 +19,7 @@ pub struct WorldChunk { impl WorldChunk { pub fn new() -> Self { Self { - nodes: vec![0_u32; (SIZE*SIZE*SIZE) as usize].into_boxed_slice(), + nodes: vec![0_u32; SIZE_QB as usize].into_boxed_slice(), blocks: Vec::new() } } @@ -40,17 +42,46 @@ impl WorldChunk { let mut bytes = Vec::with_capacity(self.nodes.len()*4 + self.blocks.len()* 32*32*32); // Nodes - let mut node_bytes = [0_u8; (SIZE*SIZE*SIZE*4) as usize]; + 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()); + // 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()); + for block in self.blocks.iter() { - encoder.write_all(&block.materials).unwrap(); + bytes.extend(&block.materials); } - bytes.extend(encoder.finish().unwrap()); bytes } + + 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 + for i in 0..SIZE_QB { + let idx = (i*4) as usize; + instance.nodes[i as usize] = u32::from_le_bytes([node_bytes[idx], node_bytes[idx+1], node_bytes[idx+2], node_bytes[idx+3]]); + } + + // Blocks + let block_num = block_bytes.len() / block::SIZE_QB; + println!("block_num {}", block_num); + for i in 0..block_num { + let mut block = WorldBlock::new(); + let idx = i * block::SIZE_QB; + for j in 0..block::SIZE_QB { + block.materials[j] = block_bytes[idx+j]; + } + instance.blocks.push(block); + } + + instance + } } \ No newline at end of file diff --git a/src/app/world/mod.rs b/src/app/world/mod.rs index 8ef8dba..5220b57 100644 --- a/src/app/world/mod.rs +++ b/src/app/world/mod.rs @@ -4,6 +4,7 @@ pub mod block; use std::path::PathBuf; use std::path::Path; use std::io::Write; +use std::io::Read; use std::fs; use cgmath::Point3; use std::collections::HashMap; @@ -42,6 +43,39 @@ impl World { } } + pub fn load(&mut self) { + // Get directory + let mut dir = dirs::data_local_dir().unwrap(); + dir.push("Voxelgame"); + if !dir.is_dir() { + println!("Not exists: {:?}", dir); + return; + } + + // Load all chunks + for entry in fs::read_dir(dir).unwrap() { + let path: PathBuf = entry.unwrap().path(); + if path.extension().unwrap().to_str() != Some("dat") { + continue; + } + let stem = path.file_stem().unwrap().to_str().unwrap(); + if !stem.starts_with("chunk") { + continue; + } + + let s: Vec<&str> = stem.split("_").collect(); + let pos = Point3{x: s[1].parse::().unwrap(), y: s[2].parse::().unwrap(), z: s[3].parse::().unwrap()}; + + let mut bytes = Vec::new(); + let mut file = fs::File::open(path).expect("Failed to open file"); + file.read_to_end(&mut bytes).expect("Failed to read file"); + let chunk = WorldChunk::from_bytes(bytes); + + println!("loaded {:?}", pos); + self.chunks.insert(pos, chunk); + } + } + pub fn gen_block(&mut self, block_pos: &Point3) -> &WorldBlock { // Split world space to chunk and block space let ch_pos = block_pos / chunk::SIZE;