mindustry logic execution, map- and schematic- parsing and rendering
remove leaky hashmap reference rwlock shenanigans
bendn 2023-08-09
parent 6dbc4c5 · commit 86805d0
-rw-r--r--Cargo.toml3
-rw-r--r--build.rs4
-rw-r--r--src/data/map.rs103
-rw-r--r--src/data/renderer.rs19
-rw-r--r--src/exe/map.rs10
5 files changed, 69 insertions, 70 deletions
diff --git a/Cargo.toml b/Cargo.toml
index c7e5b7f..c1621db 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "mindus"
-version = "3.0.3"
+version = "3.0.5"
edition = "2021"
description = "A library for working with mindustry data formats (eg schematics and maps) (fork of plandustry)"
authors = [
@@ -22,7 +22,6 @@ thiserror = "1.0"
bobbin-bits = "0.1"
blurslice = { version = "0.1" }
enum_dispatch = "0.3"
-ahash = { version = "0.8.3", default-features = false, features = ["std", "no-rng"] }
[features]
bin = ["image/png"]
diff --git a/build.rs b/build.rs
index b696779..b9904fa 100644
--- a/build.rs
+++ b/build.rs
@@ -82,7 +82,9 @@ fn main() {
let (mx, my) = if p.width() + p.height() == 48+48 {
(32, 32)
// vents (dont match VENT_CONDENSER, do match (RHYOLITE_VENT)
- } else if path.contains("_VENT") {
+ } else if path.contains("_VENT")
+ // talls
+ || matches!(path.as_str(), "YELLOWCORAL" | "WHITE_TREE" | "WHITE_TREE_DEAD" | "REDWEED" | "SPORE_CLUSTER" | "CRYSTAL_BLOCKS" | "CRYSTAL_CLUSTER" | "VIBRANT_CRYSTAL_CLUSTER" | "CRYSTAL_ORBS") {
(32, 32)
} else {
(p.height(), p.width())
diff --git a/src/data/map.rs b/src/data/map.rs
index 2545a65..aceddbc 100644
--- a/src/data/map.rs
+++ b/src/data/map.rs
@@ -71,7 +71,6 @@
//! - entity read
use std::collections::HashMap;
use std::ops::{Index, IndexMut};
-use std::sync::RwLock;
use thiserror::Error;
use crate::block::content::Type as BlockEnum;
@@ -97,6 +96,15 @@ pub struct Tile<'l> {
build: Option<Build<'l>>,
}
+macro_rules! lo {
+ ($v:expr => [$(|)? $($k:literal $(|)?)+], $scale: ident) => { paste::paste! {
+ match $v {
+ $(BlockEnum::[<$k:camel>] => load!($k, $scale),)+
+ n => unreachable!("{n:?}"),
+ }
+ } };
+}
+
pub type EntityMapping = HashMap<u8, Box<dyn Content>>;
impl<'l> Tile<'l> {
#[must_use]
@@ -138,22 +146,8 @@ impl<'l> Tile<'l> {
1
}
- /// Draw the floor of this tile
- ///
- /// # Safety
- ///
- /// UB if called before [`warmup`](crate::warmup)
- pub unsafe fn floor_image(&self, s: Scale) -> ImageHolder {
- macro_rules! lo {
- ($v:expr => [$(|)? $($k:literal $(|)?)+], $scale: ident) => { paste::paste! {
- match $v {
- $(BlockEnum::[<$k:camel>] => load!($k, $scale),)+
- n => unreachable!("{n:?}"),
- } }
- }
- }
- let floor = || {
- lo!(self.floor => [
+ pub(crate) unsafe fn floor(&self, s: Scale) -> ImageHolder {
+ lo!(self.floor => [
| "darksand"
| "sand-floor"
| "dacite"
@@ -162,62 +156,57 @@ impl<'l> Tile<'l> {
| "basalt"
| "moss"
| "mud"
- | "magmarock"
| "grass"
- | "ice-snow"
- | "hotrock"
- | "char"
- | "snow"
- | "salt"
+ | "ice-snow" | "snow" | "salt" | "ice"
+ | "hotrock" | "char" | "magmarock"
| "shale"
| "metal-floor" | "metal-floor-2" | "metal-floor-3" | "metal-floor-4" | "metal-floor-5" | "metal-floor-damaged"
| "dark-panel-1" | "dark-panel-2" | "dark-panel-3" | "dark-panel-4" | "dark-panel-5" | "dark-panel-6"
- | "darksand-tainted-water"
- | "darksand-water"
- | "deep-tainted-water"
- | "molten-slag"
- | "deep-water"
- | "sand-water"
- | "shallow-water"
+ | "darksand-tainted-water" | "darksand-water" | "deep-tainted-water" | "deep-water" | "sand-water" | "shallow-water" | "tainted-water"
+ | "tar" | "pooled-cryofluid" | "molten-slag"
| "space"
| "stone"
| "bluemat"
| "ferric-craters"
| "beryllic-stone"
- | "rhyolite-crater"
+ | "rhyolite" | "rough-rhyolite" | "rhyolite-crater" | "rhyolite-vent"
| "core-zone"
| "crater-stone"
- | "crystal-floor"
- | "dense-red-stone"
| "redmat"
| "red-ice"
| "spore-moss"
- | "arkyic-vent" | "red-stone-vent" | "rhyolite-vent" | "carbon-vent" | "crystalline-vent" | "yellow-stone-vent"
| "regolith"
- | "rhyolite"
- | "tainted-water"
- | "tar"
- | "empty"
- ], s)
- };
- if self.ore != BlockEnum::Air {
- type Floor = BlockEnum;
- type Ore = BlockEnum;
- // todo Rgb
- static ORE_LAYS: RwLock<HashMap<(Floor, Ore), &'static RgbaImage, ahash::RandomState>> =
- RwLock::new(HashMap::with_hasher(ahash::RandomState::with_seeds(
- 401, 41209, 83123, 2110,
- )));
- if let Some(v) = ORE_LAYS.read().unwrap().get(&(self.floor, self.ore)) {
- return ImageHolder::from(*v);
- }
- return ImageHolder::from(*ORE_LAYS.write().unwrap().entry((self.floor, self.ore)).or_insert_with(|| {
- let mut base = floor();
- base.overlay(lo!(self.ore => ["ore-copper" | "ore-beryllium" | "ore-lead" | "ore-scrap" | "ore-coal" | "ore-thorium" | "ore-titanium" | "ore-tungsten" | "pebbles" | "tendrils"], s).borrow());
- Box::leak(Box::new(base))
- }));
+ | "ferric-stone"
+ | "arkyic-stone" | "arkyic-vent"
+ | "yellow-stone" | "yellow-stone-plates" | "yellow-stone-vent"
+ | "red-stone" | "red-stone-vent" | "dense-red-stone"
+ | "carbon-stone" | "carbon-vent"
+ | "crystal-floor" | "crystalline-stone" | "crystalline-vent"
+ | "empty"], s)
+ }
+
+ #[must_use]
+ pub(crate) unsafe fn ore(&self, s: Scale) -> ImageHolder {
+ 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]
+ pub fn has_ore(&self) -> bool {
+ self.ore != BlockEnum::Air
+ }
+
+ /// Draw the floor of this tile
+ ///
+ /// # Safety
+ ///
+ /// UB if called before [`warmup`](crate::warmup)
+ #[must_use]
+ pub unsafe fn floor_image(&self, s: Scale) -> ImageHolder {
+ let mut floor = self.floor(s);
+ if self.has_ore() {
+ floor.overlay(&self.ore(s));
}
- floor()
+ floor
}
/// Draw this tiles build.
diff --git a/src/data/renderer.rs b/src/data/renderer.rs
index 8289ce1..b209c5a 100644
--- a/src/data/renderer.rs
+++ b/src/data/renderer.rs
@@ -276,11 +276,18 @@ impl Renderable for Map<'_> {
)
}) {
// draw the floor first.
- let img: &RgbaImage = &tile.floor_image(scale);
+ let flo: &RgbaImage = &tile.floor(scale);
// println!("draw {tile:?} ({x}, {y}) + {scale:?}");
- debug_assert_eq!(img.width(), scale.px() as u32);
- debug_assert_eq!(img.height(), scale.px() as u32);
- floor.overlay_at(img, scale * x as u32, scale * y as u32);
+ // debug_assert_eq!(floor.width(), scale.px() as u32);
+ // debug_assert_eq!(floor.height(), scale.px() as u32);
+ floor.overlay_at(flo, scale * x as u32, scale * y as u32);
+ if tile.has_ore() {
+ let ore: &RgbaImage = &tile.ore(scale);
+ // debug_assert_eq!(ore.width(), scale.px() as u32);
+ // debug_assert_eq!(ore.height(), scale.px() as u32);
+ floor.overlay_at(ore, scale * x as u32, scale * y as u32);
+ }
+
if let Some(build) = tile.build() {
let s = build.block.get_size();
let x = x - ((s - 1) / 2) as usize;
@@ -300,8 +307,8 @@ impl Renderable for Map<'_> {
None
};
let img: &RgbaImage = &tile.build_image(ctx.as_ref(), scale);
- debug_assert_eq!(img.width(), scale * build.block.get_size() as u32);
- debug_assert_eq!(img.height(), scale * build.block.get_size() as u32);
+ // debug_assert_eq!(img.width(), scale * build.block.get_size() as u32);
+ // debug_assert_eq!(img.height(), scale * build.block.get_size() as u32);
top.overlay_at(img, scale * x as u32, scale * y as u32);
}
}
diff --git a/src/exe/map.rs b/src/exe/map.rs
index c976696..51c05c6 100644
--- a/src/exe/map.rs
+++ b/src/exe/map.rs
@@ -9,6 +9,7 @@ use super::print_err;
pub fn main(args: Args) {
let reg = build_registry();
let mut ms = MapSerializer(&reg);
+ let runs = std::env::var("RUNS").map_or(10u8, |x| x.parse().unwrap_or(10u8));
// process schematics from command line
println!("starting timing");
@@ -31,17 +32,18 @@ pub fn main(args: Args) {
}
}
let starting_render = Instant::now();
- for _ in 0..10 {
+ for _ in 0..runs {
unsafe { m.render() };
}
let renders_took = starting_render.elapsed();
let took = then.elapsed();
println!(
- "μ total: {:.2}s (10 runs) (deser: {}ms, warmup: {}ms, render: {:.2}s) on map {}",
- took.as_secs_f32() / 10.,
+ "μ total: {:.2}s ({} runs) (deser: {}ms, warmup: {}ms, render: {:.2}s) on map {}",
+ took.as_secs_f32() / runs as f32,
+ runs,
deser_took.as_millis(),
warmup_took.as_millis(),
- renders_took.as_secs_f32() / 10.,
+ renders_took.as_secs_f32() / runs as f32,
m.tags.get("mapname").unwrap(),
);
}