use std::fs::{self, File}; use std::io::Write; use std::sync::{Arc, Mutex}; use log::info; use crate::error::AppError; #[derive(Debug)] pub struct World { pub size_x: i16, pub size_y: i16, pub size_z: i16, pub data: Vec, } impl World { fn build(size_x: i16, size_y: i16, size_z: i16) -> Vec { let mut world_dat: Vec = Vec::new(); for y in 0..size_y { for _z in 0..size_z { for _x in 0..size_x { match y { 0..15 => world_dat.push(0x03), // Dirt 15 => world_dat.push(0x02), // Grass _ => world_dat.push(0x00), // Air } } } } world_dat } pub fn load() -> Result { if fs::metadata("world.wrld").is_ok() { let mut world: World = World { size_x: 0, size_y: 0, size_z: 0, data: Vec::new(), }; let world_data_raw = fs::read("world.wrld")?; if world_data_raw.len() < 6 { return Err(AppError::InvalidWorldFile); } world.size_x = ((world_data_raw[0] as i16) << 8) + (world_data_raw[1] as i16); world.size_y = ((world_data_raw[2] as i16) << 8) + (world_data_raw[3] as i16); world.size_z = ((world_data_raw[4] as i16) << 8) + (world_data_raw[5] as i16); if world.size_x > 512 || world.size_y > 256 || world.size_z > 512 { return Err(AppError::InvalidWorldFile); } if world_data_raw.len() != (world.size_x as i32 * world.size_y as i32 * world.size_z as i32 + 6_i32) as usize { return Err(AppError::InvalidWorldFile); } world.data = world_data_raw[6..].to_vec(); info!("Loaded world {}", "world.wrld"); Ok(world) } else { info!("Creating word {}", "world.wrld"); Ok(World { size_x: 64, size_y: 32, size_z: 64, data: World::build(64, 32, 64), }) } } pub fn save(world_arc_clone: Arc>) -> Result<(), AppError> { let mut to_write: Vec = Vec::new(); { let mut world_dat = world_arc_clone.lock()?; to_write.push((world_dat.size_x >> 8) as u8); to_write.push((world_dat.size_x & 0xFF) as u8); to_write.push((world_dat.size_y >> 8) as u8); to_write.push((world_dat.size_y & 0xFF) as u8); to_write.push((world_dat.size_z >> 8) as u8); to_write.push((world_dat.size_z & 0xFF) as u8); to_write.append(&mut world_dat.data); } let mut file = File::create("world.wrld")?; Ok(file.write_all(&to_write)?) } }