mindustry logic execution, map- and schematic- parsing and rendering
remove Box<dyn Any> for state
bendn 2023-08-11
parent b745cca · commit c8d00a0
-rw-r--r--src/block/distribution.rs10
-rw-r--r--src/block/liquid.rs5
-rw-r--r--src/block/logic.rs21
-rw-r--r--src/block/mod.rs73
-rw-r--r--src/block/payload.rs5
-rw-r--r--src/block/power.rs21
-rw-r--r--src/block/simple.rs6
-rw-r--r--src/block/units.rs9
-rw-r--r--src/block/walls.rs5
-rw-r--r--src/data/map.rs17
-rw-r--r--src/data/schematic.rs12
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> {