Skip to content

Commit b51db0f

Browse files
committed
feat: primitive save state
1 parent c27139c commit b51db0f

File tree

9 files changed

+172
-21
lines changed

9 files changed

+172
-21
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
/target
22
.idea
33
.vscode
4-
data.txt
4+
data.txt
5+
chunks

Cargo.lock

Lines changed: 12 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,18 @@ edition = "2021"
66
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
77

88
[dependencies]
9-
winit = { version = "0.29" , features=[ "rwh_05", "rwh_06"] }
9+
winit = { version = "0.29", features = ["rwh_05", "rwh_06"] }
1010
env_logger = "0.10"
1111
log = "0.4"
1212
wgpu = "0.18"
1313
pollster = "0.3.0"
14-
bytemuck = { version = "1.14.0" , features= ["derive"] }
15-
tobj = { version = "3.2.1", features = ["async"]}
16-
glam = { version = "0.24.2" , features=["bytemuck"]}
14+
bytemuck = { version = "1.14.0", features = ["derive"] }
15+
tobj = { version = "3.2.1", features = ["async"] }
16+
glam = { version = "0.24.2", features = ["bytemuck"] }
1717
obj-rs = "0.7.1"
1818
lazy_static = "1.4.0"
1919
rand = "0.8.5"
20+
2021
[dependencies.image]
2122
version = "0.24.7"
2223
default-features = false

src/blocks/block.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use crate::world::CHUNK_SIZE;
55
use glam::Vec3;
66
use std::sync::MutexGuard;
77

