Fixed loading world, added saving meta data
This commit is contained in:
Generated
+11
@@ -2287,12 +2287,14 @@ dependencies = [
|
|||||||
"futures",
|
"futures",
|
||||||
"glob",
|
"glob",
|
||||||
"image",
|
"image",
|
||||||
|
"linked-hash-map",
|
||||||
"noise",
|
"noise",
|
||||||
"rand 0.8.3",
|
"rand 0.8.3",
|
||||||
"shaderc",
|
"shaderc",
|
||||||
"wgpu",
|
"wgpu",
|
||||||
"wgpu_glyph",
|
"wgpu_glyph",
|
||||||
"winit",
|
"winit",
|
||||||
|
"yaml-rust",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2426,3 +2428,12 @@ name = "xml-rs"
|
|||||||
version = "0.8.3"
|
version = "0.8.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b07db065a5cf61a7e4ba64f29e67db906fb1787316516c4e6e5ff0fea1efcd8a"
|
checksum = "b07db065a5cf61a7e4ba64f29e67db906fb1787316516c4e6e5ff0fea1efcd8a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "yaml-rust"
|
||||||
|
version = "0.4.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
|
||||||
|
dependencies = [
|
||||||
|
"linked-hash-map",
|
||||||
|
]
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ rand = "0.8"
|
|||||||
noise = "0.7"
|
noise = "0.7"
|
||||||
dirs = "3.0"
|
dirs = "3.0"
|
||||||
flate2 = "1.0"
|
flate2 = "1.0"
|
||||||
|
yaml-rust = "0.4"
|
||||||
|
linked-hash-map = "0.5"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
|
|||||||
+18
-15
@@ -28,23 +28,26 @@ impl App {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// let timer = Instant::now();
|
let timer = Instant::now();
|
||||||
// for x in 0..16 {
|
for x in 0..16 {
|
||||||
// for z in 0..16 {
|
for z in 0..16 {
|
||||||
// let pos = &Point3{x,y:0,z};
|
let pos = &Point3{x,y:0,z};
|
||||||
// let block = app.world.gen_block(pos);
|
let block = app.world.gen_block(pos);
|
||||||
// content.write(pos, block);
|
content.write(pos, block);
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// println!("Generated in {}", timer.elapsed().as_secs_f32());
|
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();
|
let timer = Instant::now();
|
||||||
app.world.load();
|
app.world.save();
|
||||||
println!("Loaded in {}", timer.elapsed().as_secs_f32());
|
println!("Saved in {}", timer.elapsed().as_secs_f32());
|
||||||
|
|
||||||
|
// let timer = Instant::now();
|
||||||
|
// app.world.load();
|
||||||
|
// for (pos, block) in app.world.all_blocks() {
|
||||||
|
// content.write(&pos, block);
|
||||||
|
// }
|
||||||
|
// println!("Loaded in {}", timer.elapsed().as_secs_f32());
|
||||||
|
|
||||||
// let pos = &Point3{x:1,y:0,z:0};
|
// let pos = &Point3{x:1,y:0,z:0};
|
||||||
// let block = app.world.gen_block(pos);
|
// let block = app.world.gen_block(pos);
|
||||||
|
|||||||
+35
-13
@@ -6,10 +6,12 @@ use byteorder::ByteOrder;
|
|||||||
use cgmath::Point3;
|
use cgmath::Point3;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
use std::io::Read;
|
||||||
use crate::app::world::{WorldBlock, block};
|
use crate::app::world::{WorldBlock, block};
|
||||||
|
|
||||||
pub const SIZE: u32 = 32;
|
pub const SIZE: usize = 32;
|
||||||
const SIZE_QB: u32 = SIZE*SIZE*SIZE;
|
const SIZE_SQ: usize = SIZE*SIZE;
|
||||||
|
const SIZE_QB: usize = SIZE*SIZE*SIZE;
|
||||||
|
|
||||||
pub struct WorldChunk {
|
pub struct WorldChunk {
|
||||||
nodes: Box<[u32]>,
|
nodes: Box<[u32]>,
|
||||||
@@ -24,9 +26,28 @@ impl WorldChunk {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn all_blocks(&self) -> Vec<(Point3<u32>, &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<u32>) -> &mut WorldBlock {
|
pub fn get_block(&mut self, block_pos: &Point3<u32>) -> &mut WorldBlock {
|
||||||
// Get block index
|
// Get block index
|
||||||
let index = (block_pos.x + SIZE * (block_pos.y + SIZE * block_pos.z)) as usize;
|
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];
|
let mut value = self.nodes[index];
|
||||||
// Allocate new block
|
// Allocate new block
|
||||||
if value == 0 {
|
if value == 0 {
|
||||||
@@ -47,15 +68,11 @@ impl WorldChunk {
|
|||||||
bytes.extend(node_bytes.iter());
|
bytes.extend(node_bytes.iter());
|
||||||
|
|
||||||
// Blocks
|
// 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() {
|
for block in self.blocks.iter() {
|
||||||
bytes.extend(&block.materials);
|
encoder.write_all(&block.materials).unwrap();
|
||||||
}
|
}
|
||||||
|
bytes.extend(encoder.finish().unwrap());
|
||||||
|
|
||||||
bytes
|
bytes
|
||||||
}
|
}
|
||||||
@@ -65,14 +82,19 @@ impl WorldChunk {
|
|||||||
let (node_bytes, block_bytes) = bytes.split_at((SIZE_QB*4) as usize);
|
let (node_bytes, block_bytes) = bytes.split_at((SIZE_QB*4) as usize);
|
||||||
|
|
||||||
// Nodes
|
// Nodes
|
||||||
|
let mut block_num = 0;
|
||||||
for i in 0..SIZE_QB {
|
for i in 0..SIZE_QB {
|
||||||
let idx = (i*4) as usize;
|
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]]);
|
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 { block_num+=1; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Blocks
|
// Blocks
|
||||||
let block_num = block_bytes.len() / block::SIZE_QB;
|
let mut decoder = DeflateDecoder::new(block_bytes);
|
||||||
println!("block_num {}", block_num);
|
let mut block_bytes = Vec::new();
|
||||||
|
decoder.read_to_end(&mut block_bytes).expect("Failed to decode");
|
||||||
|
|
||||||
for i in 0..block_num {
|
for i in 0..block_num {
|
||||||
let mut block = WorldBlock::new();
|
let mut block = WorldBlock::new();
|
||||||
let idx = i * block::SIZE_QB;
|
let idx = i * block::SIZE_QB;
|
||||||
|
|||||||
+38
-7
@@ -1,20 +1,23 @@
|
|||||||
mod generator;
|
mod generator;
|
||||||
pub mod chunk;
|
pub mod chunk;
|
||||||
pub mod block;
|
pub mod block;
|
||||||
|
use linked_hash_map::LinkedHashMap;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use cgmath::Point3;
|
use cgmath::{Point3, InnerSpace};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use generator::WorldGen;
|
use generator::WorldGen;
|
||||||
use chunk::WorldChunk;
|
use chunk::WorldChunk;
|
||||||
use block::WorldBlock;
|
use block::WorldBlock;
|
||||||
|
use yaml_rust::{Yaml, YamlLoader, YamlEmitter};
|
||||||
|
|
||||||
|
|
||||||
pub struct World {
|
pub struct World {
|
||||||
name: String,
|
name: String,
|
||||||
chunks: HashMap<Point3<u32>, WorldChunk>
|
chunks: HashMap<Point3<u32>, WorldChunk>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl World {
|
impl World {
|
||||||
@@ -22,10 +25,23 @@ impl World {
|
|||||||
pub fn new(name: String) -> Self {
|
pub fn new(name: String) -> Self {
|
||||||
Self {
|
Self {
|
||||||
name,
|
name,
|
||||||
chunks: HashMap::new()
|
chunks: HashMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn all_blocks(&self) -> Vec<(Point3<u32>, &WorldBlock)> {
|
||||||
|
self.chunks.iter().map(|(chunk_pos, chunk)| {
|
||||||
|
let off = chunk_pos * chunk::SIZE as u32;
|
||||||
|
let result: Vec<(Point3<u32>, &WorldBlock)> = chunk.all_blocks().iter().map(|(pos, block)| {
|
||||||
|
(
|
||||||
|
Point3{x: off.x+pos.x, y: off.y+pos.y, z: off.z+pos.z},
|
||||||
|
*block
|
||||||
|
)
|
||||||
|
}).collect();
|
||||||
|
result
|
||||||
|
}).flatten().collect()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn save(&self) {
|
pub fn save(&self) {
|
||||||
// Get directory
|
// Get directory
|
||||||
let mut dir = dirs::data_local_dir().unwrap();
|
let mut dir = dirs::data_local_dir().unwrap();
|
||||||
@@ -41,6 +57,18 @@ impl World {
|
|||||||
let mut file = fs::File::create(path).expect("Failed to create file");
|
let mut file = fs::File::create(path).expect("Failed to create file");
|
||||||
file.write(&bytes).unwrap();
|
file.write(&bytes).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Save metadata
|
||||||
|
let mut data: LinkedHashMap<Yaml, Yaml> = LinkedHashMap::new();
|
||||||
|
data.insert(Yaml::String("name".to_string()), Yaml::String(self.name.clone()));
|
||||||
|
|
||||||
|
let mut data_str = String::new();
|
||||||
|
let mut emit = YamlEmitter::new(&mut data_str);
|
||||||
|
emit.dump(&Yaml::Hash(data)).expect("Failed to encode yaml");
|
||||||
|
|
||||||
|
let data_path: PathBuf = [dir.to_str().unwrap(), "world.yml"].iter().collect();
|
||||||
|
let mut data_file = fs::File::create(data_path).unwrap();
|
||||||
|
data_file.write_all(data_str.as_bytes()).expect("Failed to write");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load(&mut self) {
|
pub fn load(&mut self) {
|
||||||
@@ -74,12 +102,15 @@ impl World {
|
|||||||
println!("loaded {:?}", pos);
|
println!("loaded {:?}", pos);
|
||||||
self.chunks.insert(pos, chunk);
|
self.chunks.insert(pos, chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load metadata
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gen_block(&mut self, block_pos: &Point3<u32>) -> &WorldBlock {
|
pub fn gen_block(&mut self, block_pos: &Point3<u32>) -> &WorldBlock {
|
||||||
// Split world space to chunk and block space
|
// Split world space to chunk and block space
|
||||||
let ch_pos = block_pos / chunk::SIZE;
|
let ch_pos = block_pos / chunk::SIZE as u32;
|
||||||
let bl_pos = block_pos % chunk::SIZE;
|
let bl_pos = block_pos % chunk::SIZE as u32;
|
||||||
// Create chunk if does not exist
|
// Create chunk if does not exist
|
||||||
if let None = self.chunks.get(&ch_pos) {
|
if let None = self.chunks.get(&ch_pos) {
|
||||||
self.chunks.insert(block_pos.clone(), WorldChunk::new());
|
self.chunks.insert(block_pos.clone(), WorldChunk::new());
|
||||||
@@ -94,8 +125,8 @@ impl World {
|
|||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub fn get_block(&mut self, block_pos: &Point3<u32>) -> Option<&WorldBlock> {
|
pub fn get_block(&mut self, block_pos: &Point3<u32>) -> Option<&WorldBlock> {
|
||||||
// Split world space to chunk and block space
|
// Split world space to chunk and block space
|
||||||
let ch_pos = block_pos / chunk::SIZE;
|
let ch_pos = block_pos / chunk::SIZE as u32;
|
||||||
let bl_pos = block_pos % chunk::SIZE;
|
let bl_pos = block_pos % chunk::SIZE as u32;
|
||||||
// Return block if exists
|
// Return block if exists
|
||||||
if let Some(chunk) = self.chunks.get_mut(&ch_pos) {
|
if let Some(chunk) = self.chunks.get_mut(&ch_pos) {
|
||||||
return Some(chunk.get_block(&bl_pos));
|
return Some(chunk.get_block(&bl_pos));
|
||||||
|
|||||||
Reference in New Issue
Block a user