mindustry logic execution, map- and schematic- parsing and rendering
make overlay() unsafe
| -rw-r--r-- | src/block/distribution.rs | 56 | ||||
| -rw-r--r-- | src/block/liquid.rs | 4 | ||||
| -rw-r--r-- | src/block/logic.rs | 2 | ||||
| -rw-r--r-- | src/block/payload.rs | 15 | ||||
| -rw-r--r-- | src/block/power.rs | 22 | ||||
| -rw-r--r-- | src/block/production.rs | 58 | ||||
| -rw-r--r-- | src/block/units.rs | 62 | ||||
| -rw-r--r-- | src/block/walls.rs | 2 | ||||
| -rw-r--r-- | src/data/autotile.rs | 2 | ||||
| -rw-r--r-- | src/data/map.rs | 12 | ||||
| -rw-r--r-- | src/utils/image.rs | 9 |
11 files changed, 139 insertions, 105 deletions
diff --git a/src/block/distribution.rs b/src/block/distribution.rs index 090eecd..67c473e 100644 --- a/src/block/distribution.rs +++ b/src/block/distribution.rs @@ -41,9 +41,12 @@ make_simple!(JunctionBlock => |_, _, _, buff| { read_directional_item_buffer(buf make_simple!(SimpleDuctBlock, |_, name, _, _, rot: Rotation, s| { let mut base = load!("duct-base", s); let mut top = load!(from name which is ["overflow-duct" "underflow-duct"], s); - // SAFETY: any load() is square - unsafe { top.rotate(rot.rotated(false).count()) }; - base.overlay(&top); + unsafe { + // SAFETY: any load() is square + top.rotate(rot.rotated(false).count()); + // SAFETY: same size + base.overlay(&top); + } base }); @@ -71,7 +74,7 @@ fn draw_stack( if i == skip { continue; } - to.overlay(&edge(i)); + unsafe { to.overlay(&edge(i)) }; } }; let gimme = |n: u8| match n { @@ -104,7 +107,7 @@ fn draw_stack( unsafe { base.rotate(going) }; for [r, i] in [[3, 0b1000], [0, 0b0100], [1, 0b0010], [2, 0b0001]] { if (mask.into_u8() & i) == 0 && (going != r || empty) { - base.overlay(&edge(r)); + unsafe { base.overlay(&edge(r)) }; } } base @@ -120,14 +123,11 @@ make_simple!( |_, _, _, buff: &mut DataRead| buff.skip(8), true ); -make_simple!( - SurgeRouter - / |s| { - let mut base = load!("surge-router", s); - base.overlay(&load!("top", s)); - base - } -); +make_simple!(SurgeRouter, |_, _, _, _, r: Rotation, s| { + let mut base = load!("surge-router", s); + unsafe { base.overlay(load!("top", s).rotate(r.rotated(false).count())) }; + base +}); // format: id: [`i32`] make_simple!(UnitCargoLoader => |_, _, _, buff: &mut DataRead| buff.skip(4)); @@ -235,7 +235,7 @@ impl BlockLogic for ItemBlock { "unloader" => "unloader-center", _ => "center", }); - p.overlay(top.tint(item.color())); + unsafe { p.overlay(top.tint(item.color())) }; return p; } } @@ -244,20 +244,26 @@ impl BlockLogic for ItemBlock { } if name == "duct-router" { let mut arrow = load!("top", s); - unsafe { arrow.rotate(rot.rotated(false).count()) }; - p.overlay(&arrow); + unsafe { + arrow.rotate(rot.rotated(false).count()); + p.overlay(&arrow); + } p } else if name == "duct-unloader" { let mut top = load!("duct-unloader-top", s); - unsafe { top.rotate(rot.rotated(false).count()) }; - p.overlay(&top); + unsafe { + top.rotate(rot.rotated(false).count()); + p.overlay(&top); + } let mut arrow = load!("duct-unloader-arrow", s); - unsafe { arrow.rotate(rot.rotated(false).count()) }; - p.overlay(&arrow); + unsafe { + arrow.rotate(rot.rotated(false).count()); + p.overlay(&arrow); + } p } else { let mut null = load!("cross-full", s); - null.overlay(&p); + unsafe { null.overlay(&p) }; null } } @@ -480,7 +486,7 @@ impl BlockLogic for BridgeBlock { match name { "mass-driver" => { let mut base = load!("mass-driver-base", s); - base.overlay(&load!("mass-driver", s)); + unsafe { base.overlay(&load!("mass-driver", s)) }; base } "duct-bridge" | "reinforced-bridge-conduit" => { @@ -492,8 +498,10 @@ impl BlockLogic for BridgeBlock { _ => "reinforced-bridge-conduit-dir", } ); - unsafe { arrow.rotate(r.rotated(false).count()) }; - base.overlay(&arrow); + unsafe { + 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" diff --git a/src/block/liquid.rs b/src/block/liquid.rs index 5ef4ea8..06d34ac 100644 --- a/src/block/liquid.rs +++ b/src/block/liquid.rs @@ -114,12 +114,12 @@ impl BlockLogic for FluidBlock { if let Some(state) = state { if let Some(liq) = Self::get_state(state) { let mut top = load!("center", s); - p.overlay(top.tint(liq.color())); + unsafe { p.overlay(top.tint(liq.color())) }; return p; } } let mut null = load!("cross-full", s); - null.overlay(&p); + unsafe { null.overlay(&p) }; null } diff --git a/src/block/logic.rs b/src/block/logic.rs index 7aa9eb1..769e639 100644 --- a/src/block/logic.rs +++ b/src/block/logic.rs @@ -328,7 +328,7 @@ impl BlockLogic for SwitchLogic { if let Some(state) = state { if *Self::get_state(state) { let on = load!("switch-on", s); - base.overlay(&on); + unsafe { base.overlay(&on) }; return base; } } diff --git a/src/block/payload.rs b/src/block/payload.rs index e8d8117..6a8ef11 100644 --- a/src/block/payload.rs +++ b/src/block/payload.rs @@ -120,9 +120,10 @@ impl BlockLogic for PayloadBlock { "payload-router" | "reinforced-payload-router" => { let mut base = load!(from name which is ["payload-router" | "reinforced-payload-router"], s); - unsafe { base.rotate(r.rotated(false).count()) }; - let over = load!(concat "over" => name which is ["payload-router" | "reinforced-payload-router"], s); - base.overlay(&over); + unsafe { + base.rotate(r.rotated(false).count()); + base.overlay(& load!(concat "over" => name which is ["payload-router" | "reinforced-payload-router"], s)); + } base } _ => { @@ -132,9 +133,11 @@ impl BlockLogic for PayloadBlock { "large-constructor" => "factory-out-5-dark", _ => "factory-out-5", }); - unsafe { out.rotate(r.rotated(false).count()) }; - base.overlay(&out); - base.overlay(&load!(concat "top" => name which is ["constructor" | "large-constructor" | "payload-source"], s)); + unsafe { + out.rotate(r.rotated(false).count()); + base.overlay(&out); + base.overlay(&load!(concat "top" => name which is ["constructor" | "large-constructor" | "payload-source"], s)) + }; base } } diff --git a/src/block/power.rs b/src/block/power.rs index ba29cb9..62f32f8 100644 --- a/src/block/power.rs +++ b/src/block/power.rs @@ -12,13 +12,15 @@ make_simple!( Neoplasia, |_, _, _, _, rot: Rotation, scl| { let mut base = load!("neoplasia-reactor", scl); - base.overlay(unsafe { - load!(scl -> match rot { - Rotation::Up | Rotation::Right => "neoplasia-reactor-top1", - Rotation::Down | Rotation::Left => "neoplasia-reactor-top2", - }) - .rotate(rot.rotated(false).count()) - }); + unsafe { + base.overlay( + load!(scl -> match rot { + Rotation::Up | Rotation::Right => "neoplasia-reactor-top1", + Rotation::Down | Rotation::Left => "neoplasia-reactor-top2", + }) + .rotate(rot.rotated(false).count()), + ) + }; base }, |_, _, _, buff: &mut DataRead| read_heater(buff) @@ -29,8 +31,10 @@ make_simple!(DiodeBlock, |_, _, _, _, rot: Rotation, s| { return base; } let mut top = load!("diode-arrow", s); - unsafe { top.rotate(rot.rotated(false).count()) }; - base.overlay(&top); + unsafe { + top.rotate(rot.rotated(false).count()); + base.overlay(&top) + }; base }); diff --git a/src/block/production.rs b/src/block/production.rs index 9cb13ca..cd48482 100644 --- a/src/block/production.rs +++ b/src/block/production.rs @@ -52,20 +52,22 @@ make_simple!( // electrolyzer exclusive // ozone <- e(^) -> hydrogen let mut base = load!("electrolyzer", s); - base.overlay(unsafe { - load!(s -> match r { - Rotation::Up | Rotation::Left => "electrolyzer-hydrogen-output1" - Rotation::Down | Rotation::Right => "electrolyzer-hydrogen-output2" - }) - .rotate(r.count()) - }); - base.overlay(unsafe { - load!(s -> match r { - Rotation::Down | Rotation::Right => "electrolyzer-ozone-output1" - Rotation::Up | Rotation::Left => "electrolyzer-ozone-output2" - }) - .rotate(r.mirrored(true, true).count()) - }); + unsafe { + base.overlay( + load!(s -> match r { + Rotation::Up | Rotation::Left => "electrolyzer-hydrogen-output1" + Rotation::Down | Rotation::Right => "electrolyzer-hydrogen-output2" + }) + .rotate(r.count()), + ); + base.overlay( + load!(s -> match r { + Rotation::Down | Rotation::Right => "electrolyzer-ozone-output1" + Rotation::Up | Rotation::Left => "electrolyzer-ozone-output2" + }) + .rotate(r.mirrored(true, true).count()), + ); + } base }, |b: &mut Build<'_>, _, _, buff: &mut DataRead| { @@ -82,10 +84,12 @@ make_simple!( HeatCrafter, |_, n, _, _, r: Rotation, s| { let mut base = load!(from n which is ["phase-heater" | "electric-heater" | "oxidation-chamber" | "slag-heater" | "heat-source"], s); - base.overlay(unsafe { match r { + unsafe { + base.overlay(match r { Rotation::Up | Rotation::Right => load!(concat "top1" => n which is ["phase-heater" | "electric-heater" | "oxidation-chamber" | "slag-heater" | "heat-source"], s), Rotation::Down | Rotation::Left => load!(concat "top2" => n which is ["phase-heater" | "electric-heater" | "oxidation-chamber" | "slag-heater" | "heat-source"], s) - }.rotate(r.rotated(false).count())}); + }.rotate(r.rotated(false).count())) + }; base }, |_, _, _, buff: &mut DataRead| { @@ -99,16 +103,18 @@ make_simple!( ); make_simple!(HeatConduit, |_, n, _, _, r: Rotation, s| { let mut base = load!(from n which is ["heat-router" | "heat-redirector"], s); - base.overlay(unsafe { - match r { - Rotation::Up | Rotation::Right => { - load!(concat "top1" => n which is ["heat-router" | "heat-redirector"], s) - } - Rotation::Down | Rotation::Left => { - load!(concat "top2" => n which is ["heat-router" | "heat-redirector"], s) + unsafe { + base.overlay( + match r { + Rotation::Up | Rotation::Right => { + load!(concat "top1" => n which is ["heat-router" | "heat-redirector"], s) + } + Rotation::Down | Rotation::Left => { + load!(concat "top2" => n which is ["heat-router" | "heat-redirector"], s) + } } - } - .rotate(r.rotated(false).count()) - }); + .rotate(r.rotated(false).count()), + ) + }; base }); diff --git a/src/block/units.rs b/src/block/units.rs index 9fc561d..83b39af 100644 --- a/src/block/units.rs +++ b/src/block/units.rs @@ -39,14 +39,16 @@ make_simple!( |_, name, _, _, rot: Rotation, s| { let mut base = load!(from name which is ["tank-assembler" | "ship-assembler" | "mech-assembler"], s); - base.overlay(unsafe { + unsafe { + base.overlay( match rot { Rotation::Up | Rotation::Right => load!(concat "side1" => name which is ["tank-assembler" | "ship-assembler" | "mech-assembler"], s), Rotation::Down | Rotation::Left => load!(concat "side2" => name which is ["tank-assembler" | "ship-assembler" | "mech-assembler"], s) - } + } .rotate(rot.rotated(false).count()) - }); - base.overlay(&load!(concat "top" => name which is ["tank-assembler" | "ship-assembler" | "mech-assembler"], s)); + ); + base.overlay(&load!(concat "top" => name which is ["tank-assembler" | "ship-assembler" | "mech-assembler"], s)) + }; base }, |_, reg, map, buff| read_assembler(reg, map, buff) @@ -76,13 +78,15 @@ make_simple!( AssemblerModule, |_, _, _, _, rot: Rotation, scl| { let mut base = load!("basic-assembler-module", scl); - base.overlay(unsafe { - load!(scl -> match rot { - Rotation::Up | Rotation::Right => "basic-assembler-module-side1", - _ => "basic-assembler-module-side2", - }) - .rotate(rot.rotated(false).count()) - }); + unsafe { + base.overlay( + load!(scl -> match rot { + Rotation::Up | Rotation::Right => "basic-assembler-module-side1", + _ => "basic-assembler-module-side2", + }) + .rotate(rot.rotated(false).count()), + ) + }; base }, |_, reg, map, buff| read_payload_block(reg, map, buff) @@ -186,7 +190,7 @@ impl BlockLogic for ConstructorBlock { "prime-refabricator" => "factory-out-5-dark", "tetrative-reconstructor" => "factory-out-9", }); - base.overlay(unsafe { out.rotate(times) }); + unsafe { base.overlay(out.rotate(times)) }; let mut r#in = load!(s -> match name { "additive-reconstructor" => "factory-in-3", @@ -197,7 +201,7 @@ impl BlockLogic for ConstructorBlock { "prime-refabricator" => "factory-in-5-dark", "tetrative-reconstructor" => "factory-in-9", }); - base.overlay(unsafe { r#in.rotate(times) }); + unsafe { base.overlay(r#in.rotate(times)) }; // TODO: the context cross is too small // for i in 0..4u8 { @@ -219,7 +223,9 @@ impl BlockLogic for ConstructorBlock { // } // } - base.overlay(&load!(concat "top" => name which is ["additive-reconstructor" | "multiplicative-reconstructor" | "exponential-reconstructor" | "tetrative-reconstructor" | "tank-refabricator" | "mech-refabricator" | "ship-refabricator" | "prime-refabricator"], s)); + unsafe { + base.overlay(&load!(concat "top" => name which is ["additive-reconstructor" | "multiplicative-reconstructor" | "exponential-reconstructor" | "tetrative-reconstructor" | "tank-refabricator" | "mech-refabricator" | "ship-refabricator" | "prime-refabricator"], s)) + }; base } @@ -327,19 +333,21 @@ impl BlockLogic for UnitFactory { s: Scale, ) -> ImageHolder<4> { let mut base = load!(from name which is ["ground-factory" | "air-factory" | "naval-factory" | "tank-fabricator" | "ship-fabricator" | "mech-fabricator"], s); - base.overlay(unsafe { - load!(s -> match name { - "ground-factory" | "air-factory" | "naval-factory" => "factory-out-3", - _ => "factory-out-3-dark", - }) - .rotate(rot.rotated(false).count()) - }) - .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", - })); + unsafe { + base.overlay( + load!(s -> match name { + "ground-factory" | "air-factory" | "naval-factory" => "factory-out-3", + _ => "factory-out-3-dark", + }) + .rotate(rot.rotated(false).count()), + ) + .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", + })) + }; base } diff --git a/src/block/walls.rs b/src/block/walls.rs index f2dcb01..4eaad5c 100644 --- a/src/block/walls.rs +++ b/src/block/walls.rs @@ -6,7 +6,7 @@ use crate::data::renderer::load; make_simple!(WallBlock, |_, _, _, _, _, s| { let mut base = load!("thruster", s); - base.overlay(&load!("thruster-top", s)); + unsafe { base.overlay(&load!("thruster-top", s)) }; base }); diff --git a/src/data/autotile.rs b/src/data/autotile.rs index ce8361c..92ef1b4 100644 --- a/src/data/autotile.rs +++ b/src/data/autotile.rs @@ -122,7 +122,7 @@ pub fn mask2tile(mask: U4, rot: Rotation, name: &str, scale: Scale) -> ImageHold // from bottom + left B0011 => match rot { Rotation::Right => p!("2-0"), // ┬ - Rotation::Up => p!("2-3-h"), // ┤ + Rotation::Up => p!("2-3-h"), // ┤ _ => unreachable!(), }, // from right diff --git a/src/data/map.rs b/src/data/map.rs index 4660d90..636e3f3 100644 --- a/src/data/map.rs +++ b/src/data/map.rs @@ -139,13 +139,12 @@ impl<'l> Tile<'l> { /// /// dont think about it too much #[must_use] + #[inline] pub fn size(&self) -> u8 { - if let Some(b) = &self.build { - return b.block.get_size(); - } - 1 + self.build.as_ref().map_or(1, |v| v.block.get_size()) } + #[inline] pub(crate) fn floor(&self, s: Scale) -> ImageHolder<4> { lo!(self.floor => [ | "darksand" @@ -186,11 +185,13 @@ impl<'l> Tile<'l> { } #[must_use] + #[inline] pub(crate) fn ore(&self, s: Scale) -> ImageHolder<4> { lo!(self.ore => ["ore-copper" | "ore-beryllium" | "ore-lead" | "ore-scrap" | "ore-coal" | "ore-thorium" | "ore-titanium" | "ore-tungsten" | "pebbles" | "tendrils" | "ore-wall-tungsten" | "ore-wall-beryllium" | "ore-wall-thorium" | "spawn" | "ore-crystal-thorium"], s) } #[must_use] + #[inline] pub fn has_ore(&self) -> bool { self.ore != BlockEnum::Air } @@ -200,13 +201,14 @@ impl<'l> Tile<'l> { pub fn floor_image(&self, s: Scale) -> ImageHolder<4> { let mut floor = self.floor(s); if self.has_ore() { - floor.overlay(&self.ore(s)); + unsafe { floor.overlay(&self.ore(s)) }; } floor } /// Draw this tiles build. #[must_use] + #[inline] pub fn build_image(&self, context: Option<&RenderingContext>, s: Scale) -> ImageHolder<4> { // building covers floore let Some(b) = &self.build else { diff --git a/src/utils/image.rs b/src/utils/image.rs index 69842b4..f5debcb 100644 --- a/src/utils/image.rs +++ b/src/utils/image.rs @@ -23,7 +23,10 @@ pub trait ImageUtils { /// Tint this image with the color fn tint(&mut self, color: (u8, u8, u8)) -> &mut Self; /// Overlay with => self (does not blend) - fn overlay(&mut self, with: Self::With<'_>) -> &mut Self; + /// # Safety + /// + /// UB if a.width != b.width || a.height != b.height + unsafe fn overlay(&mut self, with: Self::With<'_>) -> &mut Self; /// rotate (squares only) /// # Safety /// @@ -256,7 +259,7 @@ impl ImageUtils for Image<&mut [u8], 4> { self } type With<'a> = &'a Image<&'a [u8], 4>; - fn overlay(&mut self, with: &Image<&[u8], 4>) -> &mut Self { + unsafe fn overlay(&mut self, with: &Image<&[u8], 4>) -> &mut Self { unsafe_assert!(self.width() == with.width()); unsafe_assert!(self.height() == with.height()); unsafe_assert!(with.buffer.len() > 4); @@ -531,7 +534,7 @@ impl ImageUtils for ImageHolder<4> { self } type With<'a> = &'a Self; - fn overlay(&mut self, with: &Self) -> &mut Self { + unsafe fn overlay(&mut self, with: &Self) -> &mut Self { self.borrow_mut().overlay(&with.borrow()); self } |