mindustry logic execution, map- and schematic- parsing and rendering
Diffstat (limited to 'src/data/renderer.rs')
-rw-r--r--src/data/renderer.rs222
1 files changed, 16 insertions, 206 deletions
diff --git a/src/data/renderer.rs b/src/data/renderer.rs
index cb6d88d..ecbbf85 100644
--- a/src/data/renderer.rs
+++ b/src/data/renderer.rs
@@ -4,12 +4,13 @@ use dashmap::DashMap;
use image::codecs::png::PngDecoder;
pub(crate) use image::{DynamicImage, RgbaImage};
use std::io::{BufReader, Cursor};
+use std::ops::{Deref, DerefMut};
use std::path::{Path, PathBuf};
use std::sync::OnceLock;
use zip::ZipArchive;
+pub(crate) use super::autotile::*;
use crate::block::environment::METAL_FLOOR;
-use crate::block::{Block, Rotation};
use crate::team::SHARDED;
pub(crate) use crate::utils::ImageUtils;
use crate::Map;
@@ -58,6 +59,19 @@ impl BorrowMut<RgbaImage> for ImageHolder {
}
}
+impl Deref for ImageHolder {
+ type Target = RgbaImage;
+ fn deref(&self) -> &Self::Target {
+ self.borrow()
+ }
+}
+
+impl DerefMut for ImageHolder {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ self.borrow_mut()
+ }
+}
+
impl From<Option<Ref<'static, PathBuf, RgbaImage>>> for ImageHolder {
fn from(value: Option<Ref<'static, PathBuf, RgbaImage>>) -> Self {
Self::Borrow(value.unwrap())
@@ -76,61 +90,6 @@ impl From<RgbaImage> for ImageHolder {
}
}
-pub type Cross<'l> = [Option<(&'l Block, Rotation)>; 4];
-/// holds the 4 bordering blocks
-#[derive(Copy, Clone)]
-pub struct RenderingContext<'l> {
- pub cross: Cross<'l>,
- pub rotation: Rotation,
- pub position: PositionContext,
-}
-
-/// holds positions
-#[derive(Copy, Clone, Eq, PartialEq)]
-pub struct PositionContext {
- pub position: GridPos,
- pub width: usize,
- pub height: usize,
-}
-
-impl std::fmt::Debug for PositionContext {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- write!(
- f,
- "PC<{:?} ({}/{})>",
- self.position, self.width, self.height
- )
- }
-}
-
-impl std::fmt::Debug for RenderingContext<'_> {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- std::fmt::Display::fmt(self, f)
- }
-}
-
-impl std::fmt::Display for RenderingContext<'_> {
- /// this display impl shows RC<$directions=+own rotation>
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- write!(f, "RC<")?;
- macro_rules! f {
- ($f:expr, $z:expr, $x:literal, $at: expr, $srot: expr) => {
- if let Some((_, rot)) = $z {
- if (rot == $at && rot.mirrored(true, true) != $srot) {
- $f.write_str($x)?;
- }
- }
- };
- }
- f!(f, self.cross[0], "N = ", Rotation::Down, self.rotation);
- f!(f, self.cross[1], "E = ", Rotation::Left, self.rotation);
- f!(f, self.cross[2], "S = ", Rotation::Up, self.rotation);
- f!(f, self.cross[3], "W = ", Rotation::Right, self.rotation);
-
- write!(f, "{:?}>", self.rotation)
- }
-}
-
static CACHE: OnceLock<Cache> = OnceLock::new();
pub(crate) fn load(category: &str, name: &str) -> Option<Ref<'static, PathBuf, RgbaImage>> {
let key = Path::new("blocks").join(category).join(name);
@@ -199,155 +158,6 @@ where
c
}
-pub trait RotationState {
- fn get_rotation(&self) -> Option<Rotation>;
-}
-pub trait BlockState<'l> {
- fn get_block(&'l self) -> Option<&'l Block>;
-}
-pub(crate) trait Crossable {
- fn cross(&self, j: usize, c: &PositionContext) -> Cross;
-}
-
-// pub(crate) trait Darray {
-// type Output;
-// fn n(&self, j: usize, c: &PositionContext) -> Option<&Self::Output>;
-// fn e(&self, j: usize, c: &PositionContext) -> Option<&Self::Output>;
-// fn s(&self, j: usize, c: &PositionContext) -> Option<&Self::Output>;
-// fn w(&self, j: usize, c: &PositionContext) -> Option<&Self::Output>;
-// }
-
-#[cfg(test)]
-fn print_crosses(v: Vec<Cross<'_>>, height: usize) -> String {
- let mut s = String::new();
- for c in v.chunks(height) {
- for c in c {
- s.push(c[0].map_or('_', |(_, r)| r.ch()));
- for c in c[1..].iter() {
- s.push(',');
- s.push(c.map_or('_', |(_, r)| r.ch()));
- }
- s.push(' ');
- }
- s.push('\n');
- }
- s
-}
-
-#[test]
-fn test_cross() {
- use crate::block::distribution::define;
- let mut reg = crate::block::BlockRegistry::default();
- crate::block::distribution::register(&mut reg);
- let mut ss = super::schematic::SchematicSerializer(&reg);
- macro_rules! test {
- ($schem: literal => $($a:tt,$b:tt,$c:tt,$d:tt)*) => {
- let s = ss.deserialize_base64($schem).unwrap();
- let mut c = vec![];
- println!("{:#?}", s.blocks);
-
- for (position, _) in s.block_iter() {
- let pctx = PositionContext {
- position,
- width: s.width,
- height: s.height,
- };
- c.push(s.cross(&pctx));
- }
- let n = s.tags.get("name").map_or("<unknown>", |x| &x);
- let cc: Vec<Cross> = vec![
- $(define!($a,$b,$c,$d),)*
- ];
- if cc != c {
- let a = print_crosses(cc, s.height as usize);
- let b = print_crosses(c, s.height as usize);
- for diff in diff::lines(&a, &b) {
- match diff {
- diff::Result::Left(l) => println!("\x1b[38;5;1m{}", l),
- diff::Result::Right(r) => println!("\x1b[38;5;2m{}", r),
- diff::Result::Both(l, _) => println!("\x1b[0m{}", l),
- }
- }
- print!("\x1b[0m");
- /*
- for diff in diff::slice(&c.into_iter().enumerate().collect::<Vec<_>>(), &cc.into_iter().enumerate().collect::<Vec<_>>()) {
- match diff {
- diff::Result::Left((i, l)) => println!("\x1b[38;5;1m- {l:?} at {i}"),
- diff::Result::Right((i, r)) => println!("\x1b[38;5;2m+ {r:?} at {i}"),
- diff::Result::Both((i, l), _) => println!("\x1b[0m {l:?} at {i}"),
- }
- }
- */
- panic!("test {n} \x1b[38;5;1mfailed\x1b[0m")
- }
- println!("test {n} \x1b[38;5;2mpassed\x1b[0m");
- };
- }
- // crosses go from bottom left -> top left -> bottom left + 1 -> top left + 1...
- // the symbols are directions (> => Right...), which mean the neighbors pointing direction
- // _ = no block
-
- // the basic test
- // ─┐
- // ─┤
- test!("bXNjaAF4nGNgYmBiZmDJS8xNZWBNSizOTGbgTkktTi7KLCjJzM9jYGBgy0lMSs0pZmCNfr9gTSwjA0dyfl5ZamV+EVCOhQEBGGEEM4hiZGAGAOb+EWA=" =>
- // (0, 0) (0, 1)
- // n e s w borders (west void for first row)
- >,v,_,_ _,v,>,_
- // (1, 0) (1, 1)
- v,_,_,> _,_,v,>
- );
- // the loop test
- // ─│─
- // ─┼┐
- // ─└┘
- test!("bXNjaAF4nDWK4QqAIBCDd6dE0SNGP8zuh2CeaAS9fZk0xvjGBgNjYJM7BDaqy5h3qb6EfAZNAIboNokVvKyE0Wu65NbyDhM+cQv6mTtTM/WFYfqLm6m3lx9MAg7n" =>
- >,^,_,_ <,>,<,_ _,v,>,_
- >,<,_,< v,v,^,> _,>,>,<
- v,_,_,^ >,_,<,> _,_,v,v
- );
- // the snek test
- // └┐
- // ─┘
- test!("bXNjaAF4nGNgYmBiZmDJS8xNZWApzkvNZuBOSS1OLsosKMnMz2NgYGDLSUxKzSlmYIqOZWTgSM7PK0utzC8CSrAwIAAjEIIQhGJkYAIARA0Ozg==" =>
- ^,^,_,_ _,<,>,_
- <,_,_,> _,_,^,^
- );
-
- // the notile test
- test!("bXNjaAF4nCWJQQqAIBREx69E0Lq994oWph8STEMj6fZpzcDjDQMCSahoDsZsdN1TYB25aucz28uniMlxsdmf3wCGYDYOBbSsAqNN8eYn5XYofJEdAtSB31tfaoIVGw==" =>
- <,>,_,_ _,^,v,_
- ^,_,_,v _,_,>,<
- );
- // the asymmetrical test
- // <───
- // ───>
- test!("bXNjaAF4nEXJwQqAIBAE0HGVCPrE6GC2B0HdcCPw78MKnMMwj4EFWbjiM8N5bRnLwRpqPK8oBcCU/M5JQetmMAcpNzep/cCIAfX69yv6RF0PFy0O4Q==" =>
- <,>,_,_ _,<,>,_
- <,>,_,> _,<,>,<
- // <,_,_,> _,_,>,<
- <,_,_,> _,_,>,<
- );
-
- // the complex test
- // ─┬─│││─
- // ─┤─┘─┘─
- // ─┤┌─│─┐
- // ─┼┘─┴─│
- test!("bXNjaAF4nEWOUQ7CIBBEh2VZTbyCx/A2xg9a+WiC0LTGxNvb7Wjk5wEzb7M4QCO05UdBqj3PF5zuZR2XaX5OvQGwmodSV8j1FnAce3uVd1+24Iz/CYQQ8fcVHYEQIjqEXWEm9LwgX9kR+PLSbm2BMlN6Sk/3LhJnJu6S6CVmxl2MntEzv38AchUPug==" =>
- >,v,_,_ >,v,>,_ >,v,>,_ _,v,>,_
- v,<,_,> v,v,v,> v,>,v,> _,<,v,>
- v,>,_,v >,<,<,v <,^,v,v _,v,>,v
- <,>,_,< ^,v,>,v v,>,<,> _,^,^,<
- v,<,_,> >,>,>,< ^,^,v,^ _,^,>,v
- >,v,_,> ^,v,<,v ^,>,>,> _,>,^,^
- // <,_,_,< ^,_,>,v v,_,<,> _,_,^,<
- // v,_,_,> >,_,>,< ^,_,v,^ _,_,>,v
- // >,_,_,> ^,_,<,v ^,_,>,> _,_,^,^
- v,_,_,< >,_,v,> >,_,v,^ _,_,>,^
- );
-}
-
/// trait for renderable objects
pub trait Renderable {
/// creates a picture of a schematic. Bridges and node connections are not drawn.
@@ -501,7 +311,7 @@ fn all_blocks() {
None,
Some(&RenderingContext {
cross: [None; 4],
- rotation: Rotation::Up,
+ rotation: crate::block::Rotation::Up,
position: PositionContext {
position: GridPos(0, 0),
width: 5,