mindustry logic execution, map- and schematic- parsing and rendering
Diffstat (limited to 'src/block/payload.rs')
-rw-r--r--src/block/payload.rs561
1 files changed, 264 insertions, 297 deletions
diff --git a/src/block/payload.rs b/src/block/payload.rs
index bf6bc76..9803d11 100644
--- a/src/block/payload.rs
+++ b/src/block/payload.rs
@@ -2,11 +2,13 @@ use std::any::Any;
use std::error::Error;
use std::fmt;
-use crate::block::{self, BlockLogic, DataConvertError, DeserializeError, make_register, SerializeError};
-use crate::block::simple::{BuildCost, cost, SimpleBlock, state_impl};
+use crate::block::simple::{cost, state_impl, BuildCost, SimpleBlock};
+use crate::block::{
+ self, make_register, BlockLogic, DataConvertError, DeserializeError, SerializeError,
+};
use crate::content;
-use crate::data::GridPos;
use crate::data::dynamic::{DynData, DynType};
+use crate::data::GridPos;
use crate::item::storage::Storage;
use crate::unit;
@@ -14,158 +16,147 @@ const GROUND_UNITS: &[unit::Type] = &[unit::Type::Dagger, unit::Type::Crawler, u
const AIR_UNITS: &[unit::Type] = &[unit::Type::Flare, unit::Type::Mono];
const NAVAL_UNITS: &[unit::Type] = &[unit::Type::Risso, unit::Type::Retusa];
-make_register!
-(
- GROUND_FACTORY: "ground-factory" => AssemblerBlock::new(3, false, cost!(Copper: 50, Lead: 120, Silicon: 80), GROUND_UNITS);
- AIR_FACTORY: "air-factory" => AssemblerBlock::new(3, false, cost!(Copper: 60, Lead: 70), AIR_UNITS);
- NAVAL_FACTORY: "naval-factory" => AssemblerBlock::new(3, false, cost!(Copper: 150, Lead: 130, Metaglass: 120), NAVAL_UNITS);
- ADDITIVE_RECONSTRUCTOR: "additive-reconstructor" => SimpleBlock::new(3, false, cost!(Copper: 200, Lead: 120, Silicon: 90));
- MULTIPLICATIVE_RECONSTRUCTOR: "multiplicative-reconstructor" => SimpleBlock::new(5, false, cost!(Lead: 650, Titanium: 350, Thorium: 650, Silicon: 450));
- EXPONENTIAL_RECONSTRUCTOR: "exponential-reconstructor" => SimpleBlock::new(7, false,
- cost!(Lead: 2000, Titanium: 2000, Thorium: 750, Silicon: 1000, Plastanium: 450, PhaseFabric: 600));
- TETRATIVE_RECONSTRUCTOR: "tetrative-reconstructor" => SimpleBlock::new(9, false,
- cost!(Lead: 4000, Thorium: 1000, Silicon: 3000, Plastanium: 600, PhaseFabric: 600, SurgeAlloy: 800));
- REPAIR_POINT: "repair-point" => SimpleBlock::new(1, true, cost!(Copper: 30, Lead: 30, Silicon: 20));
- REPAIR_TURRET: "repair-turret" => SimpleBlock::new(2, true, cost!(Thorium: 80, Silicon: 90, Plastanium: 60));
- PAYLOAD_CONVEYOR: "payload-conveyor" => SimpleBlock::new(3, false, cost!(Copper: 10, Graphite: 10));
- PAYLOAD_ROUTER: "payload-router" => SimpleBlock::new(3, false, cost!(Copper: 10, Graphite: 15));
- // sandbox only
- PAYLOAD_SOURCE: "payload-source" => PayloadBlock::new(5, false, &[]);
- PAYLOAD_VOID: "payload-void" => SimpleBlock::new(5, true, &[]);
-);
-
-pub struct AssemblerBlock
-{
- size: u8,
- symmetric: bool,
- build_cost: BuildCost,
- valid: &'static [unit::Type],
+make_register! {
+ "ground-factory" => AssemblerBlock::new(3, false, cost!(Copper: 50, Lead: 120, Silicon: 80), GROUND_UNITS);
+ "air-factory" => AssemblerBlock::new(3, false, cost!(Copper: 60, Lead: 70), AIR_UNITS);
+ "naval-factory" => AssemblerBlock::new(3, false, cost!(Copper: 150, Lead: 130, Metaglass: 120), NAVAL_UNITS);
+ "additive-reconstructor" => SimpleBlock::new(3, false, cost!(Copper: 200, Lead: 120, Silicon: 90));
+ "multiplicative-reconstructor" => SimpleBlock::new(5, false, cost!(Lead: 650, Titanium: 350, Thorium: 650, Silicon: 450));
+ "exponential-reconstructor" => SimpleBlock::new(7, false,
+ cost!(Lead: 2000, Titanium: 2000, Thorium: 750, Silicon: 1000, Plastanium: 450, PhaseFabric: 600));
+ "tetrative-reconstructor" => SimpleBlock::new(9, false,
+ cost!(Lead: 4000, Thorium: 1000, Silicon: 3000, Plastanium: 600, PhaseFabric: 600, SurgeAlloy: 800));
+ "repair-point" => SimpleBlock::new(1, true, cost!(Copper: 30, Lead: 30, Silicon: 20));
+ "repair-turret" => SimpleBlock::new(2, true, cost!(Thorium: 80, Silicon: 90, Plastanium: 60));
+ "payload-conveyor" => SimpleBlock::new(3, false, cost!(Copper: 10, Graphite: 10));
+ "payload-router" => SimpleBlock::new(3, false, cost!(Copper: 10, Graphite: 15));
+ // sandbox only
+ "payload-source" => PayloadBlock::new(5, false, &[]);
+ "payload-void" => SimpleBlock::new(5, true, &[]);
+}
+
+pub struct AssemblerBlock {
+ size: u8,
+ symmetric: bool,
+ build_cost: BuildCost,
+ valid: &'static [unit::Type],
}
-impl AssemblerBlock
-{
- pub const fn new(size: u8, symmetric: bool, build_cost: BuildCost, valid: &'static [unit::Type]) -> Self
- {
- if size == 0
- {
- panic!("invalid size");
- }
- if valid.is_empty()
- {
- panic!("no valid units");
- }
- if valid.len() > i32::MAX as usize
- {
- panic!("too many valid units");
- }
- Self{size, symmetric, build_cost, valid}
- }
-
- state_impl!(pub Option<unit::Type>);
+impl AssemblerBlock {
+ pub const fn new(
+ size: u8,
+ symmetric: bool,
+ build_cost: BuildCost,
+ valid: &'static [unit::Type],
+ ) -> Self {
+ if size == 0 {
+ panic!("invalid size");
+ }
+ if valid.is_empty() {
+ panic!("no valid units");
+ }
+ if valid.len() > i32::MAX as usize {
+ panic!("too many valid units");
+ }
+ Self {
+ size,
+ symmetric,
+ build_cost,
+ valid,
+ }
+ }
+
+ state_impl!(pub Option<unit::Type>);
}
-impl BlockLogic for AssemblerBlock
-{
- fn get_size(&self) -> u8
- {
- self.size
- }
-
- fn is_symmetric(&self) -> bool
- {
- self.symmetric
- }
-
- fn create_build_cost(&self) -> Option<Storage>
- {
- if !self.build_cost.is_empty()
- {
- let mut storage = Storage::new();
- for (ty, cnt) in self.build_cost
- {
- storage.add(*ty, *cnt, u32::MAX);
- }
- Some(storage)
- }
- else {None}
- }
-
- fn data_from_i32(&self, _: i32, _: GridPos) -> Result<DynData, DataConvertError>
- {
- Ok(DynData::Int(-1))
- }
-
- fn deserialize_state(&self, data: DynData) -> Result<Option<Box<dyn Any>>, DeserializeError>
- {
- match data
- {
- DynData::Empty => Ok(Some(Self::create_state(None))),
- DynData::Int(idx) =>
- {
- if idx == -1
- {
- Ok(Some(Self::create_state(None)))
- }
- else if idx >= 0 && idx < self.valid.len() as i32
- {
- Ok(Some(Self::create_state(Some(self.valid[idx as usize]))))
- }
- else
- {
- Err(DeserializeError::Custom(Box::new(AssemblerDeserializeError{idx, count: self.valid.len() as i32})))
- }
- },
- _ => Err(DeserializeError::InvalidType{have: data.get_type(), expect: DynType::Int}),
- }
- }
-
- fn clone_state(&self, state: &dyn Any) -> Box<dyn Any>
- {
- let state = Self::get_state(state);
- Box::new(Self::create_state(*state))
- }
-
- fn mirror_state(&self, _: &mut dyn Any, _: bool, _: bool)
- {
- }
-
- fn rotate_state(&self, _: &mut dyn Any, _: bool)
- {
- }
-
- fn serialize_state(&self, state: &dyn Any) -> Result<DynData, SerializeError>
- {
- if let Some(state) = Self::get_state(state)
- {
- for (i, curr) in self.valid.iter().enumerate()
- {
- if curr == state
- {
- return Ok(DynData::Int(i as i32));
- }
- }
- Err(SerializeError::Custom(Box::new(AssemblerSerializeError(*state))))
- }
- else
- {
- Ok(DynData::Int(-1))
- }
- }
+impl BlockLogic for AssemblerBlock {
+ fn get_size(&self) -> u8 {
+ self.size
+ }
+
+ fn is_symmetric(&self) -> bool {
+ self.symmetric
+ }
+
+ fn create_build_cost(&self) -> Option<Storage> {
+ if !self.build_cost.is_empty() {
+ let mut storage = Storage::new();
+ for (ty, cnt) in self.build_cost {
+ storage.add(*ty, *cnt, u32::MAX);
+ }
+ Some(storage)
+ } else {
+ None
+ }
+ }
+
+ fn data_from_i32(&self, _: i32, _: GridPos) -> Result<DynData, DataConvertError> {
+ Ok(DynData::Int(-1))
+ }
+
+ fn deserialize_state(&self, data: DynData) -> Result<Option<Box<dyn Any>>, DeserializeError> {
+ match data {
+ DynData::Empty => Ok(Some(Self::create_state(None))),
+ DynData::Int(idx) => {
+ if idx == -1 {
+ Ok(Some(Self::create_state(None)))
+ } else if idx >= 0 && idx < self.valid.len() as i32 {
+ Ok(Some(Self::create_state(Some(self.valid[idx as usize]))))
+ } else {
+ Err(DeserializeError::Custom(Box::new(
+ AssemblerDeserializeError {
+ idx,
+ count: self.valid.len() as i32,
+ },
+ )))
+ }
+ }
+ _ => Err(DeserializeError::InvalidType {
+ have: data.get_type(),
+ expect: DynType::Int,
+ }),
+ }
+ }
+
+ fn clone_state(&self, state: &dyn Any) -> Box<dyn Any> {
+ let state = Self::get_state(state);
+ Box::new(Self::create_state(*state))
+ }
+
+ fn mirror_state(&self, _: &mut dyn Any, _: bool, _: bool) {}
+
+ fn rotate_state(&self, _: &mut dyn Any, _: bool) {}
+
+ fn serialize_state(&self, state: &dyn Any) -> Result<DynData, SerializeError> {
+ if let Some(state) = Self::get_state(state) {
+ for (i, curr) in self.valid.iter().enumerate() {
+ if curr == state {
+ return Ok(DynData::Int(i as i32));
+ }
+ }
+ Err(SerializeError::Custom(Box::new(AssemblerSerializeError(
+ *state,
+ ))))
+ } else {
+ Ok(DynData::Int(-1))
+ }
+ }
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
-pub struct AssemblerDeserializeError
-{
- pub idx: i32,
- pub count: i32,
+pub struct AssemblerDeserializeError {
+ pub idx: i32,
+ pub count: i32,
}
-impl fmt::Display for AssemblerDeserializeError
-{
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
- {
- write!(f, "invalid unit index ({}, #valid: {})", self.idx, self.count)
- }
+impl fmt::Display for AssemblerDeserializeError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(
+ f,
+ "invalid unit index ({}, #valid: {})",
+ self.idx, self.count
+ )
+ }
}
impl Error for AssemblerDeserializeError {}
@@ -173,179 +164,155 @@ impl Error for AssemblerDeserializeError {}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct AssemblerSerializeError(unit::Type);
-impl fmt::Display for AssemblerSerializeError
-{
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
- {
- write!(f, "invalid unit ({:?}) is not valid", self.0)
- }
+impl fmt::Display for AssemblerSerializeError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "invalid unit ({:?}) is not valid", self.0)
+ }
}
impl Error for AssemblerSerializeError {}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
-pub enum Payload
-{
- Empty,
- Block(block::content::Type),
- Unit(unit::Type),
+pub enum Payload {
+ Empty,
+ Block(block::content::Type),
+ Unit(unit::Type),
}
-pub struct PayloadBlock
-{
- size: u8,
- symmetric: bool,
- build_cost: BuildCost,
+pub struct PayloadBlock {
+ size: u8,
+ symmetric: bool,
+ build_cost: BuildCost,
}
-impl PayloadBlock
-{
- pub const fn new(size: u8, symmetric: bool, build_cost: BuildCost) -> Self
- {
- if size == 0
- {
- panic!("invalid size");
- }
- Self{size, symmetric, build_cost}
- }
-
- state_impl!(pub Payload);
+impl PayloadBlock {
+ pub const fn new(size: u8, symmetric: bool, build_cost: BuildCost) -> Self {
+ if size == 0 {
+ panic!("invalid size");
+ }
+ Self {
+ size,
+ symmetric,
+ build_cost,
+ }
+ }
+
+ state_impl!(pub Payload);
}
-impl BlockLogic for PayloadBlock
-{
- fn get_size(&self) -> u8
- {
- self.size
- }
-
- fn is_symmetric(&self) -> bool
- {
- self.symmetric
- }
-
- fn create_build_cost(&self) -> Option<Storage>
- {
- if !self.build_cost.is_empty()
- {
- let mut storage = Storage::new();
- for (ty, cnt) in self.build_cost
- {
- storage.add(*ty, *cnt, u32::MAX);
- }
- Some(storage)
- }
- else {None}
- }
-
- fn data_from_i32(&self, _: i32, _: GridPos) -> Result<DynData, DataConvertError>
- {
- Ok(DynData::Empty)
- }
-
- fn deserialize_state(&self, data: DynData) -> Result<Option<Box<dyn Any>>, DeserializeError>
- {
- match data
- {
- DynData::Empty => Ok(Some(Self::create_state(Payload::Empty))),
- DynData::Content(content::Type::Block, id) =>
- {
- let block = PayloadDeserializeError::forward(block::content::Type::try_from(id))?;
- Ok(Some(Self::create_state(Payload::Block(block))))
- },
- DynData::Content(content::Type::Unit, id) =>
- {
- let unit = PayloadDeserializeError::forward(unit::Type::try_from(id))?;
- Ok(Some(Self::create_state(Payload::Unit(unit))))
- },
- DynData::Content(have, ..) => Err(DeserializeError::Custom(Box::new(PayloadDeserializeError::ContentType(have)))),
- _ => Err(DeserializeError::InvalidType{have: data.get_type(), expect: DynType::Content}),
- }
- }
-
- fn clone_state(&self, state: &dyn Any) -> Box<dyn Any>
- {
- let state = Self::get_state(state);
- Box::new(Self::create_state(*state))
- }
-
- fn mirror_state(&self, _: &mut dyn Any, _: bool, _: bool)
- {
- }
-
- fn rotate_state(&self, _: &mut dyn Any, _: bool)
- {
- }
-
- fn serialize_state(&self, state: &dyn Any) -> Result<DynData, SerializeError>
- {
- match Self::get_state(state)
- {
- Payload::Empty => Ok(DynData::Empty),
- Payload::Block(block) => Ok(DynData::Content(content::Type::Block, (*block).into())),
- Payload::Unit(unit) => Ok(DynData::Content(content::Type::Unit, (*unit).into())),
- }
- }
+impl BlockLogic for PayloadBlock {
+ fn get_size(&self) -> u8 {
+ self.size
+ }
+
+ fn is_symmetric(&self) -> bool {
+ self.symmetric
+ }
+
+ fn create_build_cost(&self) -> Option<Storage> {
+ if !self.build_cost.is_empty() {
+ let mut storage = Storage::new();
+ for (ty, cnt) in self.build_cost {
+ storage.add(*ty, *cnt, u32::MAX);
+ }
+ Some(storage)
+ } else {
+ None
+ }
+ }
+
+ fn data_from_i32(&self, _: i32, _: GridPos) -> Result<DynData, DataConvertError> {
+ Ok(DynData::Empty)
+ }
+
+ fn deserialize_state(&self, data: DynData) -> Result<Option<Box<dyn Any>>, DeserializeError> {
+ match data {
+ DynData::Empty => Ok(Some(Self::create_state(Payload::Empty))),
+ DynData::Content(content::Type::Block, id) => {
+ let block = PayloadDeserializeError::forward(block::content::Type::try_from(id))?;
+ Ok(Some(Self::create_state(Payload::Block(block))))
+ }
+ DynData::Content(content::Type::Unit, id) => {
+ let unit = PayloadDeserializeError::forward(unit::Type::try_from(id))?;
+ Ok(Some(Self::create_state(Payload::Unit(unit))))
+ }
+ DynData::Content(have, ..) => Err(DeserializeError::Custom(Box::new(
+ PayloadDeserializeError::ContentType(have),
+ ))),
+ _ => Err(DeserializeError::InvalidType {
+ have: data.get_type(),
+ expect: DynType::Content,
+ }),
+ }
+ }
+
+ fn clone_state(&self, state: &dyn Any) -> Box<dyn Any> {
+ let state = Self::get_state(state);
+ Box::new(Self::create_state(*state))
+ }
+
+ fn mirror_state(&self, _: &mut dyn Any, _: bool, _: bool) {}
+
+ fn rotate_state(&self, _: &mut dyn Any, _: bool) {}
+
+ fn serialize_state(&self, state: &dyn Any) -> Result<DynData, SerializeError> {
+ match Self::get_state(state) {
+ Payload::Empty => Ok(DynData::Empty),
+ Payload::Block(block) => Ok(DynData::Content(content::Type::Block, (*block).into())),
+ Payload::Unit(unit) => Ok(DynData::Content(content::Type::Unit, (*unit).into())),
+ }
+ }
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
-pub enum PayloadDeserializeError
-{
- ContentType(content::Type),
- BlockNotFound(block::content::TryFromU16Error),
- UnitNotFound(unit::TryFromU16Error),
+pub enum PayloadDeserializeError {
+ ContentType(content::Type),
+ BlockNotFound(block::content::TryFromU16Error),
+ UnitNotFound(unit::TryFromU16Error),
}
-impl PayloadDeserializeError
-{
- pub fn forward<T, E: Into<Self>>(result: Result<T, E>) -> Result<T, DeserializeError>
- {
- match result
- {
- Ok(v) => Ok(v),
- Err(e) => Err(DeserializeError::Custom(Box::new(e.into()))),
- }
- }
+impl PayloadDeserializeError {
+ pub fn forward<T, E: Into<Self>>(result: Result<T, E>) -> Result<T, DeserializeError> {
+ match result {
+ Ok(v) => Ok(v),
+ Err(e) => Err(DeserializeError::Custom(Box::new(e.into()))),
+ }
+ }
}
-impl From<block::content::TryFromU16Error> for PayloadDeserializeError
-{
- fn from(err: block::content::TryFromU16Error) -> Self
- {
- Self::BlockNotFound(err)
- }
+impl From<block::content::TryFromU16Error> for PayloadDeserializeError {
+ fn from(err: block::content::TryFromU16Error) -> Self {
+ Self::BlockNotFound(err)
+ }
}
-impl From<unit::TryFromU16Error> for PayloadDeserializeError
-{
- fn from(err: unit::TryFromU16Error) -> Self
- {
- Self::UnitNotFound(err)
- }
+impl From<unit::TryFromU16Error> for PayloadDeserializeError {
+ fn from(err: unit::TryFromU16Error) -> Self {
+ Self::UnitNotFound(err)
+ }
}
-impl fmt::Display for PayloadDeserializeError
-{
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
- {
- match self
- {
- Self::ContentType(have) => write!(f, "expected content {:?} or {:?} but got {have:?}", content::Type::Block, content::Type::Unit),
- Self::BlockNotFound(..) => f.write_str("payload block not found"),
- Self::UnitNotFound(..) => f.write_str("payload unit not found"),
- }
- }
+impl fmt::Display for PayloadDeserializeError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ Self::ContentType(have) => write!(
+ f,
+ "expected content {:?} or {:?} but got {have:?}",
+ content::Type::Block,
+ content::Type::Unit
+ ),
+ Self::BlockNotFound(..) => f.write_str("payload block not found"),
+ Self::UnitNotFound(..) => f.write_str("payload unit not found"),
+ }
+ }
}
-impl Error for PayloadDeserializeError
-{
- fn source(&self) -> Option<&(dyn Error + 'static)>
- {
- match self
- {
- Self::BlockNotFound(e) => Some(e),
- Self::UnitNotFound(e) => Some(e),
- _ => None,
- }
- }
+impl Error for PayloadDeserializeError {
+ fn source(&self) -> Option<&(dyn Error + 'static)> {
+ match self {
+ Self::BlockNotFound(e) => Some(e),
+ Self::UnitNotFound(e) => Some(e),
+ _ => None,
+ }
+ }
}