diff --git a/kubi-shared/src/data.rs b/kubi-shared/src/data.rs index 45c41e9..919f2dc 100644 --- a/kubi-shared/src/data.rs +++ b/kubi-shared/src/data.rs @@ -11,9 +11,13 @@ use anyhow::Result; use crate::{block::Block, chunk::{CHUNK_SIZE, BlockDataRef}}; const SECTOR_SIZE: usize = CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE * size_of::(); -const RESERVED_SIZE: usize = 524288; //512kb (16 sectors assuming 32x32x32 world of 1byte blocks) +const RESERVED_SIZE: usize = 1048576; //~1mb (16 sectors assuming 32x32x32 world of 1byte blocks) const RESERVED_SECTOR_COUNT: usize = RESERVED_SIZE / SECTOR_SIZE; +//magic = "KUBI" + IDENTITY (4 bytes) +const HEADER_MAGIC_SIZE: usize = 8; +const HEADER_MAGIC_STR: [u8; 4] = *b"KUBI"; +const HEADER_MAGIC_IDENTITY: u32 = 1; // #[repr(transparent)] // struct IVec2Hash(IVec2); @@ -22,7 +26,7 @@ struct WorldSaveDataHeader { pub name: Cow<'static, str>, pub seed: u64, sector_count: u32, - chunk_map: HashMap + chunk_map: HashMap, } impl Default for WorldSaveDataHeader { @@ -51,13 +55,29 @@ impl WorldSaveFile { fn read_header(&mut self) -> Result<()> { self.file.rewind()?; - self.header = bincode::deserialize_from((&self.file).take(RESERVED_SIZE as u64))?; + + let mut subheader = [0u8; HEADER_MAGIC_SIZE]; + self.file.read_exact(&mut subheader)?; + if subheader[0..4] != HEADER_MAGIC_STR { + return Err(anyhow::anyhow!("invalid file header")); + } + if subheader[4..8] != HEADER_MAGIC_IDENTITY.to_be_bytes() { + return Err(anyhow::anyhow!("this save file cannot be loaded by this version of the game")); + } + + let limit = (RESERVED_SIZE - HEADER_MAGIC_SIZE) as u64; + self.header = bincode::deserialize_from((&self.file).take(limit))?; + Ok(()) } fn write_header(&mut self) -> Result<()> { self.file.rewind()?; - ///XXX: this can cause the header to destroy chunk data (if it's WAY too long) + self.file.write_all(&HEADER_MAGIC_STR)?; + self.file.write_all(&HEADER_MAGIC_IDENTITY.to_be_bytes())?; + //XXX: this can cause the header to destroy chunk data (if it's WAY too long) + // read has checks against this, but write doesn't + // 1mb is pretty generous tho, so it's not a *big* deal bincode::serialize_into(&self.file, &self.header)?; Ok(()) }