8-
#[derive(Debug)]
98
pub struct Block {
109
pub position: glam::Vec3,
1110
pub absolute_position: glam::Vec3,

src/blocks/block_type.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use rand::random;
2+
use std::any::Any;
23

34
use super::block::{FaceDirections, TexturedBlock};
45

@@ -16,6 +17,8 @@ pub struct BlockTypeConfigs {
1617
pub bottom_texture: Option<FaceTexture>,
1718
pub is_translucent: bool,
1819
}
20+
21+
#[repr(u32)]
1922
#[derive(Clone, Copy, Debug)]
2023
pub enum BlockType {
2124
Grass(BlockTypeConfigs),
@@ -26,6 +29,29 @@ pub enum BlockType {
2629
Stone(BlockTypeConfigs),
2730
}
2831
impl BlockType {
32+
pub fn from_id(id: u32) -> BlockType {
33+
match id {
34+
0 => Self::dirt(),
35+
1 => Self::water(),
36+
2 => Self::leaf(),
37+
3 => Self::stone(),
38+
4 => Self::wood(),
39+
5 => Self::grass(),
40+
_ => panic!("Invalid id")
41+
}
42+
}
43+
pub fn to_id(&self) -> u32 {
44+
// meh
45+
match self {
46+
Self::Grass(f) => f.id,
47+
Self::Dirt(f) => f.id,
48+
Self::Water(f) => f.id,
49+
Self::Wood(f) => f.id,
50+
Self::Leaf(f) => f.id,
51+
Self::Stone(f) => f.id,
52+
}
53+
}
54+
2955
pub fn dirt() -> Self {
3056
Self::Dirt(BlockTypeConfigs {
3157
id: 0,

src/chunk.rs

Lines changed: 103 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
1+
use crate::persistance::{Loadable, Saveable};
12
use crate::{
23
blocks::{
34
block::{Block, BlockVertexData, FaceDirections},
45
block_type::BlockType,
56
},
67
structures::Structure,
7-
utils::{ChunkFromPosition, RelativeFromAbsolute},
88
world::{NoiseData, CHUNK_SIZE, MAX_TREES_PER_CHUNK, NOISE_CHUNK_PER_ROW, NOISE_SIZE},
99
};
1010
use glam::Vec3;
11+
use std::any::Any;
12+
use std::error::Error;
1113
use std::sync::{Arc, Mutex};
1214
use wgpu::util::DeviceExt;
1315

@@ -302,7 +304,11 @@ impl Chunk {
302304
chunk_data_layout: Arc<wgpu::BindGroupLayout>,
303305
other_chunks: Vec<Arc<Mutex<Chunk>>>,
304306
) -> Self {
305-
let blocks = Self::create_blocks_data(x, y, noise_data.clone());
307+
let blocks = if let Ok(blocks) = Self::load(Box::new((x, y))) {
308+
blocks
309+
} else {
310+
Self::create_blocks_data(x, y, noise_data.clone())
311+
};
306312

307313
let chunk_position_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
308314
contents: bytemuck::cast_slice(&[x, y]),
@@ -339,3 +345,98 @@ impl Chunk {
339345
return chunk;
340346
}
341347
}
348+
349+
impl Saveable<Chunk> for Chunk {
350+
fn save(&self) -> Result<(), Box<dyn Error>> {
351+
if let Ok(_) = std::fs::create_dir("chunks") {
352+
println!("Created dir");
353+
}
354+
let mut data = String::new();
355+
356+
for col in self.blocks.iter() {
357+
for block in col.iter() {
358+
if let Some(block_ptr) = block {
359+
let blockbrw = block_ptr.lock().unwrap();
360+
data += &format!(
361+
"{},{},{},{}\n",
362+
blockbrw.position.x,
363+
blockbrw.position.y,
364+
blockbrw.position.z,
365+
blockbrw.block_type.to_id()
366+
);
367+
}
368+
}
369+
}
370+
371+
let chunk_file_name = format!("chunks/chunk{}_{}", self.x, self.y);
372+
std::fs::write(chunk_file_name.clone(), data.as_bytes())?;
373+
374+
Ok(())
375+
}
376+
}
377+
378+
impl Loadable<BlockVec> for Chunk {
379+
fn load(args: Box<dyn Any>) -> Result<BlockVec, Box<dyn Error>> {
380+
if let Ok(chunk_position) = args.downcast::<(i32, i32)>() {
381+
for entry in std::fs::read_dir("chunks")? {
382+
let file = entry?;
383+
let filename_chunk = file.file_name();
384+
let mut coords = filename_chunk
385+
.to_str()
386+
.unwrap()
387+
.split("k")
388+
.last()
389+
.expect("Invalid filename")
390+
.split("_");
391+
let x = coords.next().unwrap().parse::<i32>().unwrap();
392+
let y = coords.next().unwrap().parse::<i32>().unwrap();
393+
394+
let mut blocks: BlockVec = vec![];
395+
if *chunk_position == (x, y) {
396+
let file_contents =
397+
std::fs::read_to_string(format!("chunks/chunk{}_{}", x, y))?;
398+
for line in file_contents.lines() {
399+
let mut i = line.split(",");
400+
let bx = i.next().unwrap().parse::<u32>()?;
401+
let by = i.next().unwrap().parse::<u32>()?;
402+
let bz = i.next().unwrap().parse::<u32>()?;
403+
let block_type = i.next().unwrap().parse::<u32>()?;
404+
let block_type = BlockType::from_id(block_type);
405+
406+
let block = Block::new(
407+
glam::vec3(bx as f32, by as f32, bz as f32),
408+
(x, y),
409+
block_type,
410+
);
411+
412+
if let None = blocks.get_mut(
413+
(block.position.x as u32 * CHUNK_SIZE + block.position.z as u32)
414+
as usize,
415+
) {
416+
// This works only because chunks rows are in order
417+
blocks.push(vec![]);
418+
}
419+
let y_blocks = blocks
420+
.get_mut(
421+
(block.position.x as u32 * CHUNK_SIZE + block.position.z as u32)
422+
as usize,
423+
)
424+
.unwrap();
425+
426+
let start_len = y_blocks.len();
427+
let y_position = block.position.y as usize;
428+
429+
for i in start_len..=y_position {
430+
if i >= y_blocks.len() {
431+
y_blocks.push(None);
432+
}
433+
}
434+
y_blocks[y_position] = Some(Arc::new(Mutex::new(block)));
435+
}
436+
return Ok(blocks);
437+
}
438+
}
439+
}
440+
return Err("Not valid args".into());
441+
}
442+
}

src/main.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ pub mod blocks;
3434
pub mod chunk;
3535
pub mod collision;
3636
pub mod material;
37+
mod persistance;
3738
pub mod pipeline;
3839
pub mod player;
3940
pub mod state;
@@ -84,7 +85,10 @@ async fn run(event_loop: EventLoop<()>, window: Window) {
8485
..
8586
},
8687
..
87-
} => target.exit(),
88+
} => {
89+
state.world.save_state();
90+
target.exit();
91+
},
8892

8993
WindowEvent::KeyboardInput { event, .. } => {
9094
state.handle_keypress(event, delta_time.as_secs_f32())

src/persistance.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
use std::any::Any;
2+
use std::error::Error;
3+
4+
pub trait Saveable<T> {
5+
fn save(&self) -> Result<(), Box<dyn Error>>;
6+
}
7+
8+
pub trait Loadable<T> {
9+
fn load(args: Box<dyn Any>) -> Result<T, Box<dyn Error>>;
10+
}

src/world.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use std::{
44
thread,
55
};
66

7+
use crate::persistance::Saveable;
78
use crate::utils::{ChunkFromPosition, RelativeFromAbsolute};
89
use crate::{blocks::block::Block, chunk::Chunk, player::Player, utils::threadpool::ThreadPool};
910

@@ -282,6 +283,14 @@ impl World {
282283

283284
player.current_chunk = current_chunk;
284285
}
286+
pub fn save_state(&self) {
287+
288+
// TODO: Player position
289+
for chunk in self.chunks.iter() {
290+
let chunkbrw = chunk.lock().unwrap();
291+
chunkbrw.save().unwrap();
292+
}
293+
}
285294
pub fn init_chunks(&mut self) {
286295
let (sender, receiver) = mpsc::channel();
287296

0 commit comments

Comments
 (0)