From 686245436a2109995fac0d25f3eafbdfb4aa0d8a Mon Sep 17 00:00:00 2001 From: Isaac Turci <78173025+Zac8668@users.noreply.github.com> Date: Wed, 10 Jan 2024 14:02:42 -0300 Subject: [PATCH] feat: Buffered Read and Write, Save player pos to file (#48) * Changed wording * Added Buffered read/write, player pos also saved --- .gitignore | 2 +- README.md | 6 +++--- src/actors.rs | 2 +- src/chunk_manager.rs | 47 ++++++++++++++++++++++++-------------------- src/main.rs | 2 +- src/player.rs | 27 ++++++++++++++++++++++--- 6 files changed, 56 insertions(+), 30 deletions(-) diff --git a/.gitignore b/.gitignore index 9d91c4e..b53288d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ /target .vscode/ -/assets/worlds/** +/assets/world/** .cargo/config.toml diff --git a/README.md b/README.md index dd16ebc..0fad773 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Powered by a similar engine as Noita, made from scratch with Rust. - Multithreaded sand simulation - GPU rendering optimizations of the sim - AABB colliders for the player and mobs - - Player with special gun to shoot and suck atoms, and also a jetpack + - Player with special gun to push and pull atoms, and also a jetpack - Bigger map, with saving/loading **What's next:** @@ -27,7 +27,7 @@ Powered by a similar engine as Noita, made from scratch with Rust. In the bigger picture we also aim to achieve intergalactic travel like Starbound, procedurally generated animations inspired by Rainworld, all the cool mechanics you see in Noita, multiplayer and modding, the last two made possible by a future engine migration to [Bones](https://github.com/fishfolk/bones/). ## Controls -Left Mouse button to suck atoms, Right Mouse button to shoot atoms. +Left Mouse button to pull atoms, Right Mouse button to push atoms. Mouse wheel to zoom in/out. ## Last Update Changelog @@ -38,7 +38,7 @@ We added: - Player - The player is pretty cool! It has some animations, a jetpack and a pretty nice tool! - Player tool - - The tool can suck atoms(Left Mouse Button), and also shoot(Right Mouse Button) the atoms you sucked! + - The tool can pull atoms(Left Mouse Button), and also push(Right Mouse Button) the atoms you pulled! - Engine Changes - We changed the Chunk Manager approach to store Chunks in a Vec to storing them in a HashMap, this lays the ground for future updates, like Save/Load worlds, and big explorable worlds. It was needed to simplify addind the other additions and unfortunately took some time to do. diff --git a/src/actors.rs b/src/actors.rs index dba64f0..5c89fc3 100644 --- a/src/actors.rs +++ b/src/actors.rs @@ -1,6 +1,6 @@ use crate::prelude::*; -#[derive(Component, Clone, Copy)] +#[derive(Component, Clone)] pub struct Actor { pub width: u8, pub height: u8, diff --git a/src/chunk_manager.rs b/src/chunk_manager.rs index d9b1d94..e97c9ca 100644 --- a/src/chunk_manager.rs +++ b/src/chunk_manager.rs @@ -113,9 +113,10 @@ impl ChunkManager { impl Drop for ChunkManager { fn drop(&mut self) { - let file = fs::read("assets/worlds/world").unwrap_or_default(); + let file = File::open("assets/world/world").unwrap(); + let mut buffered = BufReader::new(file); let mut file_chunks: HashMap = - bincode::deserialize(&file).unwrap_or_default(); + bincode::deserialize_from(&mut buffered).unwrap(); for (pos, chunk) in &self.chunks { if let Some(file_chunk) = file_chunks.get_mut(pos) { @@ -125,12 +126,9 @@ impl Drop for ChunkManager { } } - let data = bincode::serialize(&file_chunks).unwrap(); - //Save file - let _ = File::create("assets/worlds/world") - .unwrap() - .write(&data) - .unwrap(); + let file = File::create("assets/world/world").unwrap(); + let mut buffered = BufWriter::new(file); + bincode::serialize_into(&mut buffered, &file_chunks).unwrap(); } } @@ -177,8 +175,16 @@ pub fn manager_setup( let mut images_vec = vec![]; chunk_manager.pos = ivec2(-16, -16); - let file = fs::read("assets/worlds/world").unwrap_or_default(); - let file_chunks: HashMap = bincode::deserialize(&file).unwrap_or_default(); + let file_chunks: HashMap; + if let Ok(file) = File::open("assets/world/world") { + let mut buffered = BufReader::new(file); + file_chunks = bincode::deserialize_from(&mut buffered).unwrap(); + } else { + file_chunks = HashMap::new(); + let file = File::create("assets/world/world").unwrap(); + let mut buffered = BufWriter::new(file); + bincode::serialize_into(&mut buffered, &file_chunks).unwrap(); + } for (x, y) in (chunk_manager.pos.x..chunk_manager.pos.x + width) .cartesian_product(chunk_manager.pos.y..chunk_manager.pos.y + height) @@ -543,14 +549,16 @@ pub fn update_manager_pos( if new_diff != IVec2::ZERO { task_executor.start(async move { - let file = fs::read("assets/worlds/world").unwrap_or_default(); + let file = File::open("assets/world/world").unwrap(); + let mut buffered = BufReader::new(file); + let chunks: HashMap = - bincode::deserialize(&file).unwrap_or_default(); + bincode::deserialize_from(&mut buffered).unwrap(); (chunks, new_diff) }); } } - AsyncTaskStatus::Finished((mut file, diff)) => { + AsyncTaskStatus::Finished((mut file_chunks, diff)) => { let chunk_textures = chunk_textures.single(); for _ in 0..diff.x.abs() { chunk_manager.move_manager( @@ -558,7 +566,7 @@ pub fn update_manager_pos( &mut images, &chunk_textures, &image_entities, - &mut file, + &mut file_chunks, MoveDir::X(diff.x.signum()), ); } @@ -569,19 +577,16 @@ pub fn update_manager_pos( &mut images, &chunk_textures, &image_entities, - &mut file, + &mut file_chunks, MoveDir::Y(diff.y.signum()), ); } let pool = AsyncComputeTaskPool::get(); saving_task.0 = Some(pool.spawn(async move { - let data = bincode::serialize(&file).unwrap(); - //Save file - let _ = File::create("assets/worlds/world") - .unwrap() - .write(&data) - .unwrap(); + let file = File::create("assets/world/world").unwrap(); + let mut buffered = BufWriter::new(file); + bincode::serialize_into(&mut buffered, &file_chunks).unwrap(); })); } AsyncTaskStatus::Pending => {} diff --git a/src/main.rs b/src/main.rs index 3b73ace..5722a73 100644 --- a/src/main.rs +++ b/src/main.rs @@ -30,9 +30,9 @@ mod prelude { pub use std::collections::{HashMap, HashSet}; pub use std::env; - pub use std::fs; pub use std::fs::File; pub use std::io::Write; + pub use std::io::{BufReader, BufWriter}; pub use crate::materials::Material; } diff --git a/src/player.rs b/src/player.rs index a90d5a0..df23b84 100644 --- a/src/player.rs +++ b/src/player.rs @@ -19,6 +19,14 @@ impl Default for Player { } } +impl Drop for Actor { + fn drop(&mut self) { + let file = File::create("assets/world/player").unwrap(); + let mut buffered = BufWriter::new(file); + bincode::serialize_into(&mut buffered, &self.pos).unwrap(); + } +} + #[derive(Default)] pub enum PlayerState { #[default] @@ -39,10 +47,21 @@ pub fn player_setup( asset_server: Res, mut texture_atlases: ResMut>, ) { + let pos: IVec2; + if let Ok(file) = File::open("assets/world/player") { + let mut buffered = BufReader::new(file); + pos = bincode::deserialize_from(&mut buffered).unwrap(); + } else { + pos = IVec2::default(); + let file = File::create("assets/world/player").unwrap(); + let mut buffered = BufWriter::new(file); + bincode::serialize_into(&mut buffered, &pos).unwrap(); + } + let player_actor = Actor { height: 17, width: 10, - pos: ivec2(0, 0), + pos, vel: vec2(0., 0.), }; @@ -221,7 +240,9 @@ pub fn tool_system( let (window, mut player) = querys; let (mut textatlas_sprite, player) = player.single_mut(); let (mut chunk_manager, mut dirty_rects, mouse) = resources; - let window = window.single(); + let Ok(window) = window.get_single() else { + return; + }; let materials = materials.0.get(materials.1 .0.clone()).unwrap(); if let Some(world_position) = window @@ -241,7 +262,7 @@ pub fn tool_system( tool_transform.translation.x = tool_transform.translation.x.abs() * (flip_bool as i8 * 2 - 1) as f32; - //Tool shooting and sucking atoms + //Tool pulling and pushing atoms let mut center_vec_y_flipped = center_vec; center_vec_y_flipped.y *= -1.;