mindustry logic execution, map- and schematic- parsing and rendering
make overlay() unsafe
bendn 2023-08-14
parent 4374f6d · commit 2f33303
-rw-r--r--src/block/distribution.rs56
-rw-r--r--src/block/liquid.rs4
-rw-r--r--src/block/logic.rs2
-rw-r--r--src/block/payload.rs15
-rw-r--r--src/block/power.rs22
-rw-r--r--src/block/production.rs58
-rw-r--r--src/block/units.rs62
-rw-r--r--src/block/walls.rs2
-rw-r--r--src/data/autotile.rs2
-rw-r--r--src/data/map.rs12
-rw-r--r--src/utils/image.rs9
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
}