mindustry logic execution, map- and schematic- parsing and rendering
use the enum_dispatch crate
| -rw-r--r-- | Cargo.toml | 3 | ||||
| -rw-r--r-- | src/block/drills.rs | 11 | ||||
| -rw-r--r-- | src/block/mod.rs | 107 | ||||
| -rw-r--r-- | src/block/production.rs | 2 | ||||
| -rw-r--r-- | src/data/map.rs | 2 | ||||
| -rw-r--r-- | src/data/renderer.rs | 4 | ||||
| -rw-r--r-- | src/lib.rs | 2 |
7 files changed, 116 insertions, 15 deletions
@@ -1,6 +1,6 @@ [package] name = "mindus" -version = "2.0.2" +version = "2.0.3" edition = "2021" description = "A library for working with mindustry data formats (eg schematics and maps) (fork of plandustry)" authors = [ @@ -21,6 +21,7 @@ color-hex = "0.2" thiserror = "1.0" bobbin-bits = "0.1" blurslice = { version = "0.1" } +enum_dispatch = "0.3" [features] bin = ["image/png"] diff --git a/src/block/drills.rs b/src/block/drills.rs index 8e5c20e..01332b4 100644 --- a/src/block/drills.rs +++ b/src/block/drills.rs @@ -8,14 +8,17 @@ make_simple!( |_, name, _, _, rot: Rotation, s| { let mut base = load!(from name which is ["large-plasma-bore" | "plasma-bore" | "cliff-crusher"], s); - let mut top = load!(concat top => name which is ["large-plasma-bore" | "plasma-bore" | "cliff-crusher"], s); - top.rotate(rot.rotated(false).count()); - base.overlay(&top); + base.overlay(load!(concat top => name which is ["large-plasma-bore" | "plasma-bore" | "cliff-crusher"], s).rotate(rot.rotated(false).count())); base }, |_, _, _, buff: &mut DataRead| read_drill(buff) ); make_simple!(ExtractorBlock); +make_simple!(WallDrillBlock, |_, _, _, _, rot: Rotation, scl| { + let mut base = load!("cliff-crusher", scl); + base.overlay(load!("cliff-crusher-top", scl).rotate(rot.rotated(false).count())); + base +}); make_register! { "mechanical-drill" -> DrillBlock::new(2, true, cost!(Copper: 12)); @@ -25,7 +28,7 @@ make_register! { "water-extractor" -> ExtractorBlock::new(2, true, cost!(Copper: 30, Lead: 30, Metaglass: 30, Graphite: 30)); "oil-extractor" -> ExtractorBlock::new(3, true, cost!(Copper: 150, Lead: 115, Graphite: 175, Thorium: 115, Silicon: 75)); "vent-condenser" -> ProductionBlock::new(3, true, cost!(Graphite: 20, Beryllium: 60)); - "cliff-crusher" -> DrillBlock::new(2, false, cost!(Beryllium: 100, Graphite: 40)); + "cliff-crusher" -> WallDrillBlock::new(2, false, cost!(Beryllium: 100, Graphite: 40)); "plasma-bore" => DrillBlock::new(2, false, cost!(Beryllium: 40)); "large-plasma-bore" => DrillBlock::new(3, false, cost!(Silicon: 100, Oxide: 25, Beryllium: 100, Tungsten: 70)); "impact-drill" -> DrillBlock::new(4, true, cost!(Silicon: 70, Beryllium: 90, Graphite: 60)); diff --git a/src/block/mod.rs b/src/block/mod.rs index 66ea69e..efdc1ba 100644 --- a/src/block/mod.rs +++ b/src/block/mod.rs @@ -32,7 +32,94 @@ mods! { mod simple; +macro_rules! disp { + ($($k:ident,)+) => { + use all::{$($k,)+}; + #[enum_dispatch::enum_dispatch] + pub(crate) enum BlockLogicEnum { + $($k,)+ + } + #[const_trait] + pub trait ConstFrom<T>: Sized { + fn fro(value: T) -> Self; + } + $( + impl const ConstFrom<$k> for BlockLogicEnum { + fn fro(v: $k) -> Self { + BlockLogicEnum::$k(v) + } + } + )+ + + /*impl std::fmt::Debug for BlockLogicEnum { + fn fmt(&self, w: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { + match self { + $(BlockLogicEnum::$k { .. } => write!(w, stringify!($k)),)+ + } + } + }*/ + } +} + +disp! { + EnvironmentBlock, + WallBlock, + DuctBlock, + BridgeBlock, + ItemBlock, + BatteryBlock, + ProductionBlock, + StackConveyor, + HeatCrafter, + ConnectorBlock, + ItemTurret, + ExtractorBlock, + ControlBlock, + LiquidBlock, + ConveyorBlock, + WallDrillBlock, + DrillBlock, + NuclearGeneratorBlock, + GeneratorBlock, + ConduitBlock, + HeatedBlock, + PointDefenseTurret, + JunctionBlock, + DefenseBlock, + Turret, + MemoryBlock, + MessageLogic, + ConstructorBlock, + AssemblerBlock, + SimpleDuctBlock, + SurgeRouter, + UnitCargoLoader, + LogicBlock, + SimplePayloadBlock, + PayloadConveyor, + ImpactReactorBlock, + Neoplasia, + DiodeBlock, + HeatConduit, + Incinerator, + StorageBlock, + ContinousTurret, + TractorBeamTurret, + UnitRepairTower, + AssemblerModule, + RepairTurret, + FluidBlock, + CanvasBlock, + SwitchLogic, + ProcessorLogic, + PayloadBlock, + LampBlock, + DoorBlock, + CampaignBlock, +} + pub type State = Box<dyn Any + Sync + Send>; +#[enum_dispatch::enum_dispatch(BlockLogicEnum)] pub trait BlockLogic { /// mindustry blocks are the same width and height fn get_size(&self) -> u8; @@ -164,7 +251,7 @@ impl SerializeError { pub struct Block { image: Option<[&'static LazyLock<RgbaImage>; 3]>, name: &'static str, - pub(crate) logic: &'static (dyn BlockLogic + Sync), + pub(crate) logic: BlockLogicEnum, } impl PartialEq for Block { @@ -176,9 +263,9 @@ impl PartialEq for Block { impl Block { #[must_use] /// create a new block - pub const fn new( + pub(crate) const fn new( name: &'static str, - logic: &'static (dyn BlockLogic + Sync), + logic: BlockLogicEnum, image: Option<[&'static LazyLock<RgbaImage>; 3]>, ) -> Self { Self { name, logic, image } @@ -258,6 +345,16 @@ impl Block { pub(crate) fn serialize_state(&self, state: &State) -> Result<DynData, SerializeError> { self.logic.serialize_state(state) } + + pub(crate) fn read( + &self, + build: &mut Build, + reg: &BlockRegistry, + mapping: &EntityMapping, + buff: &mut DataRead, + ) -> Result<(), DataReadError> { + self.logic.read(build, reg, mapping, buff) + } } impl fmt::Debug for Block { @@ -446,12 +543,12 @@ macro_rules! make_register { }}; (impl $field: literal => $logic: expr) => { paste::paste! { pub static [<$field:snake:upper>]: $crate::block::Block = $crate::block::Block::new( - $field, &$logic, None + $field, <crate::block::BlockLogicEnum as crate::block::ConstFrom<_>>::fro($logic), None ); } }; (impl $field: literal -> $logic: expr) => { paste::paste! { pub static [<$field:snake:upper>]: $crate::block::Block = $crate::block::Block::new( - $field, &$logic, Some(crate::data::renderer::load!($field)) + $field, <crate::block::BlockLogicEnum as crate::block::ConstFrom<_>>::fro($logic), Some(crate::data::renderer::load!($field)) ); } } } diff --git a/src/block/production.rs b/src/block/production.rs index 8faf359..9954669 100644 --- a/src/block/production.rs +++ b/src/block/production.rs @@ -24,7 +24,7 @@ make_register! { "coal-centrifuge" -> ProductionBlock::new(2, true, cost!(Lead: 30, Graphite: 40, Titanium: 20)); "incinerator" -> Incinerator::new(1, true, cost!(Lead: 15, Graphite: 5)); "silicon-arc-furnace" -> ProductionBlock::new(3, true, cost!(Beryllium: 70, Graphite: 80)); - "electrolyzer" => ProductionBlock::new(3, true, cost!(Silicon: 50, Graphite: 40, Beryllium: 130, Tungsten: 80)); + "electrolyzer" -> ProductionBlock::new(3, true, cost!(Silicon: 50, Graphite: 40, Beryllium: 130, Tungsten: 80)); "atmospheric-concentrator" -> ProductionBlock::new(3, true, cost!(Oxide: 60, Beryllium: 180, Silicon: 150)); "oxidation-chamber" => HeatCrafter::new(3, true, cost!(Tungsten: 120, Graphite: 80, Silicon: 100, Beryllium: 120)); "electric-heater" => HeatCrafter::new(2, false, cost!(Tungsten: 30, Oxide: 30)); diff --git a/src/data/map.rs b/src/data/map.rs index 4bf26cf..911f522 100644 --- a/src/data/map.rs +++ b/src/data/map.rs @@ -295,7 +295,7 @@ impl<'l> Build<'l> { buff.skip(4)?; } // "overridden by subclasses" - self.block.logic.read(self, reg, map, buff)?; + self.block.read(self, reg, map, buff)?; // implementation not complete, simply error, causing the remaining bytes in the chunk to be skipped (TODO finish impl) Err(ReadError::Version(0x0)) // Ok(()) diff --git a/src/data/renderer.rs b/src/data/renderer.rs index 5234b60..bd101e5 100644 --- a/src/data/renderer.rs +++ b/src/data/renderer.rs @@ -115,8 +115,8 @@ macro_rules! load { ($name:literal, $scale:ident) => { paste::paste! { ImageHolder::from(std::sync::LazyLock::force(match $scale { $crate::data::renderer::Scale::Quarter => $crate::data::renderer::quar::[<$name:snake:upper>], - crate::data::renderer::Scale::Eigth => $crate::data::renderer::eigh::[<$name:snake:upper>], - crate::data::renderer::Scale::Full => $crate::data::renderer::full::[<$name:snake:upper>], + $crate::data::renderer::Scale::Eigth => $crate::data::renderer::eigh::[<$name:snake:upper>], + $crate::data::renderer::Scale::Full => $crate::data::renderer::full::[<$name:snake:upper>], })) } }; ($name: literal) => { paste::paste! { @@ -1,5 +1,5 @@ //! crate for dealing with mindustry -#![feature(lazy_cell, array_chunks)] +#![feature(lazy_cell, array_chunks, const_trait_impl)] pub mod block; mod content; pub mod data; |