Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'src/block/mod.rs')
-rw-r--r--src/block/mod.rs642
1 files changed, 0 insertions, 642 deletions
diff --git a/src/block/mod.rs b/src/block/mod.rs
deleted file mode 100644
index 15b6d97..0000000
--- a/src/block/mod.rs
+++ /dev/null
@@ -1,642 +0,0 @@
-//! deal with blocks.
-//!
-//! categorized as mindustry categorizes them in its assets folder, for easy drawing.
-//!
-//! with the exception of sandbox, that is.
-use bobbin_bits::U4::{self, B0000, B0001, B0010, B0100, B1000};
-use std::error::Error;
-use std::fmt;
-
-use crate::data::dynamic::{DynData, DynType};
-use crate::data::map::{Build, EntityMapping};
-use crate::data::{self, renderer::*, CompressError};
-use crate::data::{DataRead, GridPos, ReadError as DataReadError};
-use crate::item::storage::ItemStorage;
-use crate::registry::RegistryEntry;
-
-macro_rules! mods {
- ($($mod:ident)*) => {
- $(pub mod $mod;)*
-
- pub mod all {
- $(pub use crate::block::$mod::*;)*
- pub use super::simple::BasicBlock;
- }
- }
-}
-
-mods! {
- campaign content defense distribution drills environment liquid logic payload power production storage turrets walls units
-}
-
-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! {
- BasicBlock,
- WallBlock,
- DuctBlock,
- BridgeBlock,
- ItemBlock,
- ProductionBlock,
- SeparatorBlock,
- StackConveyor,
- HeatCrafter,
- ConnectorBlock,
- ItemTurret,
- ConveyorBlock,
- WallDrillBlock,
- DrillBlock,
- NuclearGeneratorBlock,
- GeneratorBlock,
- ConduitBlock,
- HeatedBlock,
- RadarBlock,
- ShieldBlock,
- PointDefenseTurret,
- JunctionBlock,
- Turret,
- MemoryBlock,
- MessageLogic,
- ConstructorBlock,
- AssemblerBlock,
- UnitFactory,
- SimpleDuctBlock,
- SurgeRouter,
- SimplePayloadBlock,
- PayloadConveyor,
- ImpactReactorBlock,
- Neoplasia,
- DiodeBlock,
- HeatConduit,
- ContinousTurret,
- TractorBeamTurret,
- AssemblerModule,
- RepairTurret,
- FluidBlock,
- CanvasBlock,
- SwitchLogic,
- ProcessorLogic,
- PayloadBlock,
- LampBlock,
- DoorBlock,
-}
-
-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<Vec<u8>, 1>),
- 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
- fn get_size(&self) -> u8;
-
- fn is_symmetric(&self) -> bool;
-
- fn create_build_cost(&self) -> Option<ItemStorage>;
-
- fn data_from_i32(&self, config: i32, pos: GridPos) -> Result<DynData, DataConvertError>;
-
- fn deserialize_state(&self, data: DynData) -> Result<Option<State>, DeserializeError>;
-
- #[allow(unused_variables)]
- fn mirror_state(&self, state: &mut State, horizontally: bool, vertically: bool) {}
-
- #[allow(unused_variables)]
- fn rotate_state(&self, state: &mut State, clockwise: bool) {}
-
- fn serialize_state(&self, state: &State) -> Result<DynData, SerializeError>;
-
- #[allow(unused_variables)]
- fn draw(
- &self,
- name: &str,
- state: Option<&State>,
- context: Option<&RenderingContext>,
- rot: Rotation,
- scale: Scale,
- ) -> ImageHolder<4> {
- unimplemented!("{name}")
- }
-
- #[allow(unused_variables)]
- fn read(
- &self,
- build: &mut Build,
- reg: &BlockRegistry,
- mapping: &EntityMapping,
- buff: &mut DataRead,
- ) -> Result<(), DataReadError> {
- Ok(())
- }
-}
-
-// i wish i could derive
-macro_rules! impl_block {
- () => {
- fn get_size(&self) -> u8 {
- self.size
- }
-
- fn is_symmetric(&self) -> bool {
- self.symmetric
- }
-
- fn create_build_cost(&self) -> Option<$crate::item::storage::ItemStorage> {
- if self.build_cost.is_empty() {
- None
- } else {
- let mut storage = crate::item::storage::Storage::new();
- for (ty, cnt) in self.build_cost {
- storage.add(*ty, *cnt, u32::MAX);
- }
- Some(storage)
- }
- }
- };
-}
-pub(crate) use impl_block;
-
-#[derive(Debug, thiserror::Error)]
-pub enum DataConvertError {
- #[error(transparent)]
- Custom(#[from] Box<dyn Error + Sync + Send>),
-}
-
-impl DataConvertError {
- pub fn forward<T, E: Error + Sync + Send + 'static>(result: Result<T, E>) -> Result<T, Self> {
- match result {
- Ok(v) => Ok(v),
- Err(e) => Err(Self::Custom(Box::new(e))),
- }
- }
-}
-
-#[derive(Debug, thiserror::Error)]
-pub enum DeserializeError {
- #[error(transparent)]
- DecompressError(#[from] data::DecompressError),
- #[error("expected type {expect:?} but got {have:?}")]
- InvalidType { have: DynType, expect: DynType },
- #[error(transparent)]
- Custom(#[from] Box<dyn Error + Sync + Send>),
-}
-
-impl DeserializeError {
- pub fn forward<T, E: Error + Sync + Send + 'static>(result: Result<T, E>) -> Result<T, Self> {
- match result {
- Ok(v) => Ok(v),
- Err(e) => Err(Self::Custom(Box::new(e))),
- }
- }
-}
-
-#[derive(Debug, thiserror::Error)]
-pub enum SerializeError {
- #[error(transparent)]
- Custom(#[from] Box<dyn Error + Sync + Send>),
- #[error(transparent)]
- Compress(#[from] CompressError),
-}
-
-impl SerializeError {
- pub fn forward<T, E: Error + Sync + Send + 'static>(result: Result<T, E>) -> Result<T, Self> {
- match result {
- Ok(v) => Ok(v),
- Err(e) => Err(Self::Custom(Box::new(e))),
- }
- }
-}
-
-/// a block. put it in stuff!
-pub struct Block {
- image: Option<[Image<&'static [u8], 4>; 3]>,
- name: &'static str,
- logic: BlockLogicEnum,
-}
-
-impl PartialEq for Block {
- fn eq(&self, rhs: &Block) -> bool {
- self.name == rhs.name
- }
-}
-
-impl Block {
- /// create a new block
- #[must_use]
- #[inline]
- pub(crate) const fn new(
- name: &'static str,
- logic: BlockLogicEnum,
- image: Option<[Image<&'static [u8], 4>; 3]>,
- ) -> Self {
- Self { image, name, logic }
- }
-
- /// this blocks name
- /// ```
- /// assert!(mindus::block::distribution::DISTRIBUTOR.name() == "distributor")
- /// ```
- #[must_use]
- #[inline]
- pub const fn name(&self) -> &'static str {
- self.name
- }
-
- /// should you send context to [`image`]?
- #[must_use]
- #[inline]
- pub fn wants_context(&self) -> bool {
- use BlockLogicEnum::*;
- matches!(
- self.logic,
- ConveyorBlock(..) | DuctBlock(..) | StackConveyor(..) | ConduitBlock(..)
- )
- }
-
- /// draw this block, with this state
- #[must_use]
- #[inline]
- pub fn image(
- &self,
- state: Option<&State>,
- context: Option<&RenderingContext>,
- rot: Rotation,
- scale: Scale,
- ) -> ImageHolder<4> {
- if let Some(imgs) = &self.image {
- return ImageHolder::from((imgs[scale as usize]).copy());
- }
- self.logic.draw(self.name, state, context, rot, scale)
- }
-
- /// size.
- #[must_use]
- #[inline]
- pub fn get_size(&self) -> u8 {
- self.logic.get_size()
- }
-
- /// does it matter if its rotated
- #[must_use]
- #[inline]
- pub fn is_symmetric(&self) -> bool {
- self.logic.is_symmetric()
- }
-
- /// cost
- #[must_use]
- #[inline]
- pub fn get_build_cost(&self) -> Option<ItemStorage> {
- self.logic.create_build_cost()
- }
-
- pub(crate) fn data_from_i32(
- &self,
- config: i32,
- pos: GridPos,
- ) -> Result<DynData, DataConvertError> {
- self.logic.data_from_i32(config, pos)
- }
-
- pub(crate) fn deserialize_state(
- &self,
- data: DynData,
- ) -> Result<Option<State>, DeserializeError> {
- self.logic.deserialize_state(data)
- }
-
- pub(crate) fn mirror_state(&self, state: &mut State, horizontally: bool, vertically: bool) {
- self.logic.mirror_state(state, horizontally, vertically);
- }
-
- pub(crate) fn rotate_state(&self, state: &mut State, clockwise: bool) {
- self.logic.rotate_state(state, clockwise);
- }
-
- pub(crate) fn serialize_state(&self, state: &State) -> Result<DynData, SerializeError> {
- self.logic.serialize_state(state)
- }
-
- #[inline]
- 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 {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "Block<{:?}>", self.name)
- }
-}
-
-impl RegistryEntry for Block {
- fn get_name(&self) -> &str {
- self.name
- }
-}
-
-#[derive(Clone, Copy, Debug, Eq, PartialEq)]
-/// the possible rotation states of a object
-#[repr(u8)]
-pub enum Rotation {
- Up,
- Right,
- Down,
- Left,
-}
-
-impl Rotation {
- #[must_use]
- /// count rotations
- pub const fn count(self) -> u8 {
- self as u8
- }
-
- #[must_use]
- /// mask
- pub const fn mask(self) -> U4 {
- match self {
- Rotation::Up => B1000,
- Rotation::Right => B0100,
- Rotation::Down => B0010,
- Rotation::Left => B0001,
- }
- }
-
- #[must_use]
- /// character of this rot (Right => >, Up => ^, Left => <, Down => v)
- pub const fn ch(self) -> char {
- match self {
- Rotation::Right => '>',
- Rotation::Up => '^',
- Rotation::Left => '<',
- Rotation::Down => 'v',
- }
- }
-
- #[must_use]
- /// mirror the directions.
- pub const fn mirrored(self, horizontally: bool, vertically: bool) -> Self {
- match self {
- Self::Right => {
- if horizontally {
- Self::Left
- } else {
- Self::Right
- }
- }
- Self::Up => {
- if vertically {
- Self::Down
- } else {
- Self::Up
- }
- }
- Self::Left => {
- if horizontally {
- Self::Right
- } else {
- Self::Left
- }
- }
- Self::Down => {
- if vertically {
- Self::Up
- } else {
- Self::Down
- }
- }
- }
- }
-
- /// mirror in place
- pub fn mirror(&mut self, horizontally: bool, vertically: bool) {
- *self = self.mirrored(horizontally, vertically);
- }
-
- #[must_use]
- /// rotate the rotation
- pub const fn rotated(self, clockwise: bool) -> Self {
- match self {
- Self::Right => {
- if clockwise {
- Self::Down
- } else {
- Self::Up
- }
- }
- Self::Up => {
- if clockwise {
- Self::Right
- } else {
- Self::Left
- }
- }
- Self::Left => {
- if clockwise {
- Self::Up
- } else {
- Self::Down
- }
- }
- Self::Down => {
- if clockwise {
- Self::Left
- } else {
- Self::Right
- }
- }
- }
- }
-
- /// rotate the rotation in place
- pub fn rotate(&mut self, clockwise: bool) {
- *self = self.rotated(clockwise);
- }
-
- #[must_use]
- /// rotate 180
- pub const fn rotated_180(self) -> Self {
- match self {
- Self::Right => Self::Left,
- Self::Up => Self::Down,
- Self::Left => Self::Right,
- Self::Down => Self::Up,
- }
- }
-
- /// rotate 180 in place
- pub fn rotate_180(&mut self) {
- *self = self.rotated_180();
- }
-}
-
-impl From<u8> for Rotation {
- fn from(val: u8) -> Self {
- match val & 3 {
- 0 => Self::Right,
- 1 => Self::Up,
- 2 => Self::Left,
- _ => Self::Down,
- }
- }
-}
-
-impl From<Rotation> for u8 {
- fn from(rot: Rotation) -> Self {
- match rot {
- Rotation::Right => 0,
- Rotation::Up => 1,
- Rotation::Left => 2,
- Rotation::Down => 3,
- }
- }
-}
-
-pub type BlockRegistry<'l> = crate::registry::Registry<'l, Block>;
-pub type RegisterError<'l> = crate::registry::RegisterError<'l, Block>;
-
-macro_rules! make_register {
- ($($field:literal $op:tt $logic:expr;)+) => { paste::paste! {
- $(
- $crate::block::make_register!(impl $field $op $logic);
- )+
-
- pub(crate) fn register(reg: &mut $crate::block::BlockRegistry<'_>) {
- // get the static we make
- $(assert!(reg.register(&[<$field:snake:upper>]).is_ok());)+
- }
- }};
- (impl $field: literal => $logic: expr) => {
- paste::paste! { pub static [<$field:snake:upper>]: $crate::block::Block = $crate::block::Block::new(
- $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, <crate::block::BlockLogicEnum as crate::block::ConstFrom<_>>::fro($logic), Some(crate::data::renderer::load!($field))
- ); }
- }
-}
-pub(crate) use make_register;
-
-#[must_use]
-/// create a block registry
-pub fn build_registry() -> BlockRegistry<'static> {
- let mut reg = BlockRegistry::default();
- register(&mut reg);
- reg
-}
-
-fn register(reg: &mut BlockRegistry<'_>) {
- turrets::register(reg);
- drills::register(reg);
- distribution::register(reg);
- storage::register(reg);
- liquid::register(reg);
- power::register(reg);
- defense::register(reg);
- production::register(reg);
- payload::register(reg);
- campaign::register(reg);
- logic::register(reg);
- walls::register(reg);
- environment::register(reg);
- units::register(reg);
-}