From 547f66d214656313f32fff89b9b0faa9c5ab0269 Mon Sep 17 00:00:00 2001 From: Piotrek Date: Sat, 8 May 2021 18:42:32 +0200 Subject: [PATCH] Saving world to file --- Cargo.lock | 44 ++++++++++++++++++++++++++++++++++++++ Cargo.toml | 3 ++- src/app/mod.rs | 45 +++++++++++++++++++++++++-------------- src/app/player.rs | 11 +++++++--- src/app/world/block.rs | 3 +++ src/app/world/chunk.rs | 23 ++++++++++++++++++++ src/app/world/mod.rs | 21 ++++++++++++++++++ src/renderer/passes/ui.rs | 9 -------- 8 files changed, 130 insertions(+), 29 deletions(-) delete mode 100644 src/renderer/passes/ui.rs diff --git a/Cargo.lock b/Cargo.lock index 7766202..8e4e7d6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -444,6 +444,26 @@ dependencies = [ "syn", ] +[[package]] +name = "dirs" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30baa043103c9d0c2a57cf537cc2f35623889dc0d405e6c3cccfadbc81c71309" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780" +dependencies = [ + "libc", + "redox_users", + "winapi 0.3.9", +] + [[package]] name = "dispatch" version = "0.2.0" @@ -486,6 +506,18 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d" +[[package]] +name = "flate2" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd3aec53de10fe96d7d8c565eb17f2c687bb5518a2ec453b5b1252964526abe0" +dependencies = [ + "cfg-if 1.0.0", + "crc32fast", + "libc", + "miniz_oxide 0.4.4", +] + [[package]] name = "fnv" version = "1.0.7" @@ -1710,6 +1742,16 @@ dependencies = [ "bitflags", ] +[[package]] +name = "redox_users" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" +dependencies = [ + "getrandom 0.2.2", + "redox_syscall", +] + [[package]] name = "rustc-hash" version = "1.1.0" @@ -2239,6 +2281,8 @@ dependencies = [ "bytemuck", "byteorder", "cgmath", + "dirs", + "flate2", "fs_extra", "futures", "glob", diff --git a/Cargo.toml b/Cargo.toml index 6ce601b..fc5a24c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,8 @@ image = "0.23.14" cgmath = "0.18" rand = "0.8" noise = "0.7" - +dirs = "3.0" +flate2 = "1.0" [build-dependencies] anyhow = "1.0" diff --git a/src/app/mod.rs b/src/app/mod.rs index 5b673e9..1a77d8b 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -1,40 +1,53 @@ mod camera_controller; +mod player; pub mod world; +use std::time::Instant; use crate::renderer::content_view::ContentView; use cgmath::{SquareMatrix, Point3, InnerSpace}; use winit::event::Event; use crate::renderer::{camera::CameraTransform}; -use camera_controller::CameraController; +use player::Player; use world::World; + pub enum GameState { Paused, Running } pub struct App { - camera_controller: CameraController, + player: Player, world: World } impl App { pub fn new(content: &mut dyn ContentView) -> Self { let mut app = Self { - camera_controller: CameraController::new(), + player: Player::new(), world: World::new("default".to_string()) }; - let pos = &Point3{x:0,y:0,z:0}; - let block = app.world.gen_block(pos); - content.write(pos, block); + 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 pos = &Point3{x:1,y:0,z:0}; - let block = app.world.gen_block(pos); - content.write(pos, block); + // let pos = &Point3{x:1,y:0,z:0}; + // let block = app.world.gen_block(pos); + // content.write(pos, block); - let pos = &Point3{x:0,y:0,z:1}; - let block = app.world.gen_block(pos); - content.write(pos, block); + // let pos = &Point3{x:0,y:0,z:1}; + // let block = app.world.gen_block(pos); + // content.write(pos, block); println!("App initialized"); app @@ -42,16 +55,16 @@ impl App { pub fn input(&mut self, event: &Event<()>) { // Update camera controller - self.camera_controller.handle_input(event); + self.player.camera_controller.handle_input(event); } pub fn update_state(&mut self, requested_state: GameState) -> GameState { match requested_state { GameState::Paused => { - self.camera_controller.set_enabled(false); + self.player.camera_controller.set_enabled(false); } GameState::Running => { - self.camera_controller.set_enabled(true); + self.player.camera_controller.set_enabled(true); } }; @@ -60,6 +73,6 @@ impl App { } pub fn update_camera(&mut self, delta: f32, camera_transform: &mut dyn CameraTransform) { - self.camera_controller.update(delta, camera_transform); + self.player.camera_controller.update(delta, camera_transform); } } \ No newline at end of file diff --git a/src/app/player.rs b/src/app/player.rs index 0ca12b3..80ce5c7 100644 --- a/src/app/player.rs +++ b/src/app/player.rs @@ -1,8 +1,13 @@ +use super::camera_controller::CameraController; -struct Player { - camera_controller: CameraController +pub struct Player { + pub camera_controller: CameraController } impl Player { - + pub fn new() -> Self { + Self { + camera_controller: CameraController::new() + } + } } \ No newline at end of file diff --git a/src/app/world/block.rs b/src/app/world/block.rs index 59b08ed..8908e85 100644 --- a/src/app/world/block.rs +++ b/src/app/world/block.rs @@ -1,4 +1,7 @@ use cgmath::Point3; +use std::iter::FromIterator; +use std::io::Write; +use flate2::{write::DeflateEncoder, Compression}; pub const SIZE: usize = 32; diff --git a/src/app/world/chunk.rs b/src/app/world/chunk.rs index 43c200b..799ea30 100644 --- a/src/app/world/chunk.rs +++ b/src/app/world/chunk.rs @@ -1,4 +1,9 @@ +use flate2::Compression; +use flate2::write::DeflateEncoder; +use byteorder::LittleEndian; +use byteorder::ByteOrder; use cgmath::Point3; +use std::io::Write; use crate::app::world::WorldBlock; pub const SIZE: u32 = 32; @@ -30,4 +35,22 @@ impl WorldChunk { // 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*SIZE*SIZE*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 + } } \ No newline at end of file diff --git a/src/app/world/mod.rs b/src/app/world/mod.rs index 3e92d47..8ef8dba 100644 --- a/src/app/world/mod.rs +++ b/src/app/world/mod.rs @@ -1,6 +1,10 @@ mod generator; pub mod chunk; pub mod block; +use std::path::PathBuf; +use std::path::Path; +use std::io::Write; +use std::fs; use cgmath::Point3; use std::collections::HashMap; use generator::WorldGen; @@ -21,6 +25,23 @@ impl World { } } + pub fn save(&self) { + // Get directory + let mut dir = dirs::data_local_dir().unwrap(); + dir.push("Voxelgame"); + fs::create_dir_all(&dir).expect("Failed to create directory"); + + // Save all chunks + for (pos, chunk) in self.chunks.iter() { + let bytes = chunk.to_bytes(); + let filename = format!("chunk_{}_{}_{}.dat", pos.x, pos.y, pos.z); + let path: PathBuf = [dir.to_str().unwrap(), &filename].iter().collect(); + + let mut file = fs::File::create(path).expect("Failed to create file"); + file.write(&bytes).unwrap(); + } + } + 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; diff --git a/src/renderer/passes/ui.rs b/src/renderer/passes/ui.rs deleted file mode 100644 index 4112dfe..0000000 --- a/src/renderer/passes/ui.rs +++ /dev/null @@ -1,9 +0,0 @@ -use crate::renderer::buffers::Buffers; - -pub struct UserInterfacePass { - pub pipeline: wgpu::RenderPipeline -} - -impl UserInterfacePass { - -} \ No newline at end of file