mindustry logic execution, map- and schematic- parsing and rendering
Implement logic block states
KosmosPrime 2023-01-10
parent 131e2c3 · commit 1c26e49
-rw-r--r--src/block/logic.rs101
-rw-r--r--src/block/simple.rs25
-rw-r--r--src/data/dynamic.rs38
3 files changed, 160 insertions, 4 deletions
diff --git a/src/block/logic.rs b/src/block/logic.rs
index f9c6094..bc35a60 100644
--- a/src/block/logic.rs
+++ b/src/block/logic.rs
@@ -1,10 +1,13 @@
-use crate::block::make_register;
-use crate::block::simple::SimpleBlock;
+use std::any::{Any, type_name};
+
+use crate::block::{BlockLogic, make_register};
+use crate::block::simple::{SimpleBlock, state_impl};
+use crate::data::dynamic::DynData;
make_register!
(
- MESSAGE: "message" => SimpleBlock::new(1, true); // TODO config: message
- SWITCH: "switch" => SimpleBlock::new(1, true); // TODO config: enabled
+ MESSAGE: "message" => MessageLogic;
+ SWITCH: "switch" => SwitchLogic;
MICRO_PROCESSOR: "micro-processor" => SimpleBlock::new(1, true); // TODO config: code & links
LOGIC_PROCESSOR: "logic-processor" => SimpleBlock::new(2, true); // TODO config: code & links
HYPER_PROCESSOR: "hyper-processor" => SimpleBlock::new(3, true); // TODO config: code & links
@@ -13,3 +16,93 @@ make_register!
LOGIC_DISPLAY: "logic-display" => SimpleBlock::new(3, true);
LARGE_LOGIC_DISPLAY: "large-logic-display" => SimpleBlock::new(6, true);
);
+
+pub struct MessageLogic;
+
+impl MessageLogic
+{
+ state_impl!(pub String);
+}
+
+impl BlockLogic for MessageLogic
+{
+ fn get_size(&self) -> u8
+ {
+ 1
+ }
+
+ fn is_symmetric(&self) -> bool
+ {
+ true
+ }
+
+ fn data_from_i32(&self, _: i32) -> DynData
+ {
+ DynData::Empty
+ }
+
+ fn deserialize_state(&self, data: DynData) -> Option<Box<dyn Any>>
+ {
+ match data
+ {
+ DynData::Empty | DynData::String(None) => Some(Self::create_state(String::new())),
+ DynData::String(Some(s)) => Some(Self::create_state(s)),
+ _ => panic!("{} cannot use data of {:?}", type_name::<Self>(), data.get_type()),
+ }
+ }
+
+ fn clone_state(&self, state: &dyn Any) -> Box<dyn Any>
+ {
+ Box::new(Self::get_state(state).clone())
+ }
+
+ fn serialize_state(&self, state: &dyn Any) -> DynData
+ {
+ DynData::String(Some(Self::get_state(state).clone()))
+ }
+}
+
+pub struct SwitchLogic;
+
+impl SwitchLogic
+{
+ state_impl!(pub bool);
+}
+
+impl BlockLogic for SwitchLogic
+{
+ fn get_size(&self) -> u8
+ {
+ 1
+ }
+
+ fn is_symmetric(&self) -> bool
+ {
+ true
+ }
+
+ fn data_from_i32(&self, _: i32) -> DynData
+ {
+ DynData::Empty
+ }
+
+ fn deserialize_state(&self, data: DynData) -> Option<Box<dyn Any>>
+ {
+ match data
+ {
+ DynData::Empty => Some(Self::create_state(true)),
+ DynData::Boolean(enabled) => Some(Self::create_state(enabled)),
+ _ => panic!("{} cannot use data of {:?}", type_name::<Self>(), data.get_type()),
+ }
+ }
+
+ fn clone_state(&self, state: &dyn Any) -> Box<dyn Any>
+ {
+ Box::new(Self::get_state(state).clone())
+ }
+
+ fn serialize_state(&self, state: &dyn Any) -> DynData
+ {
+ DynData::Boolean(*Self::get_state(state))
+ }
+}
diff --git a/src/block/simple.rs b/src/block/simple.rs
index 330ee7f..c363064 100644
--- a/src/block/simple.rs
+++ b/src/block/simple.rs
@@ -29,6 +29,31 @@ macro_rules!gen_state_empty
};
}
+macro_rules!state_impl
+{
+ ($vis:vis $type:ty) =>
+ {
+ $vis fn get_state<'l>(state: &'l dyn Any) -> &'l $type
+ where Self: Sized
+ {
+ state.downcast_ref::<$type>().unwrap()
+ }
+
+ $vis fn get_state_mut<'l>(state: &'l mut dyn Any) -> &'l mut $type
+ where Self: Sized
+ {
+ state.downcast_mut::<$type>().unwrap()
+ }
+
+ fn create_state(val: $type) -> Box<dyn Any>
+ where Self: Sized
+ {
+ Box::new(val)
+ }
+ };
+}
+pub(crate) use state_impl;
+
pub struct SimpleBlock
{
size: u8,
diff --git a/src/data/dynamic.rs b/src/data/dynamic.rs
index 4ccafcb..0b4e3fb 100644
--- a/src/data/dynamic.rs
+++ b/src/data/dynamic.rs
@@ -69,6 +69,44 @@ pub enum DynData
Team(Team),
}
+impl DynData
+{
+ pub fn get_type(&self) -> DynType
+ {
+ match self
+ {
+ DynData::Empty => DynType::Empty,
+ DynData::Int(..) => DynType::Int,
+ DynData::Long(..) => DynType::Long,
+ DynData::Float(..) => DynType::Float,
+ DynData::String(..) => DynType::String,
+ DynData::Content(..) => DynType::Content,
+ DynData::IntArray(..) => DynType::IntArray,
+ DynData::Point2(..) => DynType::Point2,
+ DynData::Point2Array(..) => DynType::Point2Array,
+ DynData::TechNode(..) => DynType::TechNode,
+ DynData::Boolean(..) => DynType::Boolean,
+ DynData::Double(..) => DynType::Double,
+ DynData::Building(..) => DynType::Building,
+ DynData::LogicField(..) => DynType::LogicField,
+ DynData::ByteArray(..) => DynType::ByteArray,
+ DynData::UnitCommand(..) => DynType::UnitCommand,
+ DynData::BoolArray(..) => DynType::BoolArray,
+ DynData::Unit(..) => DynType::Unit,
+ DynData::Vec2Array(..) => DynType::Vec2Array,
+ DynData::Vec2(..) => DynType::Vec2,
+ DynData::Team(..) => DynType::Team,
+ }
+ }
+}
+
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+pub enum DynType
+{
+ Empty, Int, Long, Float, String, Content, IntArray, Point2, Point2Array, TechNode, Boolean, Double, Building,
+ LogicField, ByteArray, UnitCommand, BoolArray, Unit, Vec2Array, Vec2, Team,
+}
+
pub struct DynSerializer;
impl Serializer<DynData> for DynSerializer