mindustry logic execution, map- and schematic- parsing and rendering
Diffstat (limited to 'src/data/schematic.rs')
| -rw-r--r-- | src/data/schematic.rs | 53 |
1 files changed, 43 insertions, 10 deletions
diff --git a/src/data/schematic.rs b/src/data/schematic.rs index 4cdad07..eca03a2 100644 --- a/src/data/schematic.rs +++ b/src/data/schematic.rs @@ -1,13 +1,14 @@ use std::any::Any; use std::collections::HashMap; use std::collections::hash_map::Entry; +use std::error::Error; use std::fmt::{self, Write}; use std::iter::FusedIterator; use std::slice::Iter; use flate2::{Compress, CompressError, Compression, Decompress, DecompressError, FlushCompress, FlushDecompress, Status}; -use crate::block::{Block, BlockRegistry, Rotation}; +use crate::block::{self, Block, BlockRegistry, Rotation}; use crate::data::{self, DataRead, DataWrite, GridPos, Serializer}; use crate::data::base64; use crate::data::dynamic::{self, DynSerializer, DynData}; @@ -53,10 +54,10 @@ impl Placement } } - pub fn set_state(&mut self, data: DynData) -> Option<Box<dyn Any>> + pub fn set_state(&mut self, data: DynData) -> Result<Option<Box<dyn Any>>, block::DeserializeError> { - let state = self.block.deserialize_state(data); - std::mem::replace(&mut self.state, state) + let state = self.block.deserialize_state(data)?; + Ok(std::mem::replace(&mut self.state, state)) } pub fn get_rotation(&self) -> Rotation @@ -261,7 +262,7 @@ impl Schematic if self.is_region_empty(x - off, y - off, sz, sz) { let idx = self.blocks.len(); - let state = block.deserialize_state(data); + let state = block.deserialize_state(data)?; self.blocks.push(Placement{pos: GridPos(x, y), block, state, rot}); self.fill_lookup(x as usize, y as usize, block.get_size() as usize, Some(idx)); Ok(&self.blocks[idx]) @@ -298,7 +299,7 @@ impl Schematic } } let idx = self.blocks.len(); - let state = block.deserialize_state(data); + let state = block.deserialize_state(data)?; self.blocks.push(Placement{pos: GridPos(x, y), block, state, rot}); self.fill_lookup(x as usize, y as usize, sz as usize, Some(idx)); Ok(result) @@ -311,14 +312,14 @@ impl Schematic None => { let idx = self.blocks.len(); - let state = block.deserialize_state(data); + let state = block.deserialize_state(data)?; self.blocks.push(Placement{pos: GridPos(x, y), block, state, rot}); self.lookup[pos] = Some(idx); Ok(if collect {Some(Vec::new())} else {None}) }, Some(idx) => { - let state = block.deserialize_state(data); + let state = block.deserialize_state(data)?; let prev = std::mem::replace(&mut self.blocks[idx], Placement{pos: GridPos(x, y), block, state, rot}); self.fill_lookup(prev.pos.0 as usize, prev.pos.1 as usize, prev.block.get_size() as usize, None); self.fill_lookup(x as usize, y as usize, sz as usize, Some(idx)); @@ -470,11 +471,20 @@ impl fmt::Display for PosError } } -#[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[derive(Debug)] pub enum PlaceError { Bounds{x: u16, y: u16, sz: u8, w: u16, h: u16}, Overlap{x: u16, y: u16}, + Deserialize(block::DeserializeError), +} + +impl From<block::DeserializeError> for PlaceError +{ + fn from(value: block::DeserializeError) -> Self + { + PlaceError::Deserialize(value) + } } impl fmt::Display for PlaceError @@ -485,6 +495,19 @@ impl fmt::Display for PlaceError { PlaceError::Bounds{x, y, sz, w, h} => write!(f, "Block placement {x} / {y} (size {sz}) within {w} / {h}"), PlaceError::Overlap{x, y} => write!(f, "Overlapping an existing block at {x} / {y}"), + PlaceError::Deserialize(e) => e.fmt(f), + } + } +} + +impl Error for PlaceError +{ + fn source(&self) -> Option<&(dyn Error + 'static)> + { + match self + { + PlaceError::Deserialize(e) => Some(e), + _ => None, } } } @@ -835,7 +858,7 @@ impl<'l> Serializer<Schematic> for SchematicSerializer<'l> let data = match curr.state { None => DynData::Empty, - Some(ref s) => curr.block.serialize_state(s.as_ref()), + Some(ref s) => curr.block.serialize_state(s.as_ref())?, }; DynSerializer.serialize(&mut rbuff, &data)?; rbuff.write_u8(curr.rot.into())?; @@ -974,6 +997,7 @@ pub enum WriteError Write(data::WriteError), TagCount(usize), TableSize(usize), + StateSerialize(block::SerializeError), BlockState(dynamic::WriteError), Compress(CompressError), CompressEof(usize), @@ -988,6 +1012,14 @@ impl From<data::WriteError> for WriteError } } +impl From<block::SerializeError> for WriteError +{ + fn from(value: block::SerializeError) -> Self + { + Self::StateSerialize(value) + } +} + impl From<CompressError> for WriteError { fn from(value: CompressError) -> Self @@ -1013,6 +1045,7 @@ impl fmt::Display for WriteError WriteError::Write(..) => write!(f, "Failed to write data to buffer"), WriteError::TagCount(cnt) => write!(f, "Invalid tag count ({cnt})"), WriteError::TableSize(cnt) => write!(f, "Invalid block table size ({cnt})"), + WriteError::StateSerialize(e) => e.fmt(f), WriteError::BlockState(..) => write!(f, "Failed to write block state"), WriteError::Compress(e) => e.fmt(f), WriteError::CompressEof(remain) => write!(f, "Compression overflow with {remain} bytes of input remaining"), |