mindustry logic execution, map- and schematic- parsing and rendering
| -rw-r--r-- | src/block/distribution.rs | 10 | ||||
| -rw-r--r-- | src/block/liquid.rs | 5 | ||||
| -rw-r--r-- | src/block/logic.rs | 21 | ||||
| -rw-r--r-- | src/block/mod.rs | 73 | ||||
| -rw-r--r-- | src/block/payload.rs | 5 | ||||
| -rw-r--r-- | src/block/power.rs | 21 | ||||
| -rw-r--r-- | src/block/simple.rs | 6 | ||||
| -rw-r--r-- | src/block/units.rs | 9 | ||||
| -rw-r--r-- | src/block/walls.rs | 5 | ||||
| -rw-r--r-- | src/data/map.rs | 17 | ||||
| -rw-r--r-- | src/data/schematic.rs | 12 |
11 files changed, 79 insertions, 105 deletions
diff --git a/src/block/distribution.rs b/src/block/distribution.rs index 933636b..4cc68c6 100644 --- a/src/block/distribution.rs +++ b/src/block/distribution.rs @@ -204,11 +204,6 @@ impl BlockLogic for ItemBlock { } } - fn clone_state(&self, state: &State) -> State { - let state = Self::get_state(state); - Box::new(Self::create_state(*state)) - } - fn mirror_state(&self, _: &mut State, _: bool, _: bool) {} fn rotate_state(&self, _: &mut State, _: bool) {} @@ -397,11 +392,6 @@ impl BlockLogic for BridgeBlock { } } - fn clone_state(&self, state: &State) -> State { - let state = Self::get_state(state); - Box::new(Self::create_state(*state)) - } - fn mirror_state(&self, state: &mut State, horizontally: bool, vertically: bool) { match Self::get_state_mut(state) { None => (), diff --git a/src/block/liquid.rs b/src/block/liquid.rs index 7164885..5e40f64 100644 --- a/src/block/liquid.rs +++ b/src/block/liquid.rs @@ -96,11 +96,6 @@ impl BlockLogic for FluidBlock { } } - fn clone_state(&self, state: &State) -> State { - let state = Self::get_state(state); - Box::new(Self::create_state(*state)) - } - fn serialize_state(&self, state: &State) -> Result<DynData, SerializeError> { Ok(Self::get_state(state) .as_ref() diff --git a/src/block/logic.rs b/src/block/logic.rs index c0cb727..f76fa5e 100644 --- a/src/block/logic.rs +++ b/src/block/logic.rs @@ -116,10 +116,6 @@ impl BlockLogic for CanvasBlock { } } - fn clone_state(&self, state: &State) -> State { - Box::new(Self::get_state(state).clone()) - } - fn serialize_state(&self, state: &State) -> Result<DynData, SerializeError> { let mut o = vec![0; self.canvas_size as usize * self.canvas_size as usize * 3]; let p = Self::get_state(state); @@ -152,8 +148,7 @@ impl BlockLogic for CanvasBlock { s: Scale, ) -> ImageHolder { if let Some(state) = state { - let state = self.clone_state(state); - let p = state.downcast::<RgbImage>().unwrap(); + let p = Self::get_state(state); let offset = match s { Scale::Full => 7, // Scale::Half => 3, @@ -164,7 +159,7 @@ impl BlockLogic for CanvasBlock { RgbImage::from_raw( self.canvas_size as u32, self.canvas_size as u32, - p.into_raw(), + p.clone().into_raw(), ) .unwrap(), ) @@ -254,10 +249,6 @@ impl BlockLogic for MessageLogic { } } - fn clone_state(&self, state: &State) -> State { - Box::new(Self::get_state(state).clone()) - } - fn mirror_state(&self, _: &mut State, _: bool, _: bool) {} fn rotate_state(&self, _: &mut State, _: bool) {} @@ -316,10 +307,6 @@ impl BlockLogic for SwitchLogic { } } - fn clone_state(&self, state: &State) -> State { - Box::new(*Self::get_state(state)) - } - fn serialize_state(&self, state: &State) -> Result<DynData, SerializeError> { Ok(DynData::Boolean(*Self::get_state(state))) } @@ -453,10 +440,6 @@ impl BlockLogic for ProcessorLogic { Ok(()) } - fn clone_state(&self, state: &State) -> State { - Box::new(Self::get_state(state).clone()) - } - fn mirror_state(&self, state: &mut State, horizontally: bool, vertically: bool) { for link in &mut Self::get_state_mut(state).links { if horizontally { diff --git a/src/block/mod.rs b/src/block/mod.rs index 822de05..5e3bd50 100644 --- a/src/block/mod.rs +++ b/src/block/mod.rs @@ -4,7 +4,6 @@ //! //! with the exception of sandbox, that is. use bobbin_bits::U4::{self, B0000, B0001, B0010, B0100, B1000}; -use std::any::Any; use std::error::Error; use std::fmt; @@ -112,7 +111,71 @@ disp! { DoorBlock, } -pub type State = Box<dyn Any + Sync + Send>; +pub trait Cast { + fn downcast_ref(state: &State) -> Option<&Self>; + fn downcast_mut(state: &mut State) -> Option<&mut Self>; +} + +macro_rules! stater { + ($($k: ident($v: ty),)+) => { + #[derive(Debug, Clone)] + pub enum State { + $($k($v),)+ + } + + $( + impl From<$v> for State { + fn from(v: $v) -> State { State::$k(v) } + } + + impl Cast for $v { + fn downcast_ref(state: &State) -> Option<&Self> { + match state { + State::$k(v) => Some(v), + _ => None, + } + } + fn downcast_mut(state: &mut State) -> Option<&mut Self> { + match state { + State::$k(v) => Some(v), + _ => None, + } + } + } + )+ + } +} + +stater! { + // TODO deoptionize + String(String), + Item(Option<crate::item::Type>), + Fluid(Option<crate::fluid::Type>), + Image(image::RgbImage), + Point(Option<(i32, i32)>), + Bool(bool), + Processor(logic::ProcessorState), + Payload(payload::Payload), + Power(Vec<(i16, i16)>), + Color(power::Rgba), + Command(Option<crate::data::command::UnitCommand>), + Unit(Option<crate::unit::Type>), +} + +impl State { + pub fn downcast_ref<T: Cast>(&self) -> Option<&T> { + T::downcast_ref(self) + } + + pub fn downcast_mut<T: Cast>(&mut self) -> Option<&mut T> { + T::downcast_mut(self) + } + + pub fn new<T: Into<Self>>(from: T) -> Self { + from.into() + } +} + #[enum_dispatch::enum_dispatch(BlockLogicEnum)] pub trait BlockLogic { /// mindustry blocks are the same width and height @@ -126,8 +189,6 @@ pub trait BlockLogic { fn deserialize_state(&self, data: DynData) -> Result<Option<State>, DeserializeError>; - fn clone_state(&self, state: &State) -> State; - #[allow(unused_variables)] fn mirror_state(&self, state: &mut State, horizontally: bool, vertically: bool) {} @@ -331,10 +392,6 @@ impl Block { self.logic.deserialize_state(data) } - pub(crate) fn clone_state(&self, state: &State) -> State { - self.logic.clone_state(state) - } - pub(crate) fn mirror_state(&self, state: &mut State, horizontally: bool, vertically: bool) { self.logic.mirror_state(state, horizontally, vertically); } diff --git a/src/block/payload.rs b/src/block/payload.rs index 54aaa6f..64ea9ba 100644 --- a/src/block/payload.rs +++ b/src/block/payload.rs @@ -164,11 +164,6 @@ impl BlockLogic for PayloadBlock { } } - fn clone_state(&self, state: &State) -> State { - let state = Self::get_state(state); - Box::new(Self::create_state(*state)) - } - fn serialize_state(&self, state: &State) -> Result<DynData, SerializeError> { match Self::get_state(state) { Payload::Empty => Ok(DynData::Empty), diff --git a/src/block/power.rs b/src/block/power.rs index ea54750..3cb9165 100644 --- a/src/block/power.rs +++ b/src/block/power.rs @@ -110,10 +110,6 @@ impl BlockLogic for ConnectorBlock { } } - fn clone_state(&self, state: &State) -> State { - Box::new(Self::get_state(state).clone()) - } - fn mirror_state(&self, state: &mut State, horizontally: bool, vertically: bool) { for (dx, dy) in &mut *Self::get_state_mut(state) { if horizontally { @@ -154,9 +150,9 @@ impl ConnectorDeserializeError { } #[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub struct RGBA(u8, u8, u8, u8); +pub struct Rgba(u8, u8, u8, u8); -impl From<u32> for RGBA { +impl From<u32> for Rgba { fn from(value: u32) -> Self { Self( (value >> 24) as u8, @@ -167,8 +163,8 @@ impl From<u32> for RGBA { } } -impl From<RGBA> for u32 { - fn from(value: RGBA) -> Self { +impl From<Rgba> for u32 { + fn from(value: Rgba) -> Self { (u32::from(value.0) << 24) | (u32::from(value.1) << 16) | (u32::from(value.2) << 8) @@ -193,7 +189,7 @@ impl LampBlock { } } - state_impl!(pub RGBA); + state_impl!(pub Rgba); } impl BlockLogic for LampBlock { @@ -205,7 +201,7 @@ impl BlockLogic for LampBlock { fn deserialize_state(&self, data: DynData) -> Result<Option<State>, DeserializeError> { match data { - DynData::Int(rgba) => Ok(Some(Self::create_state(RGBA::from(rgba as u32)))), + DynData::Int(rgba) => Ok(Some(Self::create_state(Rgba::from(rgba as u32)))), _ => Err(DeserializeError::InvalidType { have: data.get_type(), expect: DynType::Int, @@ -213,11 +209,6 @@ impl BlockLogic for LampBlock { } } - fn clone_state(&self, state: &State) -> State { - let state = Self::get_state(state); - Box::new(Self::create_state(*state)) - } - fn serialize_state(&self, state: &State) -> Result<DynData, SerializeError> { let state = Self::get_state(state); Ok(DynData::Int(u32::from(*state) as i32)) diff --git a/src/block/simple.rs b/src/block/simple.rs index 1c00079..329e58d 100644 --- a/src/block/simple.rs +++ b/src/block/simple.rs @@ -15,7 +15,7 @@ macro_rules! state_impl { fn create_state(val: $type) -> $crate::block::State where Self: Sized { - Box::new(val) + State::from(val) } }; } @@ -65,10 +65,6 @@ macro_rules! make_simple { Ok(None) } - fn clone_state(&self, _: &crate::block::State) -> crate::block::State { - panic!("{} has no custom state", stringify!($name)) - } - fn mirror_state(&self, _: &mut crate::block::State, _: bool, _: bool) { panic!("{} has no custom state", stringify!($name)); } diff --git a/src/block/units.rs b/src/block/units.rs index 9a893d8..c34f944 100644 --- a/src/block/units.rs +++ b/src/block/units.rs @@ -178,9 +178,7 @@ impl BlockLogic for ConstructorBlock { } } - fn clone_state(&self, state: &State) -> State { - Box::new(*Self::get_state(state)) - } + fn serialize_state(&self, state: &State) -> Result<DynData, SerializeError> { Ok(Self::get_state(state).map_or(DynData::Empty, DynData::UnitCommand)) @@ -322,10 +320,7 @@ impl BlockLogic for UnitFactory { } } - fn clone_state(&self, state: &State) -> State { - let state = Self::get_state(state); - Box::new(Self::create_state(*state)) - } + fn serialize_state(&self, state: &State) -> Result<DynData, SerializeError> { if let Some(state) = Self::get_state(state) { diff --git a/src/block/walls.rs b/src/block/walls.rs index 2ec2e26..0108dc3 100644 --- a/src/block/walls.rs +++ b/src/block/walls.rs @@ -100,11 +100,6 @@ impl BlockLogic for DoorBlock { } } - fn clone_state(&self, state: &State) -> State { - let state = Self::get_state(state); - Box::new(Self::create_state(*state)) - } - fn serialize_state(&self, state: &State) -> Result<DynData, SerializeError> { let state = Self::get_state(state); Ok(DynData::Boolean(*state)) diff --git a/src/data/map.rs b/src/data/map.rs index b1405ea..6284ac7 100644 --- a/src/data/map.rs +++ b/src/data/map.rs @@ -268,6 +268,7 @@ impl<'l> BlockState<'l> for Option<Tile<'_>> { } /// a build on a tile in a map +#[derive(Clone)] pub struct Build<'l> { pub block: &'l Block, pub items: Storage<Item>, @@ -285,20 +286,6 @@ impl std::fmt::Debug for Build<'_> { } } -impl Clone for Build<'_> { - fn clone(&self) -> Self { - Self { - block: self.block, - items: self.items.clone(), - liquids: self.liquids.clone(), - state: self.state.as_ref().map(|s| self.block.clone_state(s)), - rotation: self.rotation, - team: self.team, - data: self.data, - } - } -} - impl<'l> Build<'l> { #[must_use] pub fn new(block: &'l Block) -> Build<'l> { @@ -505,7 +492,7 @@ impl<'l> Map<'l> { #[must_use] pub fn new(width: usize, height: usize, tags: HashMap<String, String>) -> Self { Self { - tiles: vec![Tile::new(BlockEnum::Stone, BlockEnum::Air); width * height], + tiles: vec![Tile::new(BlockEnum::Air, BlockEnum::Air); width * height], height, width, tags, diff --git a/src/data/schematic.rs b/src/data/schematic.rs index 25d2cb7..6dea884 100644 --- a/src/data/schematic.rs +++ b/src/data/schematic.rs @@ -19,6 +19,7 @@ pub const MAX_DIMENSION: usize = 256; pub const MAX_BLOCKS: u32 = 256 * 256; /// a placement in a schematic +#[derive(Clone)] pub struct Placement<'l> { pub block: &'l Block, pub rot: Rotation, @@ -115,17 +116,6 @@ impl RotationState for Option<Placement<'_>> { } } -// manual impl because trait objects cannot be cloned -impl<'l> Clone for Placement<'l> { - fn clone(&self) -> Self { - Self { - block: self.block, - state: self.state.as_ref().map(|s| self.block.clone_state(s)), - rot: self.rot, - } - } -} - #[derive(Clone, Debug)] /// a schematic. pub struct Schematic<'l> { |