111 lines
3.2 KiB
Rust
111 lines
3.2 KiB
Rust
mod generator;
|
|
mod data;
|
|
mod loader;
|
|
pub mod chunk;
|
|
pub mod block;
|
|
use std::thread;
|
|
use std::sync::{mpsc, mpsc::Sender, mpsc::Receiver};
|
|
use std::time::Instant;
|
|
use std::path::PathBuf;
|
|
use std::io::Write;
|
|
use std::io::Read;
|
|
use std::fs;
|
|
use cgmath::Vector3;
|
|
use std::collections::HashMap;
|
|
use generator::WorldGen;
|
|
use chunk::WorldChunk;
|
|
use block::WorldBlock;
|
|
use data::WorldData;
|
|
use loader::ChunkLoader;
|
|
|
|
pub struct World {
|
|
data: WorldData,
|
|
loader: ChunkLoader,
|
|
chunks: HashMap<Vector3<i32>, WorldChunk>,
|
|
}
|
|
|
|
impl World {
|
|
|
|
pub fn init(name: String) -> Self {
|
|
let mut instance = Self {
|
|
data: WorldData { name: name.clone(), ..Default::default() },
|
|
loader: ChunkLoader::new(name.clone()),
|
|
chunks: HashMap::new(),
|
|
};
|
|
instance.load_metadata();
|
|
instance.save_all();
|
|
instance
|
|
}
|
|
|
|
/*
|
|
* Receives loaded chunks from ChunkLoader
|
|
*/
|
|
pub fn update(&mut self) {
|
|
for (pos, chunk) in self.loader.receive() {
|
|
self.chunks.insert(pos, chunk);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Sends chunk position to the ChunkLoader
|
|
*/
|
|
pub fn load_chunk(&mut self, pos: Vector3<i32>) {
|
|
if let Some(chunk) = self.chunks.get_mut(&pos) {
|
|
chunk.dirty = true;
|
|
} else {
|
|
self.loader.load(pos);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Loads metadata
|
|
*/
|
|
fn load_metadata(&mut self, ) -> bool {
|
|
let filepath = dirs::data_local_dir().unwrap().join("Voxelgame").join(self.data.name.clone()).join("world.dat");
|
|
if let Ok(mut file) = fs::File::open(filepath) {
|
|
let mut buf = Vec::new();
|
|
file.read_to_end(&mut buf).unwrap();
|
|
if let Ok(data) = toml::from_slice::<WorldData>(&buf[..]) {
|
|
self.data = data;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
* Saves metadata and all loaded chunks to files
|
|
*/
|
|
pub fn save_all(&self) {
|
|
// Get directory
|
|
let dirpath = dirs::data_local_dir().unwrap().join("Voxelgame").join("saves").join(&self.data.name);
|
|
fs::create_dir_all(&dirpath).expect("Failed to create world directory");
|
|
|
|
// Save all chunks
|
|
for (pos, chunk) in self.chunks.iter() {
|
|
let filepath = dirpath.join(format!("chunk_{}_{}_{}.dat", pos.x, pos.y, pos.z));
|
|
let mut file = fs::File::create(filepath).expect("Failed to create chunk file");
|
|
file.write(&chunk.to_bytes()).expect("Failed to write chunk file");
|
|
}
|
|
|
|
// Save metadata
|
|
let datastr = toml::to_string(&self.data).unwrap();
|
|
let datapath: PathBuf = dirpath.join("world.dat");
|
|
let mut datafile = fs::File::create(datapath).expect("Failed to create world metadata file");
|
|
datafile.write_all(datastr.as_bytes()).expect("Failed to write world metadata");
|
|
}
|
|
|
|
/*
|
|
* Returns chunk at given world chunk position
|
|
*/
|
|
pub fn get_chunk(&mut self, chunk_wpos: &Vector3<i32>) -> Option<&mut WorldChunk> {
|
|
self.chunks.get_mut(chunk_wpos)
|
|
}
|
|
|
|
/*
|
|
* Returns vec of references to all currently loaded chunks
|
|
*/
|
|
pub fn all_chunks(&mut self) -> Vec<(&Vector3<i32>, &mut WorldChunk)> {
|
|
self.chunks.iter_mut().collect()
|
|
}
|
|
} |