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, 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) { 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::(&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) -> 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, &mut WorldChunk)> { self.chunks.iter_mut().collect() } }