mindustry logic execution, map- and schematic- parsing and rendering
fix bad segment + parallax + sandbox item rendering
bendn 2023-06-29
parent f9253eb · commit 08e123a
-rw-r--r--Cargo.toml2
-rw-r--r--assets/blocks/defense/force-projector-top.pngbin286 -> 0 bytes
-rw-r--r--assets/blocks/defense/mend-projector-top.pngbin222 -> 0 bytes
-rw-r--r--assets/blocks/defense/mender-top.pngbin157 -> 0 bytes
-rw-r--r--assets/blocks/defense/overdrive-dome-top.pngbin516 -> 0 bytes
-rw-r--r--assets/blocks/defense/overdrive-projector-top.pngbin257 -> 0 bytes
-rw-r--r--assets/blocks/defense/parallax.pngbin656 -> 0 bytes
-rw-r--r--assets/blocks/defense/segment.pngbin687 -> 0 bytes
-rw-r--r--assets/blocks/distribution/item-source.png (renamed from assets/blocks/sandbox/item-source.png)bin296 -> 296 bytes
-rw-r--r--assets/blocks/distribution/item-void.png (renamed from assets/blocks/sandbox/item-void.png)bin356 -> 356 bytes
-rw-r--r--assets/blocks/liquid/liquid-source.png (renamed from assets/blocks/sandbox/liquid-source.png)bin286 -> 286 bytes
-rw-r--r--assets/blocks/liquid/liquid-void.png (renamed from assets/blocks/sandbox/liquid-void.png)bin366 -> 366 bytes
-rw-r--r--assets/blocks/power/differential-generator-top.pngbin639 -> 0 bytes
-rw-r--r--assets/blocks/power/thorium-reactor-top.pngbin779 -> 0 bytes
-rw-r--r--assets/blocks/production/heat-source.png (renamed from assets/blocks/sandbox/heat-source.png)bin517 -> 517 bytes
-rw-r--r--assets/blocks/production/kiln-top.pngbin211 -> 0 bytes
-rw-r--r--assets/blocks/production/plastanium-compressor-top.pngbin382 -> 0 bytes
-rw-r--r--assets/blocks/production/silicon-crucible-top.pngbin418 -> 0 bytes
-rw-r--r--assets/blocks/sandbox/heat-source-heat.pngbin838 -> 0 bytes
-rw-r--r--assets/blocks/sandbox/source-bottom.pngbin121 -> 0 bytes
-rw-r--r--assets/blocks/turrets/parallax.pngbin0 -> 830 bytes
-rw-r--r--assets/blocks/turrets/segment.pngbin0 -> 791 bytes
-rw-r--r--build.rs1
-rw-r--r--src/block/base.rs104
-rw-r--r--src/block/campaign.rs8
-rw-r--r--src/block/defense.rs108
-rw-r--r--src/block/distribution.rs21
-rw-r--r--src/block/liquid.rs21
-rw-r--r--src/block/logic.rs1
-rw-r--r--src/block/mod.rs19
-rw-r--r--src/block/power.rs77
-rw-r--r--src/block/production.rs2
-rw-r--r--src/block/storage.rs4
-rw-r--r--src/block/walls.rs93
-rw-r--r--src/content.rs21
-rw-r--r--src/data/renderer.rs31
-rw-r--r--src/fluid/mod.rs26
-rw-r--r--src/item/mod.rs72
-rw-r--r--src/lib.rs1
-rw-r--r--src/utils/image.rs14
-rw-r--r--src/utils/mod.rs1
41 files changed, 333 insertions, 294 deletions
diff --git a/Cargo.toml b/Cargo.toml
index c440e2a..0116b57 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "mindus"
-version = "1.0.1"
+version = "1.0.2"
edition = "2021"
description = "A library for working with mindustry data formats (eg schematics) (fork of plandustry)"
authors = [
diff --git a/assets/blocks/defense/force-projector-top.png b/assets/blocks/defense/force-projector-top.png
deleted file mode 100644
index 540cc9b..0000000
--- a/assets/blocks/defense/force-projector-top.png
+++ /dev/null
Binary files differ
diff --git a/assets/blocks/defense/mend-projector-top.png b/assets/blocks/defense/mend-projector-top.png
deleted file mode 100644
index 24c80c0..0000000
--- a/assets/blocks/defense/mend-projector-top.png
+++ /dev/null
Binary files differ
diff --git a/assets/blocks/defense/mender-top.png b/assets/blocks/defense/mender-top.png
deleted file mode 100644
index c1feb99..0000000
--- a/assets/blocks/defense/mender-top.png
+++ /dev/null
Binary files differ
diff --git a/assets/blocks/defense/overdrive-dome-top.png b/assets/blocks/defense/overdrive-dome-top.png
deleted file mode 100644
index 4daa23b..0000000
--- a/assets/blocks/defense/overdrive-dome-top.png
+++ /dev/null
Binary files differ
diff --git a/assets/blocks/defense/overdrive-projector-top.png b/assets/blocks/defense/overdrive-projector-top.png
deleted file mode 100644
index 5b51c8d..0000000
--- a/assets/blocks/defense/overdrive-projector-top.png
+++ /dev/null
Binary files differ
diff --git a/assets/blocks/defense/parallax.png b/assets/blocks/defense/parallax.png
deleted file mode 100644
index 2b6109e..0000000
--- a/assets/blocks/defense/parallax.png
+++ /dev/null
Binary files differ
diff --git a/assets/blocks/defense/segment.png b/assets/blocks/defense/segment.png
deleted file mode 100644
index 57da490..0000000
--- a/assets/blocks/defense/segment.png
+++ /dev/null
Binary files differ
diff --git a/assets/blocks/sandbox/item-source.png b/assets/blocks/distribution/item-source.png
index 21c254c..21c254c 100644
--- a/assets/blocks/sandbox/item-source.png
+++ b/assets/blocks/distribution/item-source.png
Binary files differ
diff --git a/assets/blocks/sandbox/item-void.png b/assets/blocks/distribution/item-void.png
index eb3e38a..eb3e38a 100644
--- a/assets/blocks/sandbox/item-void.png
+++ b/assets/blocks/distribution/item-void.png
Binary files differ
diff --git a/assets/blocks/sandbox/liquid-source.png b/assets/blocks/liquid/liquid-source.png
index 92693f9..92693f9 100644
--- a/assets/blocks/sandbox/liquid-source.png
+++ b/assets/blocks/liquid/liquid-source.png
Binary files differ
diff --git a/assets/blocks/sandbox/liquid-void.png b/assets/blocks/liquid/liquid-void.png
index 0aa9e75..0aa9e75 100644
--- a/assets/blocks/sandbox/liquid-void.png
+++ b/assets/blocks/liquid/liquid-void.png
Binary files differ
diff --git a/assets/blocks/power/differential-generator-top.png b/assets/blocks/power/differential-generator-top.png
deleted file mode 100644
index eb504bc..0000000
--- a/assets/blocks/power/differential-generator-top.png
+++ /dev/null
Binary files differ
diff --git a/assets/blocks/power/thorium-reactor-top.png b/assets/blocks/power/thorium-reactor-top.png
deleted file mode 100644
index a22ce50..0000000
--- a/assets/blocks/power/thorium-reactor-top.png
+++ /dev/null
Binary files differ
diff --git a/assets/blocks/sandbox/heat-source.png b/assets/blocks/production/heat-source.png
index e281804..e281804 100644
--- a/assets/blocks/sandbox/heat-source.png
+++ b/assets/blocks/production/heat-source.png
Binary files differ
diff --git a/assets/blocks/production/kiln-top.png b/assets/blocks/production/kiln-top.png
deleted file mode 100644
index 54b786e..0000000
--- a/assets/blocks/production/kiln-top.png
+++ /dev/null
Binary files differ
diff --git a/assets/blocks/production/plastanium-compressor-top.png b/assets/blocks/production/plastanium-compressor-top.png
deleted file mode 100644
index 5289200..0000000
--- a/assets/blocks/production/plastanium-compressor-top.png
+++ /dev/null
Binary files differ
diff --git a/assets/blocks/production/silicon-crucible-top.png b/assets/blocks/production/silicon-crucible-top.png
deleted file mode 100644
index 36cc10b..0000000
--- a/assets/blocks/production/silicon-crucible-top.png
+++ /dev/null
Binary files differ
diff --git a/assets/blocks/sandbox/heat-source-heat.png b/assets/blocks/sandbox/heat-source-heat.png
deleted file mode 100644
index 92ae12d..0000000
--- a/assets/blocks/sandbox/heat-source-heat.png
+++ /dev/null
Binary files differ
diff --git a/assets/blocks/sandbox/source-bottom.png b/assets/blocks/sandbox/source-bottom.png
deleted file mode 100644
index a2dd7b5..0000000
--- a/assets/blocks/sandbox/source-bottom.png
+++ /dev/null
Binary files differ
diff --git a/assets/blocks/turrets/parallax.png b/assets/blocks/turrets/parallax.png
new file mode 100644
index 0000000..881149a
--- /dev/null
+++ b/assets/blocks/turrets/parallax.png
Binary files differ
diff --git a/assets/blocks/turrets/segment.png b/assets/blocks/turrets/segment.png
new file mode 100644
index 0000000..6b752af
--- /dev/null
+++ b/assets/blocks/turrets/segment.png
Binary files differ
diff --git a/build.rs b/build.rs
index b740e86..e9ce4ca 100644
--- a/build.rs
+++ b/build.rs
@@ -50,6 +50,7 @@ where
}
fn main() -> Result<(), ZipError> {
+ let _ = std::fs::remove_dir_all("target/out");
let walkdir = WalkDir::new("assets");
let it = walkdir.into_iter();
println!("cargo:rerun-if-changed=assets/");
diff --git a/src/block/base.rs b/src/block/base.rs
deleted file mode 100644
index fde5c5a..0000000
--- a/src/block/base.rs
+++ /dev/null
@@ -1,104 +0,0 @@
-//! all the uncategorized blocks (they need to be categorized for proper rendering tho)
-use std::any::Any;
-
-use crate::block::simple::{cost, state_impl, BuildCost, SimpleBlock};
-use crate::block::{
- impl_block, make_register, BlockLogic, DataConvertError, DeserializeError, SerializeError,
-};
-use crate::data::dynamic::{DynData, DynType};
-use crate::data::GridPos;
-use crate::item::storage::Storage;
-
-make_register! {
- "mender" => SimpleBlock::new(1, true, cost!(Copper: 25, Lead: 30));
- "mend-projector" => SimpleBlock::new(2, true, cost!(Copper: 50, Lead: 100, Titanium: 25, Silicon: 40));
- "overdrive-projector" => SimpleBlock::new(2, true, cost!(Lead: 100, Titanium: 75, Silicon: 75, Plastanium: 30));
- "overdrive-dome" => SimpleBlock::new(3, true, cost!(Lead: 200, Titanium: 130, Silicon: 130, Plastanium: 80, SurgeAlloy: 120));
- "force-projector" => SimpleBlock::new(3, true, cost!(Lead: 100, Titanium: 75, Silicon: 125));
- "shock-mine" => SimpleBlock::new(1, true, cost!(Lead: 25, Silicon: 12));
- "illuminator" => LampBlock::new(1, true, cost!(Lead: 8, Graphite: 12, Silicon: 8));
- "launch-pad" => SimpleBlock::new(3, true, cost!(Copper: 350, Lead: 200, Titanium: 150, Silicon: 140));
- "radar" => SimpleBlock::new(1, true, cost!(Silicon: 60, Graphite: 50, Beryllium: 10));
- "build-tower" => SimpleBlock::new(3, true, cost!(Silicon: 150, Oxide: 40, Thorium: 60));
- "regen-projector" => SimpleBlock::new(3, true, cost!(Silicon: 80, Tungsten: 60, Oxide: 40, Beryllium: 80));
- // barrier projector
- // editor only
- "shockwave-tower" => SimpleBlock::new(3, true, cost!(SurgeAlloy: 50, Silicon: 150, Oxide: 30, Tungsten: 100));
- "shield-projector" => SimpleBlock::new(3, true, &[]);
- "large-shield-projector" => SimpleBlock::new(4, true, &[]);
-}
-
-#[derive(Clone, Copy, Debug, Eq, PartialEq)]
-pub struct RGBA(u8, u8, u8, u8);
-
-impl From<u32> for RGBA {
- fn from(value: u32) -> Self {
- Self(
- (value >> 24) as u8,
- (value >> 16) as u8,
- (value >> 8) as u8,
- value as u8,
- )
- }
-}
-
-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)
- | u32::from(value.3)
- }
-}
-
-pub struct LampBlock {
- size: u8,
- symmetric: bool,
- build_cost: BuildCost,
-}
-
-impl LampBlock {
- #[must_use]
- pub const fn new(size: u8, symmetric: bool, build_cost: BuildCost) -> Self {
- assert!(size != 0, "invalid size");
- Self {
- size,
- symmetric,
- build_cost,
- }
- }
-
- state_impl!(pub RGBA);
-}
-
-impl BlockLogic for LampBlock {
- impl_block!();
-
- fn data_from_i32(&self, config: i32, _: GridPos) -> Result<DynData, DataConvertError> {
- Ok(DynData::Int(config))
- }
-
- fn deserialize_state(&self, data: DynData) -> Result<Option<Box<dyn Any>>, DeserializeError> {
- match data {
- DynData::Int(rgba) => Ok(Some(Self::create_state(RGBA::from(rgba as u32)))),
- _ => 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> {
- let state = Self::get_state(state);
- Ok(DynData::Int(u32::from(*state) as i32))
- }
-}
diff --git a/src/block/campaign.rs b/src/block/campaign.rs
new file mode 100644
index 0000000..9c87a15
--- /dev/null
+++ b/src/block/campaign.rs
@@ -0,0 +1,8 @@
+//! campaign blocks
+use crate::block::make_register;
+use crate::block::simple::{cost, SimpleBlock};
+
+make_register! {
+ "launch-pad" => SimpleBlock::new(3, true, cost!(Copper: 350, Lead: 200, Titanium: 150, Silicon: 140));
+ "interplanetary-accelerator" => SimpleBlock::new(7, true, cost!(Copper: 16000, Silicon: 11000, Thorium: 13000, Titanium: 12000, SurgeAlloy: 6000, PhaseFabric: 5000));
+}
diff --git a/src/block/defense.rs b/src/block/defense.rs
index 2cf3bbc..e197c37 100644
--- a/src/block/defense.rs
+++ b/src/block/defense.rs
@@ -1,93 +1,19 @@
-//! walls
-use std::any::Any;
-
-use crate::block::simple::{cost, state_impl, BuildCost, SimpleBlock};
-use crate::block::{
- impl_block, make_register, BlockLogic, DataConvertError, DeserializeError, SerializeError,
-};
-use crate::data::dynamic::{DynData, DynType};
-use crate::data::GridPos;
-use crate::item::storage::Storage;
-
+//! defense
+use crate::block::make_register;
+use crate::block::simple::{cost, SimpleBlock};
make_register! {
- "copper-wall" => SimpleBlock::new(1, true, cost!(Copper: 6));
- "copper-wall-large" => SimpleBlock::new(2, true, cost!(Copper: 6 * 4));
- "titanium-wall" => SimpleBlock::new(1, true, cost!(Titanium: 6));
- "titanium-wall-large" => SimpleBlock::new(2, true, cost!(Titanium: 6 * 4));
- "plastanium-wall" => SimpleBlock::new(1, true, cost!(Metaglass: 2, Plastanium: 5));
- "plastanium-wall-large" => SimpleBlock::new(2, true, cost!(Metaglass: 2 * 4, Plastanium: 5 * 4));
- "thorium-wall" => SimpleBlock::new(1, true, cost!(Thorium: 6));
- "thorium-wall-large" => SimpleBlock::new(2, true, cost!(Thorium: 6 * 4));
- "phase-wall" => SimpleBlock::new(1, true, cost!(PhaseFabric: 6));
- "phase-wall-large" => SimpleBlock::new(2, true, cost!(PhaseFabric: 6 * 4));
- "surge-wall" => SimpleBlock::new(1, true, cost!(SurgeAlloy: 6));
- "surge-wall-large" => SimpleBlock::new(2, true, cost!(SurgeAlloy: 6 * 4));
- "door" => DoorBlock::new(1, true, cost!(Titanium: 6, Silicon: 4));
- "door-large" => DoorBlock::new(2, true, cost!(Titanium: 6 * 4, Silicon: 4 * 4));
- "tungsten-wall" => SimpleBlock::new(1, true, cost!(Tungsten: 6));
- "large-tungsten-wall" => SimpleBlock::new(2, true, cost!(Tungsten: 6 * 4));
- "blast-door" => DoorBlock::new(2, true, cost!(Tungsten: 24, Silicon: 24));
- "reinforced-surge-wall" => SimpleBlock::new(1, true, cost!(SurgeAlloy: 6, Tungsten: 2));
- "reinforced-surge-wall-large" => SimpleBlock::new(2, true, cost!(SurgeAlloy: 6 * 4, Tungsten: 2 * 4));
- "carbide-wall" => SimpleBlock::new(1, true, cost!(Thorium: 6, Carbide: 6));
- "carbide-wall-large" => SimpleBlock::new(2, true, cost!(Thorium: 6 * 4, Carbide: 6 * 4));
- "shielded-wall" => SimpleBlock::new(2, true, cost!(PhaseFabric: 20, SurgeAlloy: 12, Beryllium: 12));
- // sandbox only
- "scrap-wall" => SimpleBlock::new(1, true, cost!(Scrap: 6));
- "scrap-wall-large" => SimpleBlock::new(2, true, cost!(Scrap: 24));
- "scrap-wall-huge" => SimpleBlock::new(3, true, cost!(Scrap: 54));
- "scrap-wall-gigantic" => SimpleBlock::new(4, true, cost!(Scrap: 96));
- "thruster" => SimpleBlock::new(4, false, cost!(Scrap: 96));
-}
-
-pub struct DoorBlock {
- size: u8,
- symmetric: bool,
- build_cost: BuildCost,
-}
-
-impl DoorBlock {
- #[must_use]
- pub const fn new(size: u8, symmetric: bool, build_cost: BuildCost) -> Self {
- assert!(size != 0, "invalid size");
- Self {
- size,
- symmetric,
- build_cost,
- }
- }
-
- state_impl!(pub bool);
-}
-
-impl BlockLogic for DoorBlock {
- impl_block!();
-
- fn data_from_i32(&self, _: i32, _: GridPos) -> Result<DynData, DataConvertError> {
- Ok(DynData::Boolean(false))
- }
-
- fn deserialize_state(&self, data: DynData) -> Result<Option<Box<dyn Any>>, DeserializeError> {
- match data {
- DynData::Boolean(opened) => Ok(Some(Self::create_state(opened))),
- _ => Err(DeserializeError::InvalidType {
- have: data.get_type(),
- expect: DynType::Boolean,
- }),
- }
- }
-
- 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> {
- let state = Self::get_state(state);
- Ok(DynData::Boolean(*state))
- }
+ "mender" => SimpleBlock::new(1, true, cost!(Copper: 25, Lead: 30));
+ "mend-projector" => SimpleBlock::new(2, true, cost!(Copper: 50, Lead: 100, Titanium: 25, Silicon: 40));
+ "overdrive-projector" => SimpleBlock::new(2, true, cost!(Lead: 100, Titanium: 75, Silicon: 75, Plastanium: 30));
+ "overdrive-dome" => SimpleBlock::new(3, true, cost!(Lead: 200, Titanium: 130, Silicon: 130, Plastanium: 80, SurgeAlloy: 120));
+ "force-projector" => SimpleBlock::new(3, true, cost!(Lead: 100, Titanium: 75, Silicon: 125));
+ "regen-projector" => SimpleBlock::new(3, true, cost!(Silicon: 80, Tungsten: 60, Oxide: 40, Beryllium: 80));
+ "shock-mine" => SimpleBlock::new(1, true, cost!(Lead: 25, Silicon: 12));
+ "radar" => SimpleBlock::new(1, true, cost!(Silicon: 60, Graphite: 50, Beryllium: 10));
+ "build-tower" => SimpleBlock::new(3, true, cost!(Silicon: 150, Oxide: 40, Thorium: 60));
+ // barrier projector
+ // editor only
+ "shockwave-tower" => SimpleBlock::new(3, true, cost!(SurgeAlloy: 50, Silicon: 150, Oxide: 30, Tungsten: 100));
+ "shield-projector" => SimpleBlock::new(3, true, &[]);
+ "large-shield-projector" => SimpleBlock::new(4, true, &[]);
}
diff --git a/src/block/distribution.rs b/src/block/distribution.rs
index 9076a12..1114115 100644
--- a/src/block/distribution.rs
+++ b/src/block/distribution.rs
@@ -3,7 +3,7 @@ use std::any::Any;
use std::error::Error;
use std::fmt;
-use image::{Rgba, RgbaImage};
+use image::RgbaImage;
use crate::block::simple::{cost, state_impl, BuildCost, SimpleBlock};
use crate::block::{
@@ -110,22 +110,17 @@ impl BlockLogic for ItemBlock {
}
fn draw(&self, category: &str, name: &str, state: Option<&dyn Any>) -> Option<RgbaImage> {
+ if !matches!(
+ name,
+ "unloader" | "item-source" | "sorter" | "inverted-sorter"
+ ) {
+ return None;
+ }
let mut p = load(category, name).unwrap();
if let Some(state) = state {
if let Some(s) = Self::get_state(state) {
- let item_c = s.color();
- let [tr, tg, tb] = [
- item_c[0] as f32 / 255.0,
- item_c[1] as f32 / 255.0,
- item_c[2] as f32 / 255.0,
- ];
let mut top = load(category, "center").unwrap();
- for Rgba([r, g, b, _]) in top.pixels_mut() {
- *r = (*r as f32 * tr) as u8;
- *g = (*g as f32 * tg) as u8;
- *b = (*b as f32 * tb) as u8;
- }
-
+ crate::utils::image::tint(&mut top, s.color());
image::imageops::overlay(&mut p, &top, 0, 0);
return Some(p);
}
diff --git a/src/block/liquid.rs b/src/block/liquid.rs
index 2400988..758ff0d 100644
--- a/src/block/liquid.rs
+++ b/src/block/liquid.rs
@@ -10,6 +10,7 @@ use crate::block::{
};
use crate::content;
use crate::data::dynamic::{DynData, DynType};
+use crate::data::renderer::load;
use crate::data::GridPos;
use crate::fluid;
use crate::item::storage::Storage;
@@ -102,6 +103,26 @@ impl BlockLogic for FluidBlock {
Some(fluid) => Ok(DynData::Content(content::Type::Fluid, (*fluid).into())),
}
}
+
+ fn draw(
+ &self,
+ category: &str,
+ name: &str,
+ state: Option<&dyn Any>,
+ ) -> Option<image::RgbaImage> {
+ let mut p = load(category, name).unwrap();
+ if let Some(state) = state {
+ if let Some(s) = Self::get_state(state) {
+ let mut top = load("distribution", "center").unwrap();
+ crate::utils::image::tint(&mut top, s.color());
+ image::imageops::overlay(&mut p, &top, 0, 0);
+ return Some(p);
+ }
+ }
+ let mut null = load("distribution", "cross-full").unwrap();
+ image::imageops::overlay(&mut null, &p, 0, 0);
+ Some(null)
+ }
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
diff --git a/src/block/logic.rs b/src/block/logic.rs
index 027302b..a56b564 100644
--- a/src/block/logic.rs
+++ b/src/block/logic.rs
@@ -20,6 +20,7 @@ use crate::item::storage::Storage;
make_register! {
// todo reinforced proc
+ "reinforced-message" => MessageLogic::new(1, true, cost!(Graphite: 10, Beryllium: 5));
"message" => MessageLogic::new(1, true, cost!(Copper: 5, Graphite: 5));
"switch" => SwitchLogic::new(1, true, cost!(Copper: 5, Graphite: 5));
"micro-processor" => ProcessorLogic::new(1, true, cost!(Copper: 90, Lead: 50, Silicon: 50));
diff --git a/src/block/mod.rs b/src/block/mod.rs
index 70fd498..47501cc 100644
--- a/src/block/mod.rs
+++ b/src/block/mod.rs
@@ -1,6 +1,7 @@
//! deal with blocks.
//!
//! categorized as mindustry categorizes them in its assets folder, for easy drawing
+//! with the exception of sandbox.
use image::RgbaImage;
use std::any::Any;
use std::borrow::Cow;
@@ -13,7 +14,7 @@ use crate::data::GridPos;
use crate::item::storage::Storage as ItemStorage;
use crate::registry::RegistryEntry;
-pub mod base;
+pub mod campaign;
pub mod content;
pub mod defense;
pub mod distribution;
@@ -26,6 +27,7 @@ pub mod production;
pub mod simple;
pub mod storage;
pub mod turrets;
+pub mod walls;
pub trait BlockLogic {
/// mindustry blocks are the same width and height
@@ -80,11 +82,11 @@ pub(crate) use impl_block;
#[derive(Debug)]
pub enum DataConvertError {
- Custom(Box<dyn Error>),
+ Custom(Box<dyn Error + Sync + Send>),
}
impl DataConvertError {
- pub fn forward<T, E: Error + 'static>(result: Result<T, E>) -> Result<T, Self> {
+ 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))),
@@ -111,11 +113,11 @@ impl Error for DataConvertError {
#[derive(Debug)]
pub enum DeserializeError {
InvalidType { have: DynType, expect: DynType },
- Custom(Box<dyn Error>),
+ Custom(Box<dyn Error + Sync + Send>),
}
impl DeserializeError {
- pub fn forward<T, E: Error + 'static>(result: Result<T, E>) -> Result<T, Self> {
+ 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))),
@@ -145,11 +147,11 @@ impl Error for DeserializeError {
#[derive(Debug)]
pub enum SerializeError {
- Custom(Box<dyn Error>),
+ Custom(Box<dyn Error + Sync + Send>),
}
impl SerializeError {
- pub fn forward<T, E: Error + 'static>(result: Result<T, E>) -> Result<T, Self> {
+ 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))),
@@ -449,6 +451,7 @@ fn register(reg: &mut BlockRegistry<'_>) {
defense::register(reg);
production::register(reg);
payload::register(reg);
- base::register(reg);
+ campaign::register(reg);
logic::register(reg);
+ walls::register(reg);
}
diff --git a/src/block/power.rs b/src/block/power.rs
index 9e0e69b..397cb62 100644
--- a/src/block/power.rs
+++ b/src/block/power.rs
@@ -12,6 +12,8 @@ use crate::data::GridPos;
use crate::item::storage::Storage;
make_register! {
+ // illuminator == power ?????
+ "illuminator" => LampBlock::new(1, true, cost!(Lead: 8, Graphite: 12, Silicon: 8));
"power-node" => ConnectorBlock::new(1, true, cost!(Copper: 1, Lead: 3), 10);
"power-node-large" => ConnectorBlock::new(2, true, cost!(Lead: 10, Titanium: 5, Silicon: 3), 15);
"surge-tower" => ConnectorBlock::new(2, true, cost!(Lead: 10, Titanium: 7, Silicon: 15, SurgeAlloy: 15), 2);
@@ -143,3 +145,78 @@ impl fmt::Display for ConnectorDeserializeError {
}
impl Error for ConnectorDeserializeError {}
+
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+pub struct RGBA(u8, u8, u8, u8);
+
+impl From<u32> for RGBA {
+ fn from(value: u32) -> Self {
+ Self(
+ (value >> 24) as u8,
+ (value >> 16) as u8,
+ (value >> 8) as u8,
+ value as u8,
+ )
+ }
+}
+
+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)
+ | u32::from(value.3)
+ }
+}
+
+pub struct LampBlock {
+ size: u8,
+ symmetric: bool,
+ build_cost: BuildCost,
+}
+
+impl LampBlock {
+ #[must_use]
+ pub const fn new(size: u8, symmetric: bool, build_cost: BuildCost) -> Self {
+ assert!(size != 0, "invalid size");
+ Self {
+ size,
+ symmetric,
+ build_cost,
+ }
+ }
+
+ state_impl!(pub RGBA);
+}
+
+impl BlockLogic for LampBlock {
+ impl_block!();
+
+ fn data_from_i32(&self, config: i32, _: GridPos) -> Result<DynData, DataConvertError> {
+ Ok(DynData::Int(config))
+ }
+
+ fn deserialize_state(&self, data: DynData) -> Result<Option<Box<dyn Any>>, DeserializeError> {
+ match data {
+ DynData::Int(rgba) => Ok(Some(Self::create_state(RGBA::from(rgba as u32)))),
+ _ => 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> {
+ let state = Self::get_state(state);
+ Ok(DynData::Int(u32::from(*state) as i32))
+ }
+}
diff --git a/src/block/production.rs b/src/block/production.rs
index 65dc9f9..ab91605 100644
--- a/src/block/production.rs
+++ b/src/block/production.rs
@@ -23,7 +23,7 @@ make_register! {
"incinerator" => SimpleBlock::new(1, true, cost!(Lead: 15, Graphite: 5));
"silicon-arc-furnace" => SimpleBlock::new(3, true, cost!(Beryllium: 70, Graphite: 80));
"electrolyzer" => SimpleBlock::new(3, true, cost!(Silicon: 50, Graphite: 40, Beryllium: 130, Tungsten: 80));
- "atmospheric-condenser" => SimpleBlock::new(3, true, cost!(Oxide: 60, Beryllium: 180, Silicon: 150));
+ "atmospheric-concentrator" => SimpleBlock::new(3, true, cost!(Oxide: 60, Beryllium: 180, Silicon: 150));
"oxidation-chamber" => SimpleBlock::new(3, true, cost!(Tungsten: 120, Graphite: 80, Silicon: 100, Beryllium: 120));
"electric-heater" => SimpleBlock::new(2, false, cost!(Tungsten: 30, Oxide: 30));
"slag-heater" => SimpleBlock::new(3, false, cost!(Tungsten: 50, Oxide: 20, Beryllium: 20));
diff --git a/src/block/storage.rs b/src/block/storage.rs
index 0e34e34..db93403 100644
--- a/src/block/storage.rs
+++ b/src/block/storage.rs
@@ -13,6 +13,6 @@ make_register! {
"container" => SimpleBlock::new(2, true, cost!(Titanium: 100));
"vault" => SimpleBlock::new(3, true, cost!(Titanium: 250, Thorium: 125));
"unloader" => ItemBlock::new(1, true, cost!(Titanium: 25, Silicon: 30));
- "reinforced-container" => SimpleBlock::new(2, true, cost!(Tungsten: 30, Graphite: 40));
- "reinforced-vault" => SimpleBlock::new(3, true, cost!(Tungsten: 125, Thorium: 70, Beryllium: 100));
+ "reinforced-container" => SimpleBlock::new(2, true, cost!(Tungsten: 30, Graphite: 40));
+ "reinforced-vault" => SimpleBlock::new(3, true, cost!(Tungsten: 125, Thorium: 70, Beryllium: 100));
}
diff --git a/src/block/walls.rs b/src/block/walls.rs
new file mode 100644
index 0000000..2cf3bbc
--- /dev/null
+++ b/src/block/walls.rs
@@ -0,0 +1,93 @@
+//! walls
+use std::any::Any;
+
+use crate::block::simple::{cost, state_impl, BuildCost, SimpleBlock};
+use crate::block::{
+ impl_block, make_register, BlockLogic, DataConvertError, DeserializeError, SerializeError,
+};
+use crate::data::dynamic::{DynData, DynType};
+use crate::data::GridPos;
+use crate::item::storage::Storage;
+
+make_register! {
+ "copper-wall" => SimpleBlock::new(1, true, cost!(Copper: 6));
+ "copper-wall-large" => SimpleBlock::new(2, true, cost!(Copper: 6 * 4));
+ "titanium-wall" => SimpleBlock::new(1, true, cost!(Titanium: 6));
+ "titanium-wall-large" => SimpleBlock::new(2, true, cost!(Titanium: 6 * 4));
+ "plastanium-wall" => SimpleBlock::new(1, true, cost!(Metaglass: 2, Plastanium: 5));
+ "plastanium-wall-large" => SimpleBlock::new(2, true, cost!(Metaglass: 2 * 4, Plastanium: 5 * 4));
+ "thorium-wall" => SimpleBlock::new(1, true, cost!(Thorium: 6));
+ "thorium-wall-large" => SimpleBlock::new(2, true, cost!(Thorium: 6 * 4));
+ "phase-wall" => SimpleBlock::new(1, true, cost!(PhaseFabric: 6));
+ "phase-wall-large" => SimpleBlock::new(2, true, cost!(PhaseFabric: 6 * 4));
+ "surge-wall" => SimpleBlock::new(1, true, cost!(SurgeAlloy: 6));
+ "surge-wall-large" => SimpleBlock::new(2, true, cost!(SurgeAlloy: 6 * 4));
+ "door" => DoorBlock::new(1, true, cost!(Titanium: 6, Silicon: 4));
+ "door-large" => DoorBlock::new(2, true, cost!(Titanium: 6 * 4, Silicon: 4 * 4));
+ "tungsten-wall" => SimpleBlock::new(1, true, cost!(Tungsten: 6));
+ "large-tungsten-wall" => SimpleBlock::new(2, true, cost!(Tungsten: 6 * 4));
+ "blast-door" => DoorBlock::new(2, true, cost!(Tungsten: 24, Silicon: 24));
+ "reinforced-surge-wall" => SimpleBlock::new(1, true, cost!(SurgeAlloy: 6, Tungsten: 2));
+ "reinforced-surge-wall-large" => SimpleBlock::new(2, true, cost!(SurgeAlloy: 6 * 4, Tungsten: 2 * 4));
+ "carbide-wall" => SimpleBlock::new(1, true, cost!(Thorium: 6, Carbide: 6));
+ "carbide-wall-large" => SimpleBlock::new(2, true, cost!(Thorium: 6 * 4, Carbide: 6 * 4));
+ "shielded-wall" => SimpleBlock::new(2, true, cost!(PhaseFabric: 20, SurgeAlloy: 12, Beryllium: 12));
+ // sandbox only
+ "scrap-wall" => SimpleBlock::new(1, true, cost!(Scrap: 6));
+ "scrap-wall-large" => SimpleBlock::new(2, true, cost!(Scrap: 24));
+ "scrap-wall-huge" => SimpleBlock::new(3, true, cost!(Scrap: 54));
+ "scrap-wall-gigantic" => SimpleBlock::new(4, true, cost!(Scrap: 96));
+ "thruster" => SimpleBlock::new(4, false, cost!(Scrap: 96));
+}
+
+pub struct DoorBlock {
+ size: u8,
+ symmetric: bool,
+ build_cost: BuildCost,
+}
+
+impl DoorBlock {
+ #[must_use]
+ pub const fn new(size: u8, symmetric: bool, build_cost: BuildCost) -> Self {
+ assert!(size != 0, "invalid size");
+ Self {
+ size,
+ symmetric,
+ build_cost,
+ }
+ }
+
+ state_impl!(pub bool);
+}
+
+impl BlockLogic for DoorBlock {
+ impl_block!();
+
+ fn data_from_i32(&self, _: i32, _: GridPos) -> Result<DynData, DataConvertError> {
+ Ok(DynData::Boolean(false))
+ }
+
+ fn deserialize_state(&self, data: DynData) -> Result<Option<Box<dyn Any>>, DeserializeError> {
+ match data {
+ DynData::Boolean(opened) => Ok(Some(Self::create_state(opened))),
+ _ => Err(DeserializeError::InvalidType {
+ have: data.get_type(),
+ expect: DynType::Boolean,
+ }),
+ }
+ }
+
+ 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> {
+ let state = Self::get_state(state);
+ Ok(DynData::Boolean(*state))
+ }
+}
diff --git a/src/content.rs b/src/content.rs
index 51025fb..5576458 100644
--- a/src/content.rs
+++ b/src/content.rs
@@ -86,6 +86,27 @@ macro_rules! content_enum {
}
pub(crate) use content_enum;
+macro_rules! color_content_enum {
+ ($vis:vis enum $tname:ident / $ctype:ident for u16 | $error:ident {$($val:literal: $col:literal),* $(,)?}) =>
+ {
+ paste::paste! {
+ $crate::content::content_enum!($vis enum $tname / $ctype for u16 | $error {
+ $($val),*,
+ });
+
+ impl Type {
+ pub fn color(&self) -> image::Rgb<u8> {
+ match &self {
+ $(Self::[<$val:camel>] => {
+ image::Rgb(color_hex::color_from_hex!($col))
+ },)*
+ }
+ }
+ }
+ }}
+}
+pub(crate) use color_content_enum;
+
numeric_enum! {
pub enum Type for u8 | TryFromU8Error
{
diff --git a/src/data/renderer.rs b/src/data/renderer.rs
index fdd169d..1f0e4d8 100644
--- a/src/data/renderer.rs
+++ b/src/data/renderer.rs
@@ -10,9 +10,13 @@ use zip::ZipArchive;
use super::schematic::Schematic;
pub(crate) fn load(category: &str, name: &str) -> Option<RgbaImage> {
- let mut p = Path::new("target/out/blocks").join(category).join(name);
+ let mut p = Path::new("blocks").join(category).join(name);
p.set_extension("png");
- let f = std::fs::File::open(p).ok()?;
+ load_raw(p)
+}
+
+pub(crate) fn load_raw(f: impl AsRef<Path>) -> Option<RgbaImage> {
+ let f = std::fs::File::open(Path::new("target/out").join(f)).ok()?;
let r = PngDecoder::new(BufReader::new(f)).unwrap();
Some(DynamicImage::from_decoder(r).unwrap().into_rgba8())
}
@@ -27,8 +31,8 @@ fn load_zip() {
}
}
-const SUFFIXES: &[&str; 8] = &[
- "bottom", "mid", "", "-base", "-left", "-right", "-top", "-over",
+const SUFFIXES: &[&str; 10] = &[
+ "-bottom", "-mid", "", "-base", "-left", "-right", "-rotator", "-weave", "-top", "-over",
];
pub(crate) fn read<S>(category: &str, name: &str, size: S) -> RgbaImage
where
@@ -46,26 +50,23 @@ where
/// renderer for creating images of schematics
pub struct Renderer {}
impl<'l> Renderer {
- /// creates a picture of a schematic. Bridges and nodes are not drawn, and there is no background.
+ /// creates a picture of a schematic. Bridges and node connections are not drawn, and there is no background.
/// conveyors, conduits, and ducts currently do not render.
/// ```
/// use mindus::*;
- /// let s = Schematic::new(2, 3);
- /// s.put(0, 0, blocks::distribution::DISTRIBUTOR);
- /// s.put(0, 3, blocks::distrubution::ROUTER);
- /// s.put(1, 3, blocks::defense::COPPER_WALL);
+ /// let mut s = Schematic::new(2, 3);
+ /// s.put(0, 0, &block::distribution::DISTRIBUTOR);
+ /// s.put(0, 3, &block::distribution::ROUTER);
+ /// s.put(1, 3, &block::walls::COPPER_WALL);
/// let output /*: RgbaImage */ = Renderer::render(&s);
/// ```
pub fn render(s: &'l Schematic<'_>) -> RgbaImage {
load_zip();
let mut canvas = RgbaImage::new((s.width * 32).into(), (s.height * 32).into());
for tile in s.block_iter() {
- let mut x = tile.pos.0 as i64;
- let mut y = tile.pos.1 as i64;
- if tile.block.get_size() != 1 && tile.block.get_size() % 2 != 0 {
- x -= 1;
- y -= 1;
- }
+ let sub = ((tile.block.get_size() - 1) / 2) as u16;
+ let x = (tile.pos.0 - sub) as i64;
+ let y = (tile.pos.1 - sub) as i64;
overlay(&mut canvas, &tile.image(), x * 32, y * 32);
}
canvas
diff --git a/src/fluid/mod.rs b/src/fluid/mod.rs
index f4d9395..45254b9 100644
--- a/src/fluid/mod.rs
+++ b/src/fluid/mod.rs
@@ -1,18 +1,18 @@
-use crate::content::content_enum;
+use crate::content::color_content_enum;
-content_enum! {
+color_content_enum! {
pub enum Type / Fluid for u16 | TryFromU16Error
{
- "water",
- "slag",
- "oil",
- "cryofluid",
- "neoplasm",
- "arkycite",
- "gallium",
- "ozone",
- "hydrogen",
- "nitrogen",
- "cyanogen",
+ "water": "596ab8",
+ "slag": "ffa166",
+ "oil": "313131",
+ "cryofluid": "6ecdec",
+ "neoplasm": "c33e2b",
+ "arkycite": "84a94b",
+ "gallium": "9a9dbf",
+ "ozone": "fc81dd",
+ "hydrogen": "9eabf7",
+ "nitrogen": "efe3ff",
+ "cyanogen": "89e8b6",
}
}
diff --git a/src/item/mod.rs b/src/item/mod.rs
index 6a4f8fc..863d3b0 100644
--- a/src/item/mod.rs
+++ b/src/item/mod.rs
@@ -1,49 +1,29 @@
//! the different kinds of items
-use image::Rgb;
-
pub mod storage;
-
-macro_rules! item_enum {
- ($($val:literal: $col:literal),* $(,)?) =>
- {
- paste::paste! {
- $crate::content::content_enum!(pub enum Type / Item for u16 | TryFromU16Error {
- $($val),*,
- });
-
- impl Type {
- pub fn color(&self) -> Rgb<u8> {
- match &self {
- $(Self::[<$val:camel>] => {
- Rgb(color_hex::color_from_hex!($col))
- },)*
- }
- }
- }
- }}
-}
-
-item_enum! {
- "copper": "d99d73",
- "lead": "8c7fa9",
- "metaglass": "ebeef5",
- "graphite": "b2c6d2",
- "sand": "f7cba4",
- "coal": "272727",
- "titanium": "8da1e3",
- "thorium": "f9a3c7",
- "scrap": "777777",
- "silicon": "53565c",
- "plastanium": "cbd97f",
- "phase-fabric": "f4ba6e",
- "surge-alloy": "f3e979",
- "spore-pod": "7457ce",
- "blast-compound": "ff795e",
- "pyratite": "ffaa5f",
- "beryllium": "3a8f64",
- "tungsten": "768a9a",
- "oxide": "e4ffd6",
- "carbide": "89769a",
- "fissile-matter": "5e988d",
- "dormant-cyst": "df824d",
+use crate::content::color_content_enum;
+color_content_enum! {
+ pub enum Type / Item for u16 | TryFromU16Error {
+ "copper": "d99d73",
+ "lead": "8c7fa9",
+ "metaglass": "ebeef5",
+ "graphite": "b2c6d2",
+ "sand": "f7cba4",
+ "coal": "272727",
+ "titanium": "8da1e3",
+ "thorium": "f9a3c7",
+ "scrap": "777777",
+ "silicon": "53565c",
+ "plastanium": "cbd97f",
+ "phase-fabric": "f4ba6e",
+ "surge-alloy": "f3e979",
+ "spore-pod": "7457ce",
+ "blast-compound": "ff795e",
+ "pyratite": "ffaa5f",
+ "beryllium": "3a8f64",
+ "tungsten": "768a9a",
+ "oxide": "e4ffd6",
+ "carbide": "89769a",
+ "fissile-matter": "5e988d",
+ "dormant-cyst": "df824d",
+ }
}
diff --git a/src/lib.rs b/src/lib.rs
index 64bdae6..31462f8 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -10,6 +10,7 @@ mod modifier;
mod registry;
mod team;
mod unit;
+mod utils;
pub use block::build_registry;
pub use data::dynamic::DynData;
pub use data::renderer::Renderer;
diff --git a/src/utils/image.rs b/src/utils/image.rs
new file mode 100644
index 0000000..50a4cf7
--- /dev/null
+++ b/src/utils/image.rs
@@ -0,0 +1,14 @@
+use image::{Rgb, Rgba, RgbaImage};
+
+pub fn tint(image: &mut RgbaImage, color: Rgb<u8>) {
+ let [tr, tg, tb] = [
+ color[0] as f32 / 255.0,
+ color[1] as f32 / 255.0,
+ color[2] as f32 / 255.0,
+ ];
+ for Rgba([r, g, b, _]) in image.pixels_mut() {
+ *r = (*r as f32 * tr) as u8;
+ *g = (*g as f32 * tg) as u8;
+ *b = (*b as f32 * tb) as u8;
+ }
+}
diff --git a/src/utils/mod.rs b/src/utils/mod.rs
new file mode 100644
index 0000000..14995d4
--- /dev/null
+++ b/src/utils/mod.rs
@@ -0,0 +1 @@
+pub mod image;