mindustry logic execution, map- and schematic- parsing and rendering
| -rw-r--r-- | Cargo.toml | 3 | ||||
| -rw-r--r-- | assets/blocks/environment/empty.png | bin | 81 -> 0 bytes | |||
| -rw-r--r-- | assets/blocks/liquid/conduits/conduit-0.png (renamed from assets/blocks/liquid/conduits/conduit-top-0.png) | bin | 185 -> 185 bytes | |||
| -rw-r--r-- | assets/blocks/liquid/conduits/conduit-1.png (renamed from assets/blocks/liquid/conduits/conduit-top-1.png) | bin | 243 -> 243 bytes | |||
| -rw-r--r-- | assets/blocks/liquid/conduits/conduit-2.png (renamed from assets/blocks/liquid/conduits/conduit-top-2.png) | bin | 215 -> 215 bytes | |||
| -rw-r--r-- | assets/blocks/liquid/conduits/conduit-3.png (renamed from assets/blocks/liquid/conduits/conduit-top-3.png) | bin | 219 -> 219 bytes | |||
| -rw-r--r-- | assets/blocks/liquid/conduits/conduit-4.png (renamed from assets/blocks/liquid/conduits/conduit-top-4.png) | bin | 202 -> 202 bytes | |||
| -rw-r--r-- | assets/blocks/liquid/conduits/plated-conduit-0.png (renamed from assets/blocks/liquid/conduits/plated-conduit-top-0.png) | bin | 210 -> 210 bytes | |||
| -rw-r--r-- | assets/blocks/liquid/conduits/plated-conduit-1.png (renamed from assets/blocks/liquid/conduits/plated-conduit-top-1.png) | bin | 272 -> 272 bytes | |||
| -rw-r--r-- | assets/blocks/liquid/conduits/plated-conduit-2.png (renamed from assets/blocks/liquid/conduits/plated-conduit-top-2.png) | bin | 227 -> 227 bytes | |||
| -rw-r--r-- | assets/blocks/liquid/conduits/plated-conduit-3.png (renamed from assets/blocks/liquid/conduits/plated-conduit-top-3.png) | bin | 215 -> 215 bytes | |||
| -rw-r--r-- | assets/blocks/liquid/conduits/plated-conduit-4.png (renamed from assets/blocks/liquid/conduits/plated-conduit-top-4.png) | bin | 228 -> 228 bytes | |||
| -rw-r--r-- | assets/blocks/liquid/conduits/pulse-conduit-0.png (renamed from assets/blocks/liquid/conduits/pulse-conduit-top-0.png) | bin | 223 -> 223 bytes | |||
| -rw-r--r-- | assets/blocks/liquid/conduits/pulse-conduit-1.png (renamed from assets/blocks/liquid/conduits/pulse-conduit-top-1.png) | bin | 297 -> 297 bytes | |||
| -rw-r--r-- | assets/blocks/liquid/conduits/pulse-conduit-2.png (renamed from assets/blocks/liquid/conduits/pulse-conduit-top-2.png) | bin | 253 -> 253 bytes | |||
| -rw-r--r-- | assets/blocks/liquid/conduits/pulse-conduit-3.png (renamed from assets/blocks/liquid/conduits/pulse-conduit-top-3.png) | bin | 263 -> 263 bytes | |||
| -rw-r--r-- | assets/blocks/liquid/conduits/pulse-conduit-4.png (renamed from assets/blocks/liquid/conduits/pulse-conduit-top-4.png) | bin | 235 -> 235 bytes | |||
| -rw-r--r-- | assets/blocks/liquid/conduits/reinforced-conduit-0.png (renamed from assets/blocks/liquid/conduits/reinforced-conduit-top-0.png) | bin | 219 -> 219 bytes | |||
| -rw-r--r-- | assets/blocks/liquid/conduits/reinforced-conduit-1.png (renamed from assets/blocks/liquid/conduits/reinforced-conduit-top-1.png) | bin | 257 -> 257 bytes | |||
| -rw-r--r-- | assets/blocks/liquid/conduits/reinforced-conduit-2.png (renamed from assets/blocks/liquid/conduits/reinforced-conduit-top-2.png) | bin | 219 -> 219 bytes | |||
| -rw-r--r-- | assets/blocks/liquid/conduits/reinforced-conduit-3.png (renamed from assets/blocks/liquid/conduits/reinforced-conduit-top-3.png) | bin | 198 -> 198 bytes | |||
| -rw-r--r-- | assets/blocks/liquid/conduits/reinforced-conduit-4.png (renamed from assets/blocks/liquid/conduits/reinforced-conduit-top-4.png) | bin | 244 -> 244 bytes | |||
| -rw-r--r-- | assets/blocks/production/heat-router-top1.png | bin | 0 -> 307 bytes | |||
| -rw-r--r-- | assets/blocks/production/heat-router-top2.png | bin | 0 -> 317 bytes | |||
| -rw-r--r-- | assets/blocks/production/heat-router.png | bin | 961 -> 959 bytes | |||
| -rw-r--r-- | build.rs | 55 | ||||
| -rw-r--r-- | src/block/campaign.rs | 4 | ||||
| -rw-r--r-- | src/block/defense.rs | 26 | ||||
| -rw-r--r-- | src/block/distribution.rs | 75 | ||||
| -rw-r--r-- | src/block/drills.rs | 34 | ||||
| -rw-r--r-- | src/block/environment.rs | 6 | ||||
| -rw-r--r-- | src/block/liquid.rs | 40 | ||||
| -rw-r--r-- | src/block/logic.rs | 49 | ||||
| -rw-r--r-- | src/block/mod.rs | 34 | ||||
| -rw-r--r-- | src/block/payload.rs | 94 | ||||
| -rw-r--r-- | src/block/power.rs | 83 | ||||
| -rw-r--r-- | src/block/production.rs | 89 | ||||
| -rw-r--r-- | src/block/simple.rs | 17 | ||||
| -rw-r--r-- | src/block/storage.rs | 22 | ||||
| -rw-r--r-- | src/block/turrets.rs | 20 | ||||
| -rw-r--r-- | src/block/units.rs | 134 | ||||
| -rw-r--r-- | src/block/walls.rs | 85 | ||||
| -rw-r--r-- | src/data/autotile.rs | 18 | ||||
| -rw-r--r-- | src/data/renderer.rs | 98 | ||||
| -rw-r--r-- | src/utils/image.rs | 4 |
45 files changed, 489 insertions, 501 deletions
@@ -1,6 +1,6 @@ [package] name = "mindus" -version = "2.0.0" +version = "2.0.1" edition = "2021" description = "A library for working with mindustry data formats (eg schematics and maps) (fork of plandustry)" authors = [ @@ -21,7 +21,6 @@ color-hex = "0.2" thiserror = "1.0" bobbin-bits = "0.1" blurslice = { version = "0.1" } -phf = { version = "0.11", features = ["macros"] } [features] bin = ["image/png"] diff --git a/assets/blocks/environment/empty.png b/assets/blocks/environment/empty.png Binary files differdeleted file mode 100644 index a994bf2..0000000 --- a/assets/blocks/environment/empty.png +++ /dev/null diff --git a/assets/blocks/liquid/conduits/conduit-top-0.png b/assets/blocks/liquid/conduits/conduit-0.png Binary files differindex 89e0a19..89e0a19 100644 --- a/assets/blocks/liquid/conduits/conduit-top-0.png +++ b/assets/blocks/liquid/conduits/conduit-0.png diff --git a/assets/blocks/liquid/conduits/conduit-top-1.png b/assets/blocks/liquid/conduits/conduit-1.png Binary files differindex dc86dd4..dc86dd4 100644 --- a/assets/blocks/liquid/conduits/conduit-top-1.png +++ b/assets/blocks/liquid/conduits/conduit-1.png diff --git a/assets/blocks/liquid/conduits/conduit-top-2.png b/assets/blocks/liquid/conduits/conduit-2.png Binary files differindex e8a7bb0..e8a7bb0 100644 --- a/assets/blocks/liquid/conduits/conduit-top-2.png +++ b/assets/blocks/liquid/conduits/conduit-2.png diff --git a/assets/blocks/liquid/conduits/conduit-top-3.png b/assets/blocks/liquid/conduits/conduit-3.png Binary files differindex 15b8dc2..15b8dc2 100644 --- a/assets/blocks/liquid/conduits/conduit-top-3.png +++ b/assets/blocks/liquid/conduits/conduit-3.png diff --git a/assets/blocks/liquid/conduits/conduit-top-4.png b/assets/blocks/liquid/conduits/conduit-4.png Binary files differindex 3d0f869..3d0f869 100644 --- a/assets/blocks/liquid/conduits/conduit-top-4.png +++ b/assets/blocks/liquid/conduits/conduit-4.png diff --git a/assets/blocks/liquid/conduits/plated-conduit-top-0.png b/assets/blocks/liquid/conduits/plated-conduit-0.png Binary files differindex 9b1dcd0..9b1dcd0 100644 --- a/assets/blocks/liquid/conduits/plated-conduit-top-0.png +++ b/assets/blocks/liquid/conduits/plated-conduit-0.png diff --git a/assets/blocks/liquid/conduits/plated-conduit-top-1.png b/assets/blocks/liquid/conduits/plated-conduit-1.png Binary files differindex 201ffa2..201ffa2 100644 --- a/assets/blocks/liquid/conduits/plated-conduit-top-1.png +++ b/assets/blocks/liquid/conduits/plated-conduit-1.png diff --git a/assets/blocks/liquid/conduits/plated-conduit-top-2.png b/assets/blocks/liquid/conduits/plated-conduit-2.png Binary files differindex 4a32d66..4a32d66 100644 --- a/assets/blocks/liquid/conduits/plated-conduit-top-2.png +++ b/assets/blocks/liquid/conduits/plated-conduit-2.png diff --git a/assets/blocks/liquid/conduits/plated-conduit-top-3.png b/assets/blocks/liquid/conduits/plated-conduit-3.png Binary files differindex ea24f9a..ea24f9a 100644 --- a/assets/blocks/liquid/conduits/plated-conduit-top-3.png +++ b/assets/blocks/liquid/conduits/plated-conduit-3.png diff --git a/assets/blocks/liquid/conduits/plated-conduit-top-4.png b/assets/blocks/liquid/conduits/plated-conduit-4.png Binary files differindex 5fd7ae2..5fd7ae2 100644 --- a/assets/blocks/liquid/conduits/plated-conduit-top-4.png +++ b/assets/blocks/liquid/conduits/plated-conduit-4.png diff --git a/assets/blocks/liquid/conduits/pulse-conduit-top-0.png b/assets/blocks/liquid/conduits/pulse-conduit-0.png Binary files differindex 09ee3e3..09ee3e3 100644 --- a/assets/blocks/liquid/conduits/pulse-conduit-top-0.png +++ b/assets/blocks/liquid/conduits/pulse-conduit-0.png diff --git a/assets/blocks/liquid/conduits/pulse-conduit-top-1.png b/assets/blocks/liquid/conduits/pulse-conduit-1.png Binary files differindex 170ffc9..170ffc9 100644 --- a/assets/blocks/liquid/conduits/pulse-conduit-top-1.png +++ b/assets/blocks/liquid/conduits/pulse-conduit-1.png diff --git a/assets/blocks/liquid/conduits/pulse-conduit-top-2.png b/assets/blocks/liquid/conduits/pulse-conduit-2.png Binary files differindex 35d1735..35d1735 100644 --- a/assets/blocks/liquid/conduits/pulse-conduit-top-2.png +++ b/assets/blocks/liquid/conduits/pulse-conduit-2.png diff --git a/assets/blocks/liquid/conduits/pulse-conduit-top-3.png b/assets/blocks/liquid/conduits/pulse-conduit-3.png Binary files differindex b7a411b..b7a411b 100644 --- a/assets/blocks/liquid/conduits/pulse-conduit-top-3.png +++ b/assets/blocks/liquid/conduits/pulse-conduit-3.png diff --git a/assets/blocks/liquid/conduits/pulse-conduit-top-4.png b/assets/blocks/liquid/conduits/pulse-conduit-4.png Binary files differindex 7958647..7958647 100644 --- a/assets/blocks/liquid/conduits/pulse-conduit-top-4.png +++ b/assets/blocks/liquid/conduits/pulse-conduit-4.png diff --git a/assets/blocks/liquid/conduits/reinforced-conduit-top-0.png b/assets/blocks/liquid/conduits/reinforced-conduit-0.png Binary files differindex 45bcdc2..45bcdc2 100644 --- a/assets/blocks/liquid/conduits/reinforced-conduit-top-0.png +++ b/assets/blocks/liquid/conduits/reinforced-conduit-0.png diff --git a/assets/blocks/liquid/conduits/reinforced-conduit-top-1.png b/assets/blocks/liquid/conduits/reinforced-conduit-1.png Binary files differindex e393c9c..e393c9c 100644 --- a/assets/blocks/liquid/conduits/reinforced-conduit-top-1.png +++ b/assets/blocks/liquid/conduits/reinforced-conduit-1.png diff --git a/assets/blocks/liquid/conduits/reinforced-conduit-top-2.png b/assets/blocks/liquid/conduits/reinforced-conduit-2.png Binary files differindex 5099798..5099798 100644 --- a/assets/blocks/liquid/conduits/reinforced-conduit-top-2.png +++ b/assets/blocks/liquid/conduits/reinforced-conduit-2.png diff --git a/assets/blocks/liquid/conduits/reinforced-conduit-top-3.png b/assets/blocks/liquid/conduits/reinforced-conduit-3.png Binary files differindex 297d720..297d720 100644 --- a/assets/blocks/liquid/conduits/reinforced-conduit-top-3.png +++ b/assets/blocks/liquid/conduits/reinforced-conduit-3.png diff --git a/assets/blocks/liquid/conduits/reinforced-conduit-top-4.png b/assets/blocks/liquid/conduits/reinforced-conduit-4.png Binary files differindex 46deb70..46deb70 100644 --- a/assets/blocks/liquid/conduits/reinforced-conduit-top-4.png +++ b/assets/blocks/liquid/conduits/reinforced-conduit-4.png diff --git a/assets/blocks/production/heat-router-top1.png b/assets/blocks/production/heat-router-top1.png Binary files differnew file mode 100644 index 0000000..75a62a4 --- /dev/null +++ b/assets/blocks/production/heat-router-top1.png diff --git a/assets/blocks/production/heat-router-top2.png b/assets/blocks/production/heat-router-top2.png Binary files differnew file mode 100644 index 0000000..c592618 --- /dev/null +++ b/assets/blocks/production/heat-router-top2.png diff --git a/assets/blocks/production/heat-router.png b/assets/blocks/production/heat-router.png Binary files differindex 7306dca..7f71e4d 100644 --- a/assets/blocks/production/heat-router.png +++ b/assets/blocks/production/heat-router.png @@ -7,6 +7,23 @@ use std::iter::Iterator; use std::path::Path; use walkdir::WalkDir; +macro_rules! wr { + ($dst:expr => $($arg:tt)*) => { writeln!($dst, $($arg)*).unwrap() }; +} + +fn kebab2bigsnek(kebab: &str) -> String { + let mut n = String::new(); + n.reserve(kebab.len()); + for c in kebab.chars() { + if c == '-' { + n.push('_'); + } else { + n.push(c.to_ascii_uppercase()); + } + } + n +} + fn main() { let _ = std::fs::remove_dir_all("target/out"); let walkdir = WalkDir::new("assets"); @@ -18,17 +35,30 @@ fn main() { // let mut half = File::create(o.join("half.rs")).unwrap(); let mut quar = File::create(o.join("quar.rs")).unwrap(); let mut eigh = File::create(o.join("eigh.rs")).unwrap(); - let mut n = 2usize; - for mut f in [&full, &eigh, &quar] { - f.write_all(b"phf::phf_map! {\n").unwrap(); + let mut n = 4usize; + + wr!(full => "pub mod full {{"); + wr!(full => "pub static EMPTY: LazyLock<RgbaImage> = LazyLock::new(|| RgbaImage::new(32, 32));"); + + wr!(quar => "pub mod quar {{"); + wr!(quar => "pub static EMPTY: LazyLock<RgbaImage> = LazyLock::new(|| RgbaImage::new(8, 8));"); + + wr!(eigh => "pub mod eigh {{"); + wr!(eigh => "pub static EMPTY: LazyLock<RgbaImage> = LazyLock::new(|| RgbaImage::new(4, 4));"); + + for mut file in [&full, &quar, &eigh] { + file.write_all(b"macro_rules!img{($v:expr)=>{{static TMP:LazyLock<RgbaImage>=LazyLock::new(||$v);&TMP}};}\n").unwrap(); + wr!(file => "use ::{{image::RgbaImage, std::sync::LazyLock}};"); } for i in 1..=16 { n += 1; - writeln!(full, r#" "build{}" => &EMPTY_FULL,"#, i).unwrap(); - writeln!(quar, r#" "build{}" => &EMPTY_QUAR,"#, i).unwrap(); - writeln!(eigh, r#" "build{}" => &EMPTY_EIGH,"#, i).unwrap(); + wr!(full => "pub static BUILD{}: &LazyLock<RgbaImage> = &EMPTY;", i); + wr!(quar => "pub static BUILD{}: &LazyLock<RgbaImage> = &EMPTY;", i); + wr!(eigh => "pub static BUILD{}: &LazyLock<RgbaImage> = &EMPTY;", i); } + let mut warmup = File::create(o.join("warmup.rs")).unwrap(); + wr!(warmup => "pub fn warmup() {{"); for e in walkdir.into_iter().filter_map(|e| e.ok()) { let path = e.path(); if path.is_file() && let Some(e) = path.extension() && e == "png" { @@ -38,7 +68,7 @@ fn main() { continue; } let path = path.with_extension(""); - let path = path.file_name().unwrap().to_str().unwrap(); + let path = kebab2bigsnek(path.file_name().unwrap().to_str().unwrap()); macro_rules! writ { ($ext:ident / $scale:literal) => { let mut buf = File::create(o.join(n.to_string() + "-" + stringify!($ext))).unwrap(); @@ -64,20 +94,25 @@ fn main() { let x = new.width(); let y = new.height(); buf.write_all(&new.into_raw()).unwrap(); - writeln!($ext, - r#" "{path}" => r!(unsafe {{ RgbaImage::from_vec({x}, {y}, include_bytes!(concat!(env!("OUT_DIR"), "/{n}-{}")).to_vec()).unwrap_unchecked() }}),"#, + wr!($ext => + r#"pub static {path}: &LazyLock<RgbaImage> = img!(unsafe {{ RgbaImage::from_vec({x}, {y}, include_bytes!(concat!(env!("OUT_DIR"), "/{n}-{}")).to_vec()).unwrap_unchecked() }});"#, stringify!($ext) - ).unwrap(); + ); }; } writ!(full / 1); // writ!(half + 0.5); writ!(quar / 4); writ!(eigh / 8); + wr!(warmup => "LazyLock::force({path});"); n += 1; } } + warmup.write_all(b"}").unwrap(); for mut f in [full, eigh, quar] { + // brazillian literal + f.write_all(br#"include!(concat!(env!("OUT_DIR"), "/warmup.rs"));"#) + .unwrap(); f.write_all(b"}").unwrap(); } } diff --git a/src/block/campaign.rs b/src/block/campaign.rs index 9869eeb..46ff605 100644 --- a/src/block/campaign.rs +++ b/src/block/campaign.rs @@ -3,6 +3,6 @@ use crate::block::make_register; use crate::block::simple::{cost, make_simple}; make_simple!(CampaignBlock); make_register! { - "launch-pad" => CampaignBlock::new(3, true, cost!(Copper: 350, Lead: 200, Titanium: 150, Silicon: 140)); - "interplanetary-accelerator" => CampaignBlock::new(7, true, cost!(Copper: 16000, Silicon: 11000, Thorium: 13000, Titanium: 12000, SurgeAlloy: 6000, PhaseFabric: 5000)); + "launch-pad" -> CampaignBlock::new(3, true, cost!(Copper: 350, Lead: 200, Titanium: 150, Silicon: 140)); + "interplanetary-accelerator" -> CampaignBlock::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 38a003f..73c290b 100644 --- a/src/block/defense.rs +++ b/src/block/defense.rs @@ -4,21 +4,21 @@ use crate::block::*; make_simple!(DefenseBlock); make_simple!(HeatedBlock => |_, _, _, buff: &mut DataRead| read_heated(buff)); make_register! { - "mender" => HeatedBlock::new(1, true, cost!(Copper: 25, Lead: 30)); - "mend-projector" => HeatedBlock::new(2, true, cost!(Copper: 50, Lead: 100, Titanium: 25, Silicon: 40)); - "overdrive-projector" => HeatedBlock::new(2, true, cost!(Lead: 100, Titanium: 75, Silicon: 75, Plastanium: 30)); - "overdrive-dome" => HeatedBlock::new(3, true, cost!(Lead: 200, Titanium: 130, Silicon: 130, Plastanium: 80, SurgeAlloy: 120)); - "force-projector" => DefenseBlock::new(3, true, cost!(Lead: 100, Titanium: 75, Silicon: 125)); - "regen-projector" => DefenseBlock::new(3, true, cost!(Silicon: 80, Tungsten: 60, Oxide: 40, Beryllium: 80)); - "shock-mine" => DefenseBlock::new(1, true, cost!(Lead: 25, Silicon: 12)); - "radar" => DefenseBlock::new(1, true, cost!(Silicon: 60, Graphite: 50, Beryllium: 10)); - "build-tower" => DefenseBlock::new(3, true, cost!(Silicon: 150, Oxide: 40, Thorium: 60)); - "shockwave-tower" => DefenseBlock::new(3, true, cost!(SurgeAlloy: 50, Silicon: 150, Oxide: 30, Tungsten: 100)); + "mender" -> HeatedBlock::new(1, true, cost!(Copper: 25, Lead: 30)); + "mend-projector" -> HeatedBlock::new(2, true, cost!(Copper: 50, Lead: 100, Titanium: 25, Silicon: 40)); + "overdrive-projector" -> HeatedBlock::new(2, true, cost!(Lead: 100, Titanium: 75, Silicon: 75, Plastanium: 30)); + "overdrive-dome" -> HeatedBlock::new(3, true, cost!(Lead: 200, Titanium: 130, Silicon: 130, Plastanium: 80, SurgeAlloy: 120)); + "force-projector" -> DefenseBlock::new(3, true, cost!(Lead: 100, Titanium: 75, Silicon: 125)); + "regen-projector" -> DefenseBlock::new(3, true, cost!(Silicon: 80, Tungsten: 60, Oxide: 40, Beryllium: 80)); + "shock-mine" -> DefenseBlock::new(1, true, cost!(Lead: 25, Silicon: 12)); + "radar" -> DefenseBlock::new(1, true, cost!(Silicon: 60, Graphite: 50, Beryllium: 10)); + "build-tower" -> DefenseBlock::new(3, true, cost!(Silicon: 150, Oxide: 40, Thorium: 60)); + "shockwave-tower" -> DefenseBlock::new(3, true, cost!(SurgeAlloy: 50, Silicon: 150, Oxide: 30, Tungsten: 100)); // barrier projector // editor only - "barrier-projector" => DefenseBlock::new(3, true, &[]); - "shield-projector" => DefenseBlock::new(3, true, &[]); - "large-shield-projector" => DefenseBlock::new(4, true, &[]); + "barrier-projector" -> DefenseBlock::new(3, true, &[]); + "shield-projector" -> DefenseBlock::new(3, true, &[]); + "large-shield-projector" -> DefenseBlock::new(4, true, &[]); } /// format: diff --git a/src/block/distribution.rs b/src/block/distribution.rs index c69a503..abf6433 100644 --- a/src/block/distribution.rs +++ b/src/block/distribution.rs @@ -39,8 +39,8 @@ make_simple!( make_simple!(JunctionBlock => |_, _, _, buff| { read_directional_item_buffer(buff) }); make_simple!(SimpleDuctBlock, |_, name, _, _, rot: Rotation, s| { - let mut base = load("duct-base", s); - let mut top = load(name, s); + let mut base = load!("duct-base", s); + let mut top = load!(from name which is ["overflow-duct" "underflow-duct"], s); top.rotate(rot.rotated(false).count()); base.overlay(&top); base @@ -56,7 +56,7 @@ fn draw_stack( ) -> ImageHolder { let ctx = ctx.unwrap(); let mask = mask(ctx, rot, name); - let edge = load(&format!("{name}-edge"), s); + let edge = load!(concat edge => name which is ["surge-conveyor" | "plastanium-conveyor"], s); let edgify = |skip, to: &mut RgbaImage| { for i in 0..4 { if i == skip { @@ -67,7 +67,11 @@ fn draw_stack( to.overlay(&edge); } }; - let gimme = |n: u8| load(&format!("{name}-{n}"), s); + let gimme = |n: u8| match n { + 0 => load!(concat 0 => name which is ["surge-conveyor" | "plastanium-conveyor"], s), + 1 => load!(concat 1 => name which is ["surge-conveyor" | "plastanium-conveyor"], s), + _ => load!("plastanium-conveyor-2", s), + }; let empty = ctx.cross[rot.count() as usize].map_or(true, |(v, _)| v.name != name); // mindustry says fuck this and just draws the arrow convs in schems but im better than that if rot.mirrored(true, true).mask() == mask && empty && name != "surge-conveyor" { @@ -115,8 +119,8 @@ make_simple!(ControlBlock); make_simple!( SurgeRouter / |s| { - let mut base = load("surge-router", s); - base.overlay(&load("top", s)); + let mut base = load!("surge-router", s); + base.overlay(&load!("top", s)); base } ); @@ -128,15 +132,15 @@ make_register! { "titanium-conveyor" => ConveyorBlock::new(1, false, cost!(Copper: 1, Lead: 1, Titanium: 1)); "plastanium-conveyor" => StackConveyor::new(1, false, cost!(Graphite: 1, Silicon: 1, Plastanium: 1)); "armored-conveyor" => ConveyorBlock::new(1, false, cost!(Metaglass: 1, Thorium: 1, Plastanium: 1)); - "junction" => JunctionBlock::new(1, true, cost!(Copper: 2)); - "bridge-conveyor" => BridgeBlock::new(1, false, cost!(Copper: 6, Lead: 6), 4, true); - "phase-conveyor" => BridgeBlock::new(1, false, cost!(Lead: 10, Graphite: 10, Silicon: 7, PhaseFabric: 5), 12, true); + "junction" -> JunctionBlock::new(1, true, cost!(Copper: 2)); + "bridge-conveyor" -> BridgeBlock::new(1, false, cost!(Copper: 6, Lead: 6), 4, true); + "phase-conveyor" -> BridgeBlock::new(1, false, cost!(Lead: 10, Graphite: 10, Silicon: 7, PhaseFabric: 5), 12, true); "sorter" => ItemBlock::new(1, true, cost!(Copper: 2, Lead: 2)); "inverted-sorter" => ItemBlock::new(1, true, cost!(Copper: 2, Lead: 2)); - "router" => ControlBlock::new(1, true, cost!(Copper: 3)); - "distributor" => ControlBlock::new(2, true, cost!(Copper: 4, Lead: 4)); - "overflow-gate" => ControlBlock::new(1, true, cost!(Copper: 4, Lead: 2)); - "underflow-gate" => ControlBlock::new(1, true, cost!(Copper: 4, Lead: 2)); + "router" -> ControlBlock::new(1, true, cost!(Copper: 3)); + "distributor" -> ControlBlock::new(2, true, cost!(Copper: 4, Lead: 4)); + "overflow-gate" -> ControlBlock::new(1, true, cost!(Copper: 4, Lead: 2)); + "underflow-gate" -> ControlBlock::new(1, true, cost!(Copper: 4, Lead: 2)); "mass-driver" => BridgeBlock::new(3, true, cost!(Lead: 125, Titanium: 125, Thorium: 50, Silicon: 75), 55, false); "duct" => DuctBlock::new(1, false, cost!(Beryllium: 1)); "armored-duct" => DuctBlock::new(1, false, cost!(Beryllium: 2, Tungsten: 1)); @@ -147,11 +151,11 @@ make_register! { "duct-unloader" => ItemBlock::new(1, true, cost!(Graphite: 20, Silicon: 20, Tungsten: 10)); "surge-conveyor" => StackConveyor::new(1, false, cost!(SurgeAlloy: 1, Tungsten: 1)); "surge-router" => SurgeRouter::new(1, false, cost!(SurgeAlloy: 5, Tungsten: 1)); // not symmetric - "unit-cargo-loader" => UnitCargoLoader::new(3, true, cost!(Silicon: 80, SurgeAlloy: 50, Oxide: 20)); + "unit-cargo-loader" -> UnitCargoLoader::new(3, true, cost!(Silicon: 80, SurgeAlloy: 50, Oxide: 20)); "unit-cargo-unload-point" => ItemBlock::new(2, true, cost!(Silicon: 60, Tungsten: 60)); // sandbox only - "item-source" => ItemBlock::new(1, true, &[]); - "item-void" => ControlBlock::new(1, true, &[]); + "item-source" -> ItemBlock::new(1, true, &[]); + "item-void" -> ControlBlock::new(1, true, &[]); } pub struct ItemBlock { @@ -224,17 +228,14 @@ impl BlockLogic for ItemBlock { rot: Rotation, s: Scale, ) -> ImageHolder { - let mut p = load(name, s); + let mut p = load!(from name which is ["sorter" | "inverted-sorter" | "duct-router" | "duct-unloader" | "unit-cargo-unload-point" | "unloader" | "item-source"], s); if let Some(state) = state { if let Some(item) = Self::get_state(state) { - let mut top = load( - match name { - "unit-cargo-unload-point" => "unit-cargo-unload-point-top", - "unloader" => "unloader-center", - _ => "center", - }, - s, - ); + let mut top = load!(s -> match name { + "unit-cargo-unload-point" => "unit-cargo-unload-point-top", + "unloader" => "unloader-center", + _ => "center", + }); p.overlay(top.tint(item.color())); return p; } @@ -243,20 +244,20 @@ impl BlockLogic for ItemBlock { return p; } if name == "duct-router" { - let mut arrow = load("top", s); + let mut arrow = load!("top", s); arrow.rotate(rot.rotated(false).count()); p.overlay(&arrow); p } else if name == "duct-unloader" { - let mut top = load("duct-unloader-top", s); + let mut top = load!("duct-unloader-top", s); top.rotate(rot.rotated(false).count()); p.overlay(&top); - let mut arrow = load("top", s); + let mut arrow = load!("top", s); arrow.rotate(rot.rotated(false).count()); p.overlay(&arrow); p } else { - let mut null = load("cross-full", s); + let mut null = load!("cross-full", s); null.overlay(&p); null } @@ -484,25 +485,25 @@ impl BlockLogic for BridgeBlock { ) -> ImageHolder { match name { "mass-driver" => { - let mut base = load("mass-driver-base", s); - base.overlay(&load("mass-driver", s)); + let mut base = load!("mass-driver-base", s); + base.overlay(&load!("mass-driver", s)); base } "duct-bridge" | "reinforced-bridge-conduit" => { - let mut base = load(name, s); - let mut arrow = load( - match name { + let mut base = + load!(from name which is ["duct-bridge" | "reinforced-bridge-conduit"], s); + let mut arrow = load!( + s -> match name { "duct-bridge" => "duct-bridge-dir", _ => "reinforced-bridge-conduit-dir", - }, - s, + } ); arrow.rotate(r.rotated(false).count()); base.overlay(&arrow); base } // "bridge-conveyor" | "phase-conveyor" | "bridge-conduit" | "phase-conduit" | "payload-mass-driver" | "large-payload-mass-driver" - _ => load(name, s), + _ => unreachable!(), } } } diff --git a/src/block/drills.rs b/src/block/drills.rs index a06c1e4..7d09941 100644 --- a/src/block/drills.rs +++ b/src/block/drills.rs @@ -6,32 +6,30 @@ use crate::block::*; make_simple!( DrillBlock, |_, name, _, _, rot: Rotation, s| { - if matches!(name, "large-plasma-bore" | "plasma-bore" | "cliff-crusher") { - let mut base = load(name, s); - let mut top = load(&format!("{name}-top"), s); - top.rotate(rot.rotated(false).count()); - base.overlay(&top); - return base; - } - load(name, 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); + return base; }, |_, _, _, buff: &mut DataRead| read_drill(buff) ); make_simple!(ExtractorBlock); make_register! { - "mechanical-drill" => DrillBlock::new(2, true, cost!(Copper: 12)); - "pneumatic-drill" => DrillBlock::new(2, true, cost!(Copper: 18, Graphite: 10)); - "laser-drill" => DrillBlock::new(3, true, cost!(Copper: 35, Graphite: 30, Titanium: 20, Silicon: 30)); - "blast-drill" => DrillBlock::new(4, true, cost!(Copper: 65, Titanium: 50, Thorium: 75, Silicon: 60)); - "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)); + "mechanical-drill" -> DrillBlock::new(2, true, cost!(Copper: 12)); + "pneumatic-drill" -> DrillBlock::new(2, true, cost!(Copper: 18, Graphite: 10)); + "laser-drill" -> DrillBlock::new(3, true, cost!(Copper: 35, Graphite: 30, Titanium: 20, Silicon: 30)); + "blast-drill" -> DrillBlock::new(4, true, cost!(Copper: 65, Titanium: 50, Thorium: 75, Silicon: 60)); + "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)); "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)); - "eruption-drill" => DrillBlock::new(5, true, cost!(Silicon: 200, Oxide: 20, Tungsten: 200, Thorium: 120)); + "impact-drill" -> DrillBlock::new(4, true, cost!(Silicon: 70, Beryllium: 90, Graphite: 60)); + "eruption-drill" -> DrillBlock::new(5, true, cost!(Silicon: 200, Oxide: 20, Tungsten: 200, Thorium: 120)); } /// format: diff --git a/src/block/environment.rs b/src/block/environment.rs index 7b0b250..efa7803 100644 --- a/src/block/environment.rs +++ b/src/block/environment.rs @@ -1,17 +1,16 @@ //! grass use crate::block::make_register; use crate::block::simple::make_simple; -use crate::data::renderer::*; macro_rules! register_env { ($($field:literal: $size:literal;)+) => { make_register!( - $($field => EnvironmentBlock::new($size, true, &[]);)* + $($field -> EnvironmentBlock::new($size, true, &[]);)* ); }; } -make_simple!(EnvironmentBlock, |_, name, _, _, _, s| load(name, s)); +make_simple!(EnvironmentBlock); register_env! { "darksand": 1; @@ -164,7 +163,6 @@ register_env! { "red-stone-boulder": 1; "rhyolite-boulder": 1; "sand-boulder": 1; - "yellow-sand-boulder": 1; "pur-bush": 1; "tendrils": 1; // these are tall but uh (TODO layering) diff --git a/src/block/liquid.rs b/src/block/liquid.rs index de2917b..3869971 100644 --- a/src/block/liquid.rs +++ b/src/block/liquid.rs @@ -17,7 +17,7 @@ make_simple!( let ctx = ctx.unwrap(); let mask = mask(ctx, rot, name); let (index, rot, flip) = mask2rotations(mask, rot); - let tile = rotations2tile((index, rot, flip), &format!("{name}-top"), s); + let tile = rotations2tile((index, rot, flip), "conduit", s); // TODO caps. stopped trying bcz too complex tile }, @@ -25,28 +25,28 @@ make_simple!( ); make_register! { - "reinforced-pump" => LiquidBlock::new(2, true, cost!(Beryllium: 40, Tungsten: 30, Silicon: 20)); - "mechanical-pump" => LiquidBlock::new(1, true, cost!(Copper: 15, Metaglass: 10)); - "rotary-pump" => LiquidBlock::new(2, true, cost!(Copper: 70, Metaglass: 50, Titanium: 35, Silicon: 20)); - "impulse-pump" => LiquidBlock::new(3, true, cost!(Copper: 80, Metaglass: 90, Titanium: 40, Thorium: 35, Silicon: 30)); + "reinforced-pump" -> LiquidBlock::new(2, true, cost!(Beryllium: 40, Tungsten: 30, Silicon: 20)); + "mechanical-pump" -> LiquidBlock::new(1, true, cost!(Copper: 15, Metaglass: 10)); + "rotary-pump" -> LiquidBlock::new(2, true, cost!(Copper: 70, Metaglass: 50, Titanium: 35, Silicon: 20)); + "impulse-pump" -> LiquidBlock::new(3, true, cost!(Copper: 80, Metaglass: 90, Titanium: 40, Thorium: 35, Silicon: 30)); "conduit" => ConduitBlock::new(1, false, cost!(Metaglass: 1)); "pulse-conduit" => ConduitBlock::new(1, false, cost!(Metaglass: 1, Titanium: 2)); "plated-conduit" => ConduitBlock::new(1, false, cost!(Metaglass: 1, Thorium: 2, Plastanium: 1)); - "liquid-router" => LiquidBlock::new(1, true, cost!(Metaglass: 2, Graphite: 4)); - "liquid-container" => LiquidBlock::new(2, true, cost!(Metaglass: 15, Titanium: 10)); - "liquid-tank" => LiquidBlock::new(3, true, cost!(Metaglass: 40, Titanium: 30)); - "liquid-junction" => LiquidBlock::new(1, true, cost!(Metaglass: 8, Graphite: 4)); - "bridge-conduit" => BridgeBlock::new(1, true, cost!(Metaglass: 8, Graphite: 4), 4, true); - "phase-conduit" => BridgeBlock::new(1, true, cost!(Metaglass: 20, Titanium: 10, Silicon: 7, PhaseFabric: 5), 12, true); + "liquid-router" -> LiquidBlock::new(1, true, cost!(Metaglass: 2, Graphite: 4)); + "liquid-container" -> LiquidBlock::new(2, true, cost!(Metaglass: 15, Titanium: 10)); + "liquid-tank" -> LiquidBlock::new(3, true, cost!(Metaglass: 40, Titanium: 30)); + "liquid-junction" -> LiquidBlock::new(1, true, cost!(Metaglass: 8, Graphite: 4)); + "bridge-conduit" -> BridgeBlock::new(1, true, cost!(Metaglass: 8, Graphite: 4), 4, true); + "phase-conduit" -> BridgeBlock::new(1, true, cost!(Metaglass: 20, Titanium: 10, Silicon: 7, PhaseFabric: 5), 12, true); "reinforced-conduit" => ConduitBlock::new(1, false, cost!(Beryllium: 2)); - "reinforced-liquid-junction" => LiquidBlock::new(1, true, cost!(Graphite: 4, Beryllium: 8)); + "reinforced-liquid-junction" -> LiquidBlock::new(1, true, cost!(Graphite: 4, Beryllium: 8)); "reinforced-bridge-conduit" => BridgeBlock::new(1, true, cost!(Graphite: 8, Beryllium: 20), 4, true); - "reinforced-liquid-router" => LiquidBlock::new(1, true, cost!(Graphite: 8, Beryllium: 4)); - "reinforced-liquid-container" => LiquidBlock::new(2, true, cost!(Tungsten: 10, Beryllium: 16)); - "reinforced-liquid-tank" => LiquidBlock::new(3, true, cost!(Tungsten: 40, Beryllium: 50)); + "reinforced-liquid-router" -> LiquidBlock::new(1, true, cost!(Graphite: 8, Beryllium: 4)); + "reinforced-liquid-container" -> LiquidBlock::new(2, true, cost!(Tungsten: 10, Beryllium: 16)); + "reinforced-liquid-tank" -> LiquidBlock::new(3, true, cost!(Tungsten: 40, Beryllium: 50)); // sandbox only "liquid-source" => FluidBlock::new(1, true, &[]); - "liquid-void" => LiquidBlock::new(1, true, &[]); + "liquid-void" -> LiquidBlock::new(1, true, &[]); } pub struct FluidBlock { @@ -111,21 +111,21 @@ impl BlockLogic for FluidBlock { fn draw( &self, - name: &str, + _: &str, state: Option<&State>, _: Option<&RenderingContext>, _: Rotation, s: Scale, ) -> ImageHolder { - let mut p = load(name, s); + let mut p = load!("liquid-source", s); if let Some(state) = state { if let Some(liq) = Self::get_state(state) { - let mut top = load("center", s); + let mut top = load!("center", s); p.overlay(top.tint(liq.color())); return p; } } - let mut null = load("cross-full", s); + let mut null = load!("cross-full", s); null.overlay(&p); null } diff --git a/src/block/logic.rs b/src/block/logic.rs index afaa947..0320fb6 100644 --- a/src/block/logic.rs +++ b/src/block/logic.rs @@ -23,21 +23,21 @@ make_simple!( ); make_register! { - "reinforced-message" => MessageLogic::new(1, true, cost!(Graphite: 10, Beryllium: 5)); - "message" => MessageLogic::new(1, true, cost!(Copper: 5, Graphite: 5)); + "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)); - "logic-processor" => ProcessorLogic::new(2, true, cost!(Lead: 320, Graphite: 60, Thorium: 50, Silicon: 80)); - "hyper-processor" => ProcessorLogic::new(3, true, cost!(Lead: 450, Thorium: 75, Silicon: 150, SurgeAlloy: 50)); - "memory-cell" => MemoryBlock::new(1, true, cost!(Copper: 30, Graphite: 30, Silicon: 30)); - "memory-bank" => MemoryBlock::new(2, true, cost!(Copper: 30, Graphite: 80, Silicon: 80, PhaseFabric: 30)); - "logic-display" => LogicBlock::new(3, true, cost!(Lead: 100, Metaglass: 50, Silicon: 50)); - "large-logic-display" => LogicBlock::new(6, true, cost!(Lead: 200, Metaglass: 100, Silicon: 150, PhaseFabric: 75)); + "micro-processor" -> ProcessorLogic::new(1, true, cost!(Copper: 90, Lead: 50, Silicon: 50)); + "logic-processor" -> ProcessorLogic::new(2, true, cost!(Lead: 320, Graphite: 60, Thorium: 50, Silicon: 80)); + "hyper-processor" -> ProcessorLogic::new(3, true, cost!(Lead: 450, Thorium: 75, Silicon: 150, SurgeAlloy: 50)); + "memory-cell" -> MemoryBlock::new(1, true, cost!(Copper: 30, Graphite: 30, Silicon: 30)); + "memory-bank" -> MemoryBlock::new(2, true, cost!(Copper: 30, Graphite: 80, Silicon: 80, PhaseFabric: 30)); + "logic-display" -> LogicBlock::new(3, true, cost!(Lead: 100, Metaglass: 50, Silicon: 50)); + "large-logic-display" -> LogicBlock::new(6, true, cost!(Lead: 200, Metaglass: 100, Silicon: 150, PhaseFabric: 75)); "canvas" => CanvasBlock::new(2, true, cost!(Silicon: 30, Beryllium: 10), 12); // editor only - "world-processor" => LogicBlock::new(1, true, &[]); - "world-message" => MessageLogic::new(1, true, &[]); - "world-cell" => MemoryBlock::new(1, true, &[]); + "world-processor" -> LogicBlock::new(1, true, &[]); + "world-message" -> MessageLogic::new(1, true, &[]); + "world-cell" -> MemoryBlock::new(1, true, &[]); } pub struct CanvasBlock { @@ -146,7 +146,7 @@ impl BlockLogic for CanvasBlock { /// i thought about drawing the borders and stuff but it felt like too much work fn draw( &self, - n: &str, + _: &str, state: Option<&State>, _: Option<&RenderingContext>, _: Rotation, @@ -171,7 +171,7 @@ impl BlockLogic for CanvasBlock { ) .into_rgba8() .scale((s * self.size as u32) - offset * 2); - let mut borders = load(n, s); + let mut borders = load!("canvas", s); borders.overlay_at(&p, offset, offset); return borders; } @@ -235,13 +235,13 @@ impl BlockLogic for MessageLogic { fn draw( &self, - name: &str, + _: &str, _: Option<&State>, _: Option<&RenderingContext>, _: Rotation, - s: Scale, + _: Scale, ) -> ImageHolder { - load(name, s) + unreachable!() } fn deserialize_state(&self, data: DynData) -> Result<Option<State>, DeserializeError> { @@ -344,10 +344,10 @@ impl BlockLogic for SwitchLogic { _: Rotation, s: Scale, ) -> ImageHolder { - let mut base = load("switch", s); + let mut base = load!("switch", s); if let Some(state) = state { if *Self::get_state(state) { - let on = load("switch-on", s); + let on = load!("switch-on", s); base.overlay(&on); return base; } @@ -408,17 +408,6 @@ fn read_decompressed(buff: &mut DataRead) -> Result<ProcessorState, ProcessorDes impl BlockLogic for ProcessorLogic { impl_block!(); - fn draw( - &self, - name: &str, - _: Option<&State>, - _: Option<&RenderingContext>, - _: Rotation, - s: Scale, - ) -> ImageHolder { - load(name, s) - } - fn data_from_i32(&self, _: i32, _: GridPos) -> Result<DynData, DataConvertError> { Ok(DynData::Empty) } diff --git a/src/block/mod.rs b/src/block/mod.rs index c1440c5..49d095d 100644 --- a/src/block/mod.rs +++ b/src/block/mod.rs @@ -8,6 +8,7 @@ use std::any::Any; use std::borrow::Cow; use std::error::Error; use std::fmt; +use std::sync::LazyLock; use crate::access::BoxAccess; use crate::data::dynamic::{DynData, DynType}; @@ -64,7 +65,9 @@ pub trait BlockLogic { context: Option<&RenderingContext>, rot: Rotation, scale: Scale, - ) -> ImageHolder; + ) -> ImageHolder { + unimplemented!("{name}") + } fn want_context(&self) -> bool { false @@ -161,6 +164,7 @@ impl SerializeError { /// a block. put it in stuff! pub struct Block { + image: Option<[&'static LazyLock<RgbaImage>; 3]>, name: Cow<'static, str>, pub(crate) logic: BoxAccess<'static, dyn BlockLogic + Sync>, } @@ -177,8 +181,9 @@ impl Block { pub const fn new( name: Cow<'static, str>, logic: BoxAccess<'static, dyn BlockLogic + Sync>, + image: Option<[&'static LazyLock<RgbaImage>; 3]>, ) -> Self { - Self { name, logic } + Self { name, logic, image } } /// this blocks name @@ -202,6 +207,11 @@ impl Block { rot: Rotation, scale: Scale, ) -> ImageHolder { + if let Some(imgs) = self.image { + return ImageHolder::from(LazyLock::force(unsafe { + imgs.get_unchecked(scale as usize) + })); + } self.logic .as_ref() .draw(&self.name, state, context, rot, scale) @@ -429,16 +439,26 @@ pub type BlockRegistry<'l> = crate::registry::Registry<'l, Block>; pub type RegisterError<'l> = crate::registry::RegisterError<'l, Block>; macro_rules! make_register { - ($($field:literal => $logic:expr;)+) => { paste::paste! { + ($($field:literal $op:tt $logic:expr;)+) => { paste::paste! { $( - pub static [<$field:snake:upper>]: $crate::block::Block = $crate::block::Block::new( - std::borrow::Cow::Borrowed($field), $crate::access::Access::Borrowed(&$logic)); - )+ + $crate::block::make_register!(impl $field $op $logic); + )+ pub(crate) fn register(reg: &mut $crate::block::BlockRegistry<'_>) { - $(assert!(reg.register(&[<$field:snake:upper>]).is_ok(), "duplicate block {:?}", $field);)+ + // 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( + std::borrow::Cow::Borrowed($field), $crate::access::Access::Borrowed(&$logic), None + ); } + }; + (impl $field: literal -> $logic: expr) => { + paste::paste! { pub static [<$field:snake:upper>]: $crate::block::Block = $crate::block::Block::new( + std::borrow::Cow::Borrowed($field), $crate::access::Access::Borrowed(&$logic), Some(crate::data::renderer::load!($field)) + ); } + } } pub(crate) use make_register; diff --git a/src/block/payload.rs b/src/block/payload.rs index e20aae9..070efe0 100644 --- a/src/block/payload.rs +++ b/src/block/payload.rs @@ -15,39 +15,32 @@ use super::BlockRegistry; make_simple!(SimplePayloadBlock, |_, n, _, _, r: Rotation, scl| { match n { "deconstructor" | "small-deconstructor" | "payload-void" => { - let mut base = load(n, scl); - let mut r#in = load( - match n { - "small-deconstructor" => "factory-in-3", - _ => "factory-in-5", - }, - scl, + let mut base = load!(from n which is ["deconstructor" | "small-deconstructor" | "payload-void"], scl); + let mut r#in = load!(scl -> match n { + "small-deconstructor" => "factory-in-3", + _ => "factory-in-5", + }); + base.overlay(r#in.rotate(r.rotated(false).count())).overlay( + load!(scl -> match n { + "small-deconstructor" => "small-deconstructor-top", + "deconstructor" => "deconstructor-top", + _ => "payload-void-top", + }) + .borrow(), ); - base.overlay(r#in.rotate(r.rotated(false).count())) - .overlay(&load( - match n { - "small-deconstructor" => "small-deconstructor-top", - "deconstructor" => "deconstructor-top", - _ => "payload-void-top", - }, - scl, - )); base } // "payload-loader" | "payload-unloader" _ => { - let mut base = load(n, scl); - let mut input = load("factory-in-3-dark", scl); - let mut output = load("factory-out-3-dark", scl); + let mut base = load!(from n which is ["payload-loader" | "payload-unloader"], scl); + let mut input = load!("factory-in-3-dark", scl); + let mut output = load!("factory-out-3-dark", scl); base.overlay(input.rotate(r.rotated(false).count())) .overlay(output.rotate(r.rotated(false).count())) - .overlay(&load( - match n { - "payload-loader" => "payload-loader-top", - _ => "payload-unloader-top", - }, - scl, - )); + .overlay( + load!(concat top => n which is ["payload-loader" | "payload-unloader"], scl) + .borrow(), + ); base } } @@ -55,7 +48,8 @@ make_simple!(SimplePayloadBlock, |_, n, _, _, r: Rotation, scl| { make_simple!( PayloadConveyor, |_, n, _, _, r: Rotation, s| { - let mut base = load(n, s); + let mut base = + load!(from n which is ["payload-conveyor" | "reinforced-payload-conveyor"], s); base.rotate(r.rotated(false).count()); base }, @@ -68,8 +62,8 @@ make_register! { "payload-router" => PayloadBlock::new(3, false, cost!(Copper: 10, Graphite: 15)); "reinforced-payload-conveyor" => PayloadConveyor::new(3, false, cost!(Tungsten: 10)); "reinforced-payload-router" => PayloadBlock::new(3, false, cost!(Tungsten: 15)); - "payload-mass-driver" => BridgeBlock::new(3, true, cost!(Tungsten: 120, Silicon: 120, Graphite: 50), 700, false); - "large-payload-mass-driver" => BridgeBlock::new(5, true, cost!(Thorium: 200, Tungsten: 200, Silicon: 200, Graphite: 100, Oxide: 30), 1100, false); + "payload-mass-driver" -> BridgeBlock::new(3, true, cost!(Tungsten: 120, Silicon: 120, Graphite: 50), 700, false); + "large-payload-mass-driver" -> BridgeBlock::new(5, true, cost!(Thorium: 200, Tungsten: 200, Silicon: 200, Graphite: 100, Oxide: 30), 1100, false); "small-deconstructor" => SimplePayloadBlock::new(3, true, cost!(Beryllium: 100, Silicon: 100, Oxide: 40, Graphite: 80)); "deconstructor" => SimplePayloadBlock::new(5, true, cost!(Beryllium: 250, Oxide: 100, Silicon: 250, Carbide: 250)); "constructor" => PayloadBlock::new(3, true, cost!(Silicon: 100, Beryllium: 150, Tungsten: 80)); @@ -123,41 +117,23 @@ impl BlockLogic for PayloadBlock { ) -> ImageHolder { match name { "payload-router" | "reinforced-payload-router" => { - let mut base = load(name, s); + let mut base = + load!(from name which is ["payload-router" | "reinforced-payload-router"], s); base.rotate(r.rotated(false).count()); - let over = load( - match name { - "payload-router" => "payload-router-over", - _ => "reinforced-payload-router-over", - }, - s, - ); + let over = load!(concat over => name which is ["payload-router" | "reinforced-payload-router"], s); base.overlay(&over); base } - // "constructor" | "large-constructor" | "payload-source" _ => { - let mut base = load(name, s); - let mut out = load( - match name { - "constructor" => "factory-out-3", - "large-constructor" => "factory-out-5-dark", - _ => "factory-out-5", - }, - s, - ); + let mut base = load!(from name which is ["constructor" | "large-constructor" | "payload-source"], s); + let mut out = load!(s -> match name { + "constructor" => "factory-out-3", + "large-constructor" => "factory-out-5-dark", + _ => "factory-out-5", + }); out.rotate(r.rotated(false).count()); base.overlay(&out); - - base.overlay(&load( - match name { - "constructor" => "constructor-top", - "large-constructor" => "large-constructor-top", - _ => "payload-source-top", - }, - s, - )); - + base.overlay(load!(concat top => name which is ["constructor" | "large-constructor" | "payload-source"], s).borrow()); base } } @@ -193,10 +169,6 @@ impl BlockLogic for PayloadBlock { Box::new(Self::create_state(*state)) } - fn mirror_state(&self, _: &mut State, _: bool, _: bool) {} - - fn rotate_state(&self, _: &mut State, _: bool) {} - fn serialize_state(&self, state: &State) -> Result<DynData, SerializeError> { match Self::get_state(state) { Payload::Empty => Ok(DynData::Empty), diff --git a/src/block/power.rs b/src/block/power.rs index 1d853e8..a46a0ab 100644 --- a/src/block/power.rs +++ b/src/block/power.rs @@ -11,19 +11,20 @@ make_simple!(ImpactReactorBlock => |_, _, _, buff: &mut DataRead| read_impact(bu make_simple!( Neoplasia, |_, _, _, _, rot: Rotation, scl| { - let mut base = load("neoplasia-reactor", scl); - base.overlay(load("neoplasia-reactor-top", scl).rotate(rot.rotated(false).count())); + let mut base = load!("neoplasia-reactor", scl); + // TODO 2 tops + base.overlay(load!("neoplasia-reactor-top", scl).rotate(rot.rotated(false).count())); base }, |_, _, _, buff: &mut DataRead| read_heater(buff) ); make_simple!(BatteryBlock); make_simple!(DiodeBlock, |_, _, _, _, rot: Rotation, s| { - let mut base = load("diode", s); + let mut base = load!("diode", s); if rot == Rotation::Right { return base; } - let mut top = load("diode-arrow", s); + let mut top = load!("diode-arrow", s); top.rotate(rot.rotated(false).count()); base.overlay(&top); base @@ -31,35 +32,35 @@ make_simple!(DiodeBlock, |_, _, _, _, rot: Rotation, s| { 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); + "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); "diode" => DiodeBlock::new(1, false, cost!(Metaglass: 10, Silicon: 10, Plastanium: 5)); - "battery" => BatteryBlock::new(1, true, cost!(Copper: 5, Lead: 20)); - "battery-large" => BatteryBlock::new(3, true, cost!(Lead: 50, Titanium: 20, Silicon: 30)); - "combustion-generator" => GeneratorBlock::new(1, true, cost!(Copper: 25, Lead: 15)); - "thermal-generator" => GeneratorBlock::new(2, true, cost!(Copper: 40, Lead: 50, Metaglass: 40, Graphite: 35, Silicon: 35)); - "steam-generator" => GeneratorBlock::new(2, true, cost!(Copper: 35, Lead: 40, Graphite: 25, Silicon: 30)); - "differential-generator" => GeneratorBlock::new(3, true, cost!(Copper: 70, Lead: 100, Metaglass: 50, Titanium: 50, Silicon: 65)); - "rtg-generator" => GeneratorBlock::new(2, true, cost!(Lead: 100, Thorium: 50, Silicon: 75, Plastanium: 75, PhaseFabric: 25)); - "solar-panel" => GeneratorBlock::new(1, true, cost!(Lead: 10, Silicon: 15)); - "solar-panel-large" => GeneratorBlock::new(3, true, cost!(Lead: 80, Silicon: 110, PhaseFabric: 15)); - "thorium-reactor" => NuclearGeneratorBlock::new(3, true, cost!(Lead: 300, Metaglass: 50, Graphite: 150, Thorium: 150, Silicon: 200)); - "impact-reactor" => ImpactReactorBlock::new(4, true, + "battery" -> BatteryBlock::new(1, true, cost!(Copper: 5, Lead: 20)); + "battery-large" -> BatteryBlock::new(3, true, cost!(Lead: 50, Titanium: 20, Silicon: 30)); + "combustion-generator" -> GeneratorBlock::new(1, true, cost!(Copper: 25, Lead: 15)); + "thermal-generator" -> GeneratorBlock::new(2, true, cost!(Copper: 40, Lead: 50, Metaglass: 40, Graphite: 35, Silicon: 35)); + "steam-generator" -> GeneratorBlock::new(2, true, cost!(Copper: 35, Lead: 40, Graphite: 25, Silicon: 30)); + "differential-generator" -> GeneratorBlock::new(3, true, cost!(Copper: 70, Lead: 100, Metaglass: 50, Titanium: 50, Silicon: 65)); + "rtg-generator" -> GeneratorBlock::new(2, true, cost!(Lead: 100, Thorium: 50, Silicon: 75, Plastanium: 75, PhaseFabric: 25)); + "solar-panel" -> GeneratorBlock::new(1, true, cost!(Lead: 10, Silicon: 15)); + "solar-panel-large" -> GeneratorBlock::new(3, true, cost!(Lead: 80, Silicon: 110, PhaseFabric: 15)); + "thorium-reactor" -> NuclearGeneratorBlock::new(3, true, cost!(Lead: 300, Metaglass: 50, Graphite: 150, Thorium: 150, Silicon: 200)); + "impact-reactor" -> ImpactReactorBlock::new(4, true, cost!(Lead: 500, Metaglass: 250, Graphite: 400, Thorium: 100, Silicon: 300, SurgeAlloy: 250)); - "beam-node" => ConnectorBlock::new(1, true, cost!(Beryllium: 8), 4); - "beam-tower" => ConnectorBlock::new(3, true, cost!(Beryllium: 30, Oxide: 10, Silicon: 10), 12); - "turbine-condenser" => GeneratorBlock::new(3, true, cost!(Beryllium: 60)); - "chemical-combustion-chamber" => GeneratorBlock::new(3, true, cost!(Graphite: 40, Tungsten: 40, Oxide: 40, Silicon: 30)); - "pyrolysis-generator" => GeneratorBlock::new(3, true, cost!(Graphite: 50, Carbide: 50, Oxide: 60, Silicon: 50)); - "flux-reactor" => GeneratorBlock::new(5, true, cost!(Graphite: 300, Carbide: 200, Oxide: 100, Silicon: 600, SurgeAlloy: 300)); + "beam-node" -> ConnectorBlock::new(1, true, cost!(Beryllium: 8), 4); + "beam-tower" -> ConnectorBlock::new(3, true, cost!(Beryllium: 30, Oxide: 10, Silicon: 10), 12); + "turbine-condenser" -> GeneratorBlock::new(3, true, cost!(Beryllium: 60)); + "chemical-combustion-chamber" -> GeneratorBlock::new(3, true, cost!(Graphite: 40, Tungsten: 40, Oxide: 40, Silicon: 30)); + "pyrolysis-generator" -> GeneratorBlock::new(3, true, cost!(Graphite: 50, Carbide: 50, Oxide: 60, Silicon: 50)); + "flux-reactor" -> GeneratorBlock::new(5, true, cost!(Graphite: 300, Carbide: 200, Oxide: 100, Silicon: 600, SurgeAlloy: 300)); "neoplasia-reactor" => Neoplasia::new(5, true, cost!(Tungsten: 1000, Carbide: 300, Oxide: 150, Silicon: 500, PhaseFabric: 300, SurgeAlloy: 200)); // editor only - "beam-link" => ConnectorBlock::new(3, true, &[], 12); + "beam-link" -> ConnectorBlock::new(3, true, &[], 12); // sandbox only - "power-source" => ConnectorBlock::new(1, true, &[], 100); - "power-void" => GeneratorBlock::new(1, true, &[]); + "power-source" -> ConnectorBlock::new(1, true, &[], 100); + "power-void" -> GeneratorBlock::new(1, true, &[]); } pub struct ConnectorBlock { @@ -137,17 +138,6 @@ impl BlockLogic for ConnectorBlock { fn serialize_state(&self, state: &State) -> Result<DynData, SerializeError> { Ok(DynData::Point2Array(Self::get_state(state).clone())) } - - fn draw( - &self, - name: &str, - _: Option<&State>, - _: Option<&RenderingContext>, - _: Rotation, - s: Scale, - ) -> ImageHolder { - load(name, s) - } } #[derive(Debug, Error)] @@ -225,26 +215,11 @@ impl BlockLogic for LampBlock { } } - fn draw( - &self, - name: &str, - _: Option<&State>, - _: Option<&RenderingContext>, - _: Rotation, - s: Scale, - ) -> ImageHolder { - load(name, s) - } - fn clone_state(&self, state: &State) -> State { let state = Self::get_state(state); Box::new(Self::create_state(*state)) } - fn mirror_state(&self, _: &mut State, _: bool, _: bool) {} - - fn rotate_state(&self, _: &mut State, _: bool) {} - fn serialize_state(&self, state: &State) -> 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 af4c547..8faf359 100644 --- a/src/block/production.rs +++ b/src/block/production.rs @@ -4,43 +4,43 @@ use crate::block::*; use crate::data::DataRead; make_register! { - "cultivator" => ProductionBlock::new(2, true, cost!(Copper: 25, Lead: 25, Silicon: 10)); - "graphite-press" => ProductionBlock::new(2, true, cost!(Copper: 75, Lead: 30)); - "multi-press" => ProductionBlock::new(3, true, cost!(Lead: 100, Graphite: 50, Titanium: 100, Silicon: 25)); - "silicon-smelter" => ProductionBlock::new(2, true, cost!(Copper: 30, Lead: 25)); - "silicon-crucible" => ProductionBlock::new(3, true, cost!(Metaglass: 80, Titanium: 120, Silicon: 60, Plastanium: 35)); - "kiln" => ProductionBlock::new(2, true, cost!(Copper: 60, Lead: 30, Graphite: 30)); - "plastanium-compressor" => ProductionBlock::new(2, true, cost!(Lead: 115, Graphite: 60, Titanium: 80, Silicon: 80)); - "phase-weaver" => ProductionBlock::new(2, true, cost!(Lead: 120, Thorium: 75, Silicon: 130)); - "surge-smelter" => ProductionBlock::new(3, true, cost!(Lead: 80, Thorium: 70, Silicon: 80)); - "cryofluid-mixer" => ProductionBlock::new(2, true, cost!(Lead: 65, Thorium: 60, Silicon: 40)); - "pyratite-mixer" => ProductionBlock::new(2, true, cost!(Copper: 50, Lead: 25)); - "blast-mixer" => ProductionBlock::new(2, true, cost!(Lead: 30, Thorium: 20)); - "melter" => ProductionBlock::new(1, true, cost!(Copper: 30, Lead: 35, Graphite: 45)); - "separator" => ProductionBlock::new(2, true, cost!(Copper: 30, Titanium: 25)); - "disassembler" => ProductionBlock::new(3, true, cost!(Titanium: 100, Thorium: 80, Silicon: 150, Plastanium: 40)); - "spore-press" => ProductionBlock::new(2, true, cost!(Lead: 35, Silicon: 30)); - "pulverizer" => ProductionBlock::new(1, true, cost!(Copper: 30, Lead: 25)); - "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)); + "cultivator" -> ProductionBlock::new(2, true, cost!(Copper: 25, Lead: 25, Silicon: 10)); + "graphite-press" -> ProductionBlock::new(2, true, cost!(Copper: 75, Lead: 30)); + "multi-press" -> ProductionBlock::new(3, true, cost!(Lead: 100, Graphite: 50, Titanium: 100, Silicon: 25)); + "silicon-smelter" -> ProductionBlock::new(2, true, cost!(Copper: 30, Lead: 25)); + "silicon-crucible" -> ProductionBlock::new(3, true, cost!(Metaglass: 80, Titanium: 120, Silicon: 60, Plastanium: 35)); + "kiln" -> ProductionBlock::new(2, true, cost!(Copper: 60, Lead: 30, Graphite: 30)); + "plastanium-compressor" -> ProductionBlock::new(2, true, cost!(Lead: 115, Graphite: 60, Titanium: 80, Silicon: 80)); + "phase-weaver" -> ProductionBlock::new(2, true, cost!(Lead: 120, Thorium: 75, Silicon: 130)); + "surge-smelter" -> ProductionBlock::new(3, true, cost!(Lead: 80, Thorium: 70, Silicon: 80)); + "cryofluid-mixer" -> ProductionBlock::new(2, true, cost!(Lead: 65, Thorium: 60, Silicon: 40)); + "pyratite-mixer" -> ProductionBlock::new(2, true, cost!(Copper: 50, Lead: 25)); + "blast-mixer" -> ProductionBlock::new(2, true, cost!(Lead: 30, Thorium: 20)); + "melter" -> ProductionBlock::new(1, true, cost!(Copper: 30, Lead: 35, Graphite: 45)); + "separator" -> ProductionBlock::new(2, true, cost!(Copper: 30, Titanium: 25)); + "disassembler" -> ProductionBlock::new(3, true, cost!(Titanium: 100, Thorium: 80, Silicon: 150, Plastanium: 40)); + "spore-press" -> ProductionBlock::new(2, true, cost!(Lead: 35, Silicon: 30)); + "pulverizer" -> ProductionBlock::new(1, true, cost!(Copper: 30, Lead: 25)); + "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)); - "atmospheric-concentrator" => ProductionBlock::new(3, true, cost!(Oxide: 60, Beryllium: 180, Silicon: 150)); + "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)); "slag-heater" => HeatCrafter::new(3, false, cost!(Tungsten: 50, Oxide: 20, Beryllium: 20)); "phase-heater" => HeatCrafter::new(2, false, cost!(Oxide: 30, Carbide: 30, Beryllium: 30)); "heat-redirector" => HeatConduit::new(3, false, cost!(Tungsten: 10, Graphite: 10)); "heat-router" => HeatConduit::new(3, false, cost!(Tungsten: 15, Graphite: 10)); - "slag-incinerator" => Incinerator::new(1, true, cost!(Tungsten: 15)); - "carbide-crucible" => ProductionBlock::new(3, true, cost!(Tungsten: 110, Thorium: 150, Oxide: 60)); + "slag-incinerator" -> Incinerator::new(1, true, cost!(Tungsten: 15)); + "carbide-crucible" -> ProductionBlock::new(3, true, cost!(Tungsten: 110, Thorium: 150, Oxide: 60)); // slag centrifuge - "surge-crucible" => ProductionBlock::new(3, true, cost!(Silicon: 100, Graphite: 80, Tungsten: 80, Oxide: 80)); - "cyanogen-synthesizer" => ProductionBlock::new(3, true, cost!(Carbide: 50, Silicon: 80, Beryllium: 90)); - "phase-synthesizer" => ProductionBlock::new(3, true, cost!(Carbide: 90, Silicon: 100, Thorium: 100, Tungsten: 200)); + "surge-crucible" -> ProductionBlock::new(3, true, cost!(Silicon: 100, Graphite: 80, Tungsten: 80, Oxide: 80)); + "cyanogen-synthesizer" -> ProductionBlock::new(3, true, cost!(Carbide: 50, Silicon: 80, Beryllium: 90)); + "phase-synthesizer" -> ProductionBlock::new(3, true, cost!(Carbide: 90, Silicon: 100, Thorium: 100, Tungsten: 200)); // heat reactor // sandbox only - "heat-source" => HeatCrafter::new(1, false, &[]); + "heat-source" -> HeatCrafter::new(1, false, &[]); } make_simple!( @@ -60,30 +60,18 @@ make_simple!( match n { // TODO i didnt realize the significance of two tops before and kinda deleted them, add them back "phase-heater" | "electric-heater" | "oxidation-chamber" | "slag-heater" => { - let mut base = load(n, s); + let mut base = load!(from n which is ["phase-heater" | "electric-heater" | "oxidation-chamber" | "slag-heater"], s); base.overlay( - load( - match r { - Rotation::Up | Rotation::Right => match n { - "phase-heater" => "phase-heater-top1", - "oxidation-chamber" => "oxidation-chamber-top1", - "slag-heater" => "slag-heater-top1", - _ => "electric-heater-top1", - }, - _ => match n { - "phase-heater" => "phase-heater-top2", - "oxidation-chamber" => "oxidation-chamber-top2", - "slag-heater" => "slag-heater-top2", - _ => "electric-heater-top2", - }, - }, - s, - ) + match r { + Rotation::Up | Rotation::Right => + load!(concat top1 => n which is ["phase-heater" | "electric-heater" | "oxidation-chamber" | "slag-heater"], s), + _ => load!(concat top2 => n which is ["phase-heater" | "electric-heater" | "oxidation-chamber" | "slag-heater"], s) + } .rotate(r.rotated(false).count()), ); base } - _ => load(n, s), + n => unimplemented!("{n}"), } }, |_, _, _, buff: &mut DataRead| { @@ -95,5 +83,12 @@ make_simple!( Ok(()) } ); -make_simple!(HeatConduit); +make_simple!(HeatConduit, |_, n, _, _, r: Rotation, s| { + let mut base = load!(from n which is ["heat-router" | "heat-redirector"], s); + base.overlay(match r { + Rotation::Up | Rotation::Right => load!(concat top1 => n which is ["heat-router" | "heat-redirector"], s), + _ => load!(concat top2 => n which is ["heat-router" | "heat-redirector"], s), + }.rotate(r.rotated(false).count())); + base +}); make_simple!(Incinerator); diff --git a/src/block/simple.rs b/src/block/simple.rs index f3053ee..aa7f398 100644 --- a/src/block/simple.rs +++ b/src/block/simple.rs @@ -122,19 +122,7 @@ macro_rules! make_simple { crate::block::simple::make_simple!($name, $draw, $read, false); }; ($name: ident => $read: expr) => { - crate::block::simple::make_simple!( - $name, - |_, n, _, _, _, s| crate::data::renderer::load(n, s), - $read - ); - }; - ($name: ident) => { - crate::block::simple::make_simple!( - $name, - |_, n, _, _, _, s| crate::data::renderer::load(n, s), - |_, _, _, _| Ok(()), - false - ); + crate::block::simple::make_simple!($name, |_, n, _, _, _, _| unimplemented!("{n}"), $read); }; ($name: ident => $draw: expr, $read: expr) => { crate::block::simple::make_simple!($name, |_, _, _, _, _, scl| $draw(scl), $read); @@ -146,6 +134,9 @@ macro_rules! make_simple { |_, _, _, _| Ok(()) ); }; + ($name: ident) => { + crate::block::simple::make_simple!($name, |_, n, _, _, _, _| unimplemented!("{n}")); + }; } pub(crate) use make_simple; diff --git a/src/block/storage.rs b/src/block/storage.rs index b64a0cd..f3a9089 100644 --- a/src/block/storage.rs +++ b/src/block/storage.rs @@ -4,17 +4,17 @@ use crate::block::make_register; use crate::block::simple::{cost, make_simple}; make_register! { - "core-shard" => StorageBlock::new(3, true, cost!(Copper: 1000, Lead: 800)); - "core-foundation" => StorageBlock::new(4, true, cost!(Copper: 3000, Lead: 3000, Silicon: 2000)); - "core-nucleus" => StorageBlock::new(5, true, cost!(Copper: 8000, Lead: 8000, Thorium: 4000, Silicon: 5000)); - "core-bastion" => StorageBlock::new(4, true, cost!(Graphite: 1000, Silicon: 1000, Beryllium: 800)); - "core-citadel" => StorageBlock::new(5, true, cost!(Silicon: 4000, Beryllium: 4000, Tungsten: 3000, Oxide: 1000)); - "core-acropolis" => StorageBlock::new(6, true, cost!(Beryllium: 6000, Silicon: 5000, Tungsten: 5000, Carbide: 3000, Oxide: 3000)); - "container" => StorageBlock::new(2, true, cost!(Titanium: 100)); - "vault" => StorageBlock::new(3, true, cost!(Titanium: 250, Thorium: 125)); - "unloader" => ItemBlock::new(1, true, cost!(Titanium: 25, Silicon: 30)); - "reinforced-container" => StorageBlock::new(2, true, cost!(Tungsten: 30, Graphite: 40)); - "reinforced-vault" => StorageBlock::new(3, true, cost!(Tungsten: 125, Thorium: 70, Beryllium: 100)); + "core-shard" -> StorageBlock::new(3, true, cost!(Copper: 1000, Lead: 800)); + "core-foundation" -> StorageBlock::new(4, true, cost!(Copper: 3000, Lead: 3000, Silicon: 2000)); + "core-nucleus" -> StorageBlock::new(5, true, cost!(Copper: 8000, Lead: 8000, Thorium: 4000, Silicon: 5000)); + "core-bastion" -> StorageBlock::new(4, true, cost!(Graphite: 1000, Silicon: 1000, Beryllium: 800)); + "core-citadel" -> StorageBlock::new(5, true, cost!(Silicon: 4000, Beryllium: 4000, Tungsten: 3000, Oxide: 1000)); + "core-acropolis" -> StorageBlock::new(6, true, cost!(Beryllium: 6000, Silicon: 5000, Tungsten: 5000, Carbide: 3000, Oxide: 3000)); + "container" -> StorageBlock::new(2, true, cost!(Titanium: 100)); + "vault" -> StorageBlock::new(3, true, cost!(Titanium: 250, Thorium: 125)); + "unloader" -> ItemBlock::new(1, true, cost!(Titanium: 25, Silicon: 30)); + "reinforced-container" -> StorageBlock::new(2, true, cost!(Tungsten: 30, Graphite: 40)); + "reinforced-vault" -> StorageBlock::new(3, true, cost!(Tungsten: 125, Thorium: 70, Beryllium: 100)); } make_simple!(StorageBlock); diff --git a/src/block/turrets.rs b/src/block/turrets.rs index 6510d5c..0a3cf0e 100644 --- a/src/block/turrets.rs +++ b/src/block/turrets.rs @@ -4,7 +4,6 @@ use super::{BlockLogic, Rotation, State}; use crate::block::make_register; use crate::block::simple::cost; use crate::data::{renderer::*, DataRead, ReadError}; -use crate::utils::ImageUtils; make_register! { "duo" => ItemTurret::new(1, true, cost!(Copper: 35)); @@ -45,13 +44,22 @@ fn draw_turret( _: Rotation, s: Scale, ) -> ImageHolder { - let path = match name { + let size = me.get_size(); + let mut base = match name { "breach" | "diffuse" | "sublimate" | "titan" | "disperse" | "afflict" | "lustre" - | "scathe" | "malign" | "smite" => format!("reinforced-block-{}", me.get_size()), - _ => format!("block-{}", me.get_size()), + | "scathe" | "malign" | "smite" => load!(s -> match size { + 3 => "reinforced-block-3", + 4 => "reinforced-block-4", + 5 => "reinforced-block-5", + }), + _ => load!(s -> match size { + 1 => "block-1", + 2 => "block-2", + 3 => "block-3", + 4 => "block-4", + }), }; - let mut base = load(&path, s); - base.overlay(&load(name, s)); + base.overlay(load!(from name which is ["duo" | "scatter" | "scorch" | "hail" | "wave" | "tsunami" | "lancer" | "arc" | "parallax" | "swarmer" | "salvo" | "segment" | "fuse" | "ripple" | "cyclone" | "foreshadow" | "spectre" | "meltdown" | "breach" | "diffuse" | "sublimate" | "titan" | "disperse" | "afflict" | "lustre" | "scathe" | "malign" | "smite"], s).borrow()); base } diff --git a/src/block/units.rs b/src/block/units.rs index fa31095..dcd15de 100644 --- a/src/block/units.rs +++ b/src/block/units.rs @@ -33,40 +33,33 @@ use crate::unit; // ) // } -make_simple!(ConstructorBlock, |me: &Self, - name, - _, - _, - rot: Rotation, - s| { - let mut base = load(name, s); +make_simple!(ConstructorBlock, |_, name, _, _, rot: Rotation, s| { + let mut base = load!(from name which is ["additive-reconstructor" | "multiplicative-reconstructor" | "exponential-reconstructor" | "tetrative-reconstructor" | "tank-refabricator" | "mech-refabricator" | "ship-refabricator" | "prime-refabricator" | "tank-assembler" | "ship-assembler" | "mech-assembler"], s); let times = rot.rotated(false).count(); if !name.contains("assembler") { - let mut out = load( - &match name { - "additive-reconstructor" - | "multiplicative-reconstructor" - | "exponential-reconstructor" - | "tetrative-reconstructor" => format!("factory-out-{}", me.size), - _ => format!("factory-out-{}-dark", me.size), - }, - s, - ); - out.rotate(times); - base.overlay(&out); + let mut out = load!(s -> match name { + "additive-reconstructor" => "factory-out-3", + "multiplicative-reconstructor" => "factory-out-5", + "tank-refabricator" | "mech-refabricator" | "ship-refabricator" => + "factory-out-3-dark", + "exponential-reconstructor" => "factory-out-7", + "prime-refabricator" | "tank-assembler" | "ship-assembler" | "mech-assembler" => + "factory-out-5-dark", + "tetrative-reconstructor" => "factory-out-9", + }); + base.overlay(out.rotate(times)); - let mut input = load( - &match name { - "additive-reconstructor" - | "multiplicative-reconstructor" - | "exponential-reconstructor" - | "tetrative-reconstructor" => format!("factory-in-{}", me.size), - _ => format!("factory-in-{}-dark", me.size), - }, - s, - ); - input.rotate(times); - base.overlay(&input); + let mut r#in = load!(s -> match name { + "additive-reconstructor" => "factory-in-3", + "multiplicative-reconstructor" => "factory-in-5", + "tank-refabricator" | "mech-refabricator" | "ship-refabricator" => + "factory-in-3-dark", + "exponential-reconstructor" => "factory-in-7", + "prime-refabricator" | "tank-assembler" | "ship-assembler" | "mech-assembler" => + "factory-in-5-dark", + "tetrative-reconstructor" => "factory-in-9", + }); + base.overlay(r#in.rotate(times)); } // TODO: the context cross is too small @@ -89,24 +82,21 @@ make_simple!(ConstructorBlock, |me: &Self, // } // } - base.overlay(&load(&format!("{name}-top"), s)); + base.overlay(load!(concat top => name which is ["additive-reconstructor" | "multiplicative-reconstructor" | "exponential-reconstructor" | "tetrative-reconstructor" | "tank-refabricator" | "mech-refabricator" | "ship-refabricator" | "prime-refabricator" | "tank-assembler" | "ship-assembler" | "mech-assembler"], s).borrow()); if matches!(name, "mech-assembler" | "tank-assembler" | "ship-assembler") { base.overlay( - load( - match rot { - Rotation::Up | Rotation::Right => match name { - "mech-assembler" => "mech-assembler-side1", - "tank-assembler" => "tank-assembler-side1", - _ => "ship-assembler-side1", - }, - _ => match name { - "mech-assembler" => "mech-assembler-side2", - "tank-assembler" => "tank-assembler-side2", - _ => "ship-assembler-side2", - }, - }, - s, - ) + match rot { + Rotation::Up | Rotation::Right => load!(s -> match name { + "mech-assembler" => "mech-assembler-side1", + "tank-assembler" => "tank-assembler-side1", + "ship-assembler" => "ship-assembler-side1", + }), + _ => load!(s -> match name { + "mech-assembler" => "mech-assembler-side2", + "tank-assembler" => "tank-assembler-side2", + "ship-assembler" => "ship-assembler-side2", + }), + } .rotate(times), ); } @@ -114,23 +104,20 @@ make_simple!(ConstructorBlock, |me: &Self, }); make_simple!(UnitRepairTower); make_simple!(AssemblerModule, |_, _, _, _, rot: Rotation, scl| { - let mut base = load("basic-assembler-module", scl); + let mut base = load!("basic-assembler-module", scl); base.overlay( - load( - match rot { - Rotation::Up | Rotation::Right => "basic-assembler-module-side1", - _ => "basic-assembler-module-side2", - }, - scl, - ) + load!(scl -> match rot { + Rotation::Up | Rotation::Right => "basic-assembler-module-side1", + _ => "basic-assembler-module-side2", + }) .rotate(rot.rotated(false).count()), ); base }); make_simple!( RepairTurret => |scl| { - let mut bot = load("block-2", scl); - let top = load("repair-turret", scl); + let mut bot = load!("block-2", scl); + let top = load!("repair-turret", scl); bot.overlay(&top); bot }, @@ -166,7 +153,7 @@ make_register! { "ship-assembler" => ConstructorBlock::new(5, true, cost!(Carbide: 100, Oxide: 200, Tungsten: 500, Silicon: 800, Thorium: 400)); "mech-assembler" => ConstructorBlock::new(5, true, cost!(Carbide: 200, Thorium: 600, Oxide: 200, Tungsten: 500, Silicon: 900)); // smh collaris "basic-assembler-module" => AssemblerModule::new(5, true, cost!(Carbide: 300, Thorium: 500, Oxide: 200, PhaseFabric: 400)); // the dummy block - "unit-repair-tower" => UnitRepairTower::new(2, true, cost!(Graphite: 90, Silicon: 90, Tungsten: 80)); + "unit-repair-tower" -> UnitRepairTower::new(2, true, cost!(Graphite: 90, Silicon: 90, Tungsten: 80)); } @@ -258,25 +245,22 @@ impl BlockLogic for AssemblerBlock { rot: Rotation, s: Scale, ) -> ImageHolder { - let mut base = load(name, s); - let mut out = load( - match name { - "ground-factory" | "air-factory" | "naval-factory" => "factory-out-3", - _ => "factory-out-3-dark", - }, - s, - ); + let mut base = load!(from name which is ["ground-factory" | "air-factory" | "naval-factory" | "tank-fabricator" | "ship-fabricator" | "mech-fabricator"], s); + let mut out = load!(s -> match name { + "ground-factory" | "air-factory" | "naval-factory" => "factory-out-3", + _ => "factory-out-3-dark", + }); out.rotate(rot.rotated(false).count()); base.overlay(&out); - base.overlay(&load( - &match name { - "ground-factory" | "air-factory" | "naval-factory" => { - format!("factory-top-{}", self.size) - } - _ => format!("{name}-top"), - }, - s, - )); + base.overlay( + load!(s -> match name { + "ground-factory" | "air-factory" | "naval-factory" => "factory-top-3", + "tank-fabricator" => "tank-fabricator-top", + "ship-fabricator" => "ship-fabricator-top", + "mech-fabricator" => "mech-fabricator-top", + }) + .borrow(), + ); base } diff --git a/src/block/walls.rs b/src/block/walls.rs index 900232f..2ec2e26 100644 --- a/src/block/walls.rs +++ b/src/block/walls.rs @@ -4,47 +4,42 @@ use crate::block::*; use crate::data::dynamic::DynType; use crate::data::renderer::load; -make_simple!(WallBlock, |_, name, _, _, _, s| { - match name { - "thruster" => { - let mut base = load("thruster", s); - base.overlay(&load("thruster-top", s)); - base - } - _ => load(name, s), - } +make_simple!(WallBlock, |_, _, _, _, _, s| { + let mut base = load!("thruster", s); + base.overlay(&load!("thruster-top", s)); + base }); make_register! { - "copper-wall" => WallBlock::new(1, true, cost!(Copper: 6)); - "copper-wall-large" => WallBlock::new(2, true, cost!(Copper: 6 * 4)); - "titanium-wall" => WallBlock::new(1, true, cost!(Titanium: 6)); - "titanium-wall-large" => WallBlock::new(2, true, cost!(Titanium: 6 * 4)); - "plastanium-wall" => WallBlock::new(1, true, cost!(Metaglass: 2, Plastanium: 5)); - "plastanium-wall-large" => WallBlock::new(2, true, cost!(Metaglass: 2 * 4, Plastanium: 5 * 4)); - "thorium-wall" => WallBlock::new(1, true, cost!(Thorium: 6)); - "thorium-wall-large" => WallBlock::new(2, true, cost!(Thorium: 6 * 4)); - "phase-wall" => WallBlock::new(1, true, cost!(PhaseFabric: 6)); - "phase-wall-large" => WallBlock::new(2, true, cost!(PhaseFabric: 6 * 4)); - "surge-wall" => WallBlock::new(1, true, cost!(SurgeAlloy: 6)); - "surge-wall-large" => WallBlock::new(2, true, cost!(SurgeAlloy: 6 * 4)); + "copper-wall" -> WallBlock::new(1, true, cost!(Copper: 6)); + "copper-wall-large" -> WallBlock::new(2, true, cost!(Copper: 6 * 4)); + "titanium-wall" -> WallBlock::new(1, true, cost!(Titanium: 6)); + "titanium-wall-large" -> WallBlock::new(2, true, cost!(Titanium: 6 * 4)); + "plastanium-wall" -> WallBlock::new(1, true, cost!(Metaglass: 2, Plastanium: 5)); + "plastanium-wall-large" -> WallBlock::new(2, true, cost!(Metaglass: 2 * 4, Plastanium: 5 * 4)); + "thorium-wall" -> WallBlock::new(1, true, cost!(Thorium: 6)); + "thorium-wall-large" -> WallBlock::new(2, true, cost!(Thorium: 6 * 4)); + "phase-wall" -> WallBlock::new(1, true, cost!(PhaseFabric: 6)); + "phase-wall-large" -> WallBlock::new(2, true, cost!(PhaseFabric: 6 * 4)); + "surge-wall" -> WallBlock::new(1, true, cost!(SurgeAlloy: 6)); + "surge-wall-large" -> WallBlock::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" => WallBlock::new(1, true, cost!(Tungsten: 6)); - "tungsten-wall-large" => WallBlock::new(2, true, cost!(Tungsten: 6 * 4)); - "blast-door" => DoorBlock::new(2, true, cost!(Tungsten: 24, Silicon: 24)); - "reinforced-surge-wall" => WallBlock::new(1, true, cost!(SurgeAlloy: 6, Tungsten: 2)); - "reinforced-surge-wall-large" => WallBlock::new(2, true, cost!(SurgeAlloy: 6 * 4, Tungsten: 2 * 4)); - "carbide-wall" => WallBlock::new(1, true, cost!(Thorium: 6, Carbide: 6)); - "carbide-wall-large" => WallBlock::new(2, true, cost!(Thorium: 6 * 4, Carbide: 6 * 4)); - "shielded-wall" => WallBlock::new(2, true, cost!(PhaseFabric: 20, SurgeAlloy: 12, Beryllium: 12)); - "beryllium-wall" => WallBlock::new(1, true, cost!(Beryllium: 6)); - "beryllium-wall-large" => WallBlock::new(2, true, cost!(Beryllium: 6 * 4)); + "tungsten-wall" -> WallBlock::new(1, true, cost!(Tungsten: 6)); + "tungsten-wall-large" -> WallBlock::new(2, true, cost!(Tungsten: 6 * 4)); + "blast-door" -> DoorBlock::new(2, true, cost!(Tungsten: 24, Silicon: 24)); + "reinforced-surge-wall" -> WallBlock::new(1, true, cost!(SurgeAlloy: 6, Tungsten: 2)); + "reinforced-surge-wall-large" -> WallBlock::new(2, true, cost!(SurgeAlloy: 6 * 4, Tungsten: 2 * 4)); + "carbide-wall" -> WallBlock::new(1, true, cost!(Thorium: 6, Carbide: 6)); + "carbide-wall-large" -> WallBlock::new(2, true, cost!(Thorium: 6 * 4, Carbide: 6 * 4)); + "shielded-wall" -> WallBlock::new(2, true, cost!(PhaseFabric: 20, SurgeAlloy: 12, Beryllium: 12)); + "beryllium-wall" -> WallBlock::new(1, true, cost!(Beryllium: 6)); + "beryllium-wall-large" -> WallBlock::new(2, true, cost!(Beryllium: 6 * 4)); // sandbox only - "scrap-wall" => WallBlock::new(1, true, cost!(Scrap: 6)); - "scrap-wall-large" => WallBlock::new(2, true, cost!(Scrap: 24)); - "scrap-wall-huge" => WallBlock::new(3, true, cost!(Scrap: 54)); - "scrap-wall-gigantic" => WallBlock::new(4, true, cost!(Scrap: 96)); + "scrap-wall" -> WallBlock::new(1, true, cost!(Scrap: 6)); + "scrap-wall-large" -> WallBlock::new(2, true, cost!(Scrap: 24)); + "scrap-wall-huge" -> WallBlock::new(3, true, cost!(Scrap: 54)); + "scrap-wall-gigantic" -> WallBlock::new(4, true, cost!(Scrap: 96)); "thruster" => WallBlock::new(4, false, cost!(Scrap: 96)); } @@ -80,21 +75,15 @@ impl BlockLogic for DoorBlock { s: Scale, ) -> ImageHolder { if let Some(state) = state { - return if *Self::get_state(state) { - // TODO check - load( - match name { - "door" => "door-open", - "blast-door" => "blast-door-open", - _ => "door-large-open", - }, - s, - ) - } else { - load(name, s) + if *Self::get_state(state) { + return load!(s -> match name { + "door" => "door-open", + "blast-door" => "blast-door-open", + _ => "door-large-open", + }); }; } - load(name, s) + load!(from name which is ["door" | "blast-door" | "door-large"], s) } fn data_from_i32(&self, _: i32, _: GridPos) -> Result<DynData, DataConvertError> { diff --git a/src/data/autotile.rs b/src/data/autotile.rs index a79195e..28b864d 100644 --- a/src/data/autotile.rs +++ b/src/data/autotile.rs @@ -221,7 +221,23 @@ pub fn flrot(flip: u8, rot: u8, with: &mut ImageHolder) { /// TODO figure out if a flip is cheaper than a rotate_270 pub fn rotations2tile((index, rot, flip): (u8, u8, u8), name: &str, scale: Scale) -> ImageHolder { - let mut p = load(&format!("{name}-{index}"), scale); + let mut p = match index { + 0 => { + load!(concat 0 => name which is ["armored-duct" | "pulse-conduit" | "plated-conduit" | "conduit" | "conveyor" | "titanium-conveyor" | "armored-conveyor" | "duct"], scale) + } + 1 => { + load!(concat 1 => name which is ["armored-duct" | "pulse-conduit" | "plated-conduit" | "conduit" | "conveyor" | "titanium-conveyor" | "armored-conveyor" | "duct"], scale) + } + 2 => { + load!(concat 2 => name which is ["armored-duct" | "pulse-conduit" | "plated-conduit" | "conduit" | "conveyor" | "titanium-conveyor" | "armored-conveyor" | "duct"], scale) + } + 3 => { + load!(concat 3 => name which is ["armored-duct" | "pulse-conduit" | "plated-conduit" | "conduit" | "conveyor" | "titanium-conveyor" | "armored-conveyor" | "duct"], scale) + } + _ => { + load!(concat 4 => name which is ["armored-duct" | "pulse-conduit" | "plated-conduit" | "conduit" | "conveyor" | "titanium-conveyor" | "armored-conveyor" | "duct"], scale) + } + }; flrot(flip, rot, p.borrow_mut()); p } diff --git a/src/data/renderer.rs b/src/data/renderer.rs index 2ae8ac8..c06fb44 100644 --- a/src/data/renderer.rs +++ b/src/data/renderer.rs @@ -1,5 +1,7 @@ //! schematic drawing pub(crate) use super::autotile::*; +use super::schematic::Schematic; +use super::GridPos; use crate::block::environment::METAL_FLOOR; use crate::block::Rotation; pub(crate) use crate::utils::{ImageUtils, Overlay, Repeat}; @@ -9,27 +11,9 @@ pub(crate) use image::{ }; pub(crate) use std::borrow::{Borrow, BorrowMut}; use std::ops::{Deref, DerefMut}; -use std::sync::LazyLock; - -use super::schematic::Schematic; -use super::GridPos; - -macro_rules! r { - ($v:expr) => {{ - static TMP: LazyLock<RgbaImage> = LazyLock::new(|| $v); - &TMP - }}; -} - -type Images = phf::Map<&'static str, &'static LazyLock<RgbaImage>>; -static EMPTY_FULL: LazyLock<RgbaImage> = LazyLock::new(|| RgbaImage::new(32, 32)); -static EMPTY_QUAR: LazyLock<RgbaImage> = LazyLock::new(|| RgbaImage::new(8, 8)); -static EMPTY_EIGH: LazyLock<RgbaImage> = LazyLock::new(|| RgbaImage::new(4, 4)); - -static FULL: Images = include!(concat!(env!("OUT_DIR"), "/full.rs")); -// static HALF: Images = include!(concat!(env!("OUT_DIR"), "/half.rs")); -static QUAR: Images = include!(concat!(env!("OUT_DIR"), "/quar.rs")); -static EIGH: Images = include!(concat!(env!("OUT_DIR"), "/eigh.rs")); +include!(concat!(env!("OUT_DIR"), "/full.rs")); +include!(concat!(env!("OUT_DIR"), "/quar.rs")); +include!(concat!(env!("OUT_DIR"), "/eigh.rs")); pub enum ImageHolder { Borrow(&'static RgbaImage), @@ -101,6 +85,7 @@ impl From<RgbaImage> for ImageHolder { } #[derive(Debug, Copy, Clone)] +#[repr(u8)] pub enum Scale { Full, // Half, @@ -125,22 +110,57 @@ impl std::ops::Mul<u32> for Scale { } } -pub(crate) fn try_load(name: &str, scale: Scale) -> Option<&'static RgbaImage> { - match scale { - Scale::Quarter => QUAR.get(name).map(|v| LazyLock::force(v)), - Scale::Eigth => EIGH.get(name).map(|v| LazyLock::force(v)), - Scale::Full => FULL.get(name).map(|v| LazyLock::force(v)), - // Scale::Half => HALF.get(&name).map(|v| LazyLock::force(v)), - } -} - -#[track_caller] -pub(crate) fn load(name: &str, scale: Scale) -> ImageHolder { - let Some(i) = try_load(name, scale) else { - panic!("failed to load {name}") +#[macro_export] +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>], + })) + } }; + ($name: literal) => { paste::paste! { + [crate::data::renderer::full::[<$name:snake:upper>], crate::data::renderer::quar::[<$name:snake:upper>], crate::data::renderer::eigh::[<$name:snake:upper>]] + } }; + (from $v:ident which is [$($k:literal $(|)?)+], $scale: ident) => { + crate::data::renderer::load!($scale -> match $v { + $($k => $k,)+ + }) + }; + // turn load!(s -> match x { "v" => "y" }) into match x { "v" => load!("y", s) } + ($scale:ident -> match $v:ident { $($k:pat => $nam:literal $(,)?)+ }) => { + match $v { + $($k => crate::data::renderer::load!($nam, $scale),)+ + #[allow(unreachable_patterns)] + n => unreachable!("{n:?}"), + } }; - ImageHolder::from(i) + (concat $x:expr => $v:ident which is [$($k:literal $(|)?)+], $scale: ident) => { paste::paste! { + match $v { + $($k => + ImageHolder::from(std::sync::LazyLock::force(match $scale { + crate::data::renderer::Scale::Quarter => crate::data::renderer::quar::[<$k:snake:upper _ $x:snake:upper>], + crate::data::renderer::Scale::Eigth => crate::data::renderer::eigh::[<$k:snake:upper _ $x:snake:upper>], + crate::data::renderer::Scale::Full => crate::data::renderer::full::[<$k:snake:upper _ $x:snake:upper>], + })), + )+ + #[allow(unreachable_patterns)] + n => unreachable!("{n:?}"), + } + } }; + // (concat $x:expr, to $v:ident which is [$($k:literal $(|)?)+], $scale: ident) => { paste::paste! { + // match $v { + // $($k => + // ImageHolder::from(**match $scale { + // crate::data::renderer::Scale::Quarter => crate::data::renderer::quar::[<$k:snake:upper $x:snake:upper>], + // crate::data::renderer::Scale::Eigth => crate::data::renderer::eigh::[<$k:snake:upper $x:snake:upper>], + // crate::data::renderer::Scale::Full => crate::data::renderer::full::[<$k:snake:upper $x:snake:upper>], + // }), + // )+ + // } + // } } } +pub(crate) use load; /// trait for renderable objects pub trait Renderable { @@ -278,11 +298,9 @@ impl Renderable for Map<'_> { /// Loads all the images into memory (about 300mb) pub fn warmup() { - for map in [&FULL, &QUAR, &EIGH] { - for val in map.values() { - LazyLock::force(val); - } - } + full::warmup(); + quar::warmup(); + eigh::warmup(); } #[test] diff --git a/src/utils/image.rs b/src/utils/image.rs index 4095404..423a4c7 100644 --- a/src/utils/image.rs +++ b/src/utils/image.rs @@ -1,7 +1,7 @@ use image::*; pub trait Overlay<W> { - /// Overlay with onto self at coordinates x, y, without blending + /// Overlay with => self at coordinates x, y, without blending fn overlay_at(&mut self, with: &W, x: u32, y: u32) -> &mut Self; } @@ -13,7 +13,7 @@ pub trait RepeatNew { pub trait ImageUtils { /// Tint this image with the color fn tint(&mut self, color: Rgb<u8>) -> &mut Self; - /// Overlay with onto self (does not blend) + /// Overlay with => self (does not blend) fn overlay(&mut self, with: &Self) -> &mut Self; /// rotate fn rotate(&mut self, times: u8) -> &mut Self; |