mindustry logic execution, map- and schematic- parsing and rendering
| -rw-r--r-- | mindus/Cargo.toml | 2 | ||||
| -rw-r--r-- | mindus/src/block/production.rs | 2 | ||||
| -rw-r--r-- | mindus/src/data/autotile.rs | 14 | ||||
| -rw-r--r-- | mindus/src/data/map.rs | 54 | ||||
| -rw-r--r-- | mindus/src/data/renderer.rs | 4 | ||||
| -rw-r--r-- | mindus/src/data/schematic.rs | 56 | ||||
| -rw-r--r-- | mindus/src/item/storage.rs | 48 |
7 files changed, 97 insertions, 83 deletions
diff --git a/mindus/Cargo.toml b/mindus/Cargo.toml index c7411cd..bc1a042 100644 --- a/mindus/Cargo.toml +++ b/mindus/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mindus" -version = "4.0.18" +version = "5.0.1" edition = "2021" description = "A library for working with mindustry data formats (eg schematics and maps) (fork of plandustry)" authors = [ diff --git a/mindus/src/block/production.rs b/mindus/src/block/production.rs index 9e97bf2..b20f121 100644 --- a/mindus/src/block/production.rs +++ b/mindus/src/block/production.rs @@ -27,7 +27,7 @@ make_simple!( unsafe { base.overlay(&ozone) }; base }, - |b: &mut Build<'_>, buff: &mut DataRead| { + |b: &mut Build, buff: &mut DataRead| { // format: // - progress: `f32` // - warmup: `f32` diff --git a/mindus/src/data/autotile.rs b/mindus/src/data/autotile.rs index 59a6010..f8021f3 100644 --- a/mindus/src/data/autotile.rs +++ b/mindus/src/data/autotile.rs @@ -46,11 +46,11 @@ pub(crate) use define; #[cfg(test)] pub(crate) use dir; -pub type Cross<'l> = [Option<(&'l Block, Rotation)>; 4]; +pub type Cross = [Option<(&'static Block, Rotation)>; 4]; /// holds the 4 bordering blocks #[derive(Copy, Clone)] -pub struct RenderingContext<'l> { - pub cross: Cross<'l>, +pub struct RenderingContext { + pub cross: Cross, pub position: PositionContext, } @@ -73,7 +73,7 @@ impl std::fmt::Debug for PositionContext { } #[cfg(test)] -fn print_crosses(v: Vec<Cross<'_>>, height: usize) -> String { +fn print_crosses(v: Vec<Cross>, height: usize) -> String { let mut s = String::new(); for c in v.chunks(height) { for c in c { @@ -89,7 +89,7 @@ fn print_crosses(v: Vec<Cross<'_>>, height: usize) -> String { s } -pub fn tile(ctx: &RenderingContext<'_>, name: &str, rot: Rotation, s: Scale) -> ImageHolder<4> { +pub fn tile(ctx: &RenderingContext, name: &str, rot: Rotation, s: Scale) -> ImageHolder<4> { mask2tile(mask(ctx, rot, name), rot, name, s) } @@ -224,8 +224,8 @@ pub fn mask(ctx: &RenderingContext, rot: Rotation, n: &str) -> U4 { pub trait RotationState { fn get_rotation(&self) -> Option<Rotation>; } -pub trait BlockState<'l> { - fn get_block(&'l self) -> Option<&'l Block>; +pub trait BlockState { + fn get_block(&self) -> Option<&'static Block>; } pub trait Crossable { fn cross(&self, j: usize, c: &PositionContext) -> Cross; diff --git a/mindus/src/data/map.rs b/mindus/src/data/map.rs index c58fbbc..b29ffd8 100644 --- a/mindus/src/data/map.rs +++ b/mindus/src/data/map.rs @@ -90,10 +90,10 @@ use crate::content::Content; /// a tile in a map #[derive(Clone)] -pub struct Tile<'l> { +pub struct Tile { pub floor: BlockEnum, pub ore: BlockEnum, - build: Option<Build<'l>>, + build: Option<Build>, } macro_rules! lo { @@ -105,7 +105,7 @@ macro_rules! lo { } }; } -impl<'l> Tile<'l> { +impl Tile { #[must_use] pub const fn new(floor: BlockEnum, ore: BlockEnum) -> Self { Self { @@ -115,7 +115,7 @@ impl<'l> Tile<'l> { } } - fn set_block(&mut self, block: &'l Block) { + fn set_block(&mut self, block: &'static Block) { self.build = Some(Build { block, state: None, @@ -128,7 +128,7 @@ impl<'l> Tile<'l> { } #[must_use] - pub const fn build(&self) -> Option<&Build<'l>> { + pub const fn build(&self) -> Option<&Build> { self.build.as_ref() } @@ -217,7 +217,7 @@ impl<'l> Tile<'l> { } } -impl std::fmt::Debug for Tile<'_> { +impl std::fmt::Debug for Tile { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!( f, @@ -237,34 +237,34 @@ impl std::fmt::Debug for Tile<'_> { } } -impl<'l> BlockState<'l> for Tile<'l> { - fn get_block(&self) -> Option<&'l Block> { +impl BlockState for Tile { + fn get_block(&self) -> Option<&'static Block> { Some(self.build()?.block) } } -impl RotationState for Tile<'_> { +impl RotationState for Tile { fn get_rotation(&self) -> Option<Rotation> { Some(self.build()?.rotation) } } -impl RotationState for Option<Tile<'_>> { +impl RotationState for Option<Tile> { fn get_rotation(&self) -> Option<Rotation> { self.as_ref().unwrap().get_rotation() } } -impl<'l> BlockState<'l> for Option<Tile<'_>> { - fn get_block(&'l self) -> Option<&'l Block> { +impl BlockState for Option<Tile> { + fn get_block(&self) -> Option<&'static Block> { self.as_ref().unwrap().get_block() } } /// a build on a tile in a map #[derive(Clone)] -pub struct Build<'l> { - pub block: &'l Block, +pub struct Build { + pub block: &'static Block, pub items: Storage<Item>, pub liquids: Storage<Fluid>, pub state: Option<State>, @@ -274,15 +274,15 @@ pub struct Build<'l> { pub data: i8, } -impl std::fmt::Debug for Build<'_> { +impl std::fmt::Debug for Build { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "Build<{block}>", block = self.block.name(),) } } -impl<'l> Build<'l> { +impl Build { #[must_use] - pub fn new(block: &'l Block) -> Build<'l> { + pub fn new(block: &'static Block) -> Build { Self { block, items: Storage::default(), @@ -420,7 +420,7 @@ fn test_read_liquids() { /// a map. /// ## Does not support serialization yet! #[derive(Debug)] -pub struct Map<'l> { +pub struct Map { pub width: usize, pub height: usize, pub tags: HashMap<String, String>, @@ -431,7 +431,7 @@ pub struct Map<'l> { /// (0, 1), (1, 1), (2, 1) /// (0, 2), (1, 2), (2, 2) /// ``` - pub tiles: Vec<Tile<'l>>, + pub tiles: Vec<Tile>, } macro_rules! cond { @@ -444,7 +444,7 @@ macro_rules! cond { }; } -impl<'l> Crossable for Map<'l> { +impl Crossable for Map { fn cross(&self, j: usize, c: &PositionContext) -> Cross { let get = |i| { let b = &self[i]; @@ -462,7 +462,7 @@ impl<'l> Crossable for Map<'l> { } } -impl<'l> Map<'l> { +impl Map { #[must_use] pub fn new(width: usize, height: usize, tags: HashMap<String, String>) -> Self { Self { @@ -474,19 +474,19 @@ impl<'l> Map<'l> { } } - fn push(&mut self, t: Tile<'l>) { + fn push(&mut self, t: Tile) { self.tiles.push(t); } } -impl<'l> Index<usize> for Map<'l> { - type Output = Tile<'l>; +impl Index<usize> for Map { + type Output = Tile; fn index(&self, index: usize) -> &Self::Output { &self.tiles[index] } } -impl<'l> IndexMut<usize> for Map<'l> { +impl IndexMut<usize> for Map { fn index_mut(&mut self, index: usize) -> &mut Self::Output { &mut self.tiles[index] } @@ -512,7 +512,7 @@ pub enum ReadError { } /// serde map -impl<'l> Serializable for Map<'l> { +impl Serializable for Map { type ReadError = ReadError; type WriteError = (); /// deserialize a map @@ -520,7 +520,7 @@ impl<'l> Serializable for Map<'l> { /// notes: /// - does not deserialize data /// - does not deserialize entities - fn deserialize(buff: &mut DataRead<'_>) -> Result<Map<'l>, Self::ReadError> { + fn deserialize(buff: &mut DataRead<'_>) -> Result<Map, Self::ReadError> { let buff = buff.deflate()?; let mut buff = DataRead::new(&buff); { diff --git a/mindus/src/data/renderer.rs b/mindus/src/data/renderer.rs index 5fa5556..e68c96a 100644 --- a/mindus/src/data/renderer.rs +++ b/mindus/src/data/renderer.rs @@ -84,7 +84,7 @@ pub trait Renderable { fn render(&self) -> Image<Vec<u8>, 3>; } -impl Renderable for Schematic<'_> { +impl Renderable for Schematic { /// creates a picture of a schematic. Bridges and node connections are not drawn. /// ``` /// # use mindus::*; @@ -151,7 +151,7 @@ impl Renderable for Schematic<'_> { } } -impl Renderable for Map<'_> { +impl Renderable for Map { /// Draws a map fn render(&self) -> Image<Vec<u8>, 3> { let scale = if self.width + self.height < 2000 { diff --git a/mindus/src/data/schematic.rs b/mindus/src/data/schematic.rs index d324d7f..48e388f 100644 --- a/mindus/src/data/schematic.rs +++ b/mindus/src/data/schematic.rs @@ -19,28 +19,28 @@ pub const MAX_BLOCKS: u32 = 256 * 256; /// a placement in a schematic #[derive(Clone)] -pub struct Placement<'l> { - pub block: &'l Block, +pub struct Placement { + pub block: &'static Block, pub rot: Rotation, state: Option<State>, } -impl PartialEq for Placement<'_> { - fn eq(&self, rhs: &Placement<'_>) -> bool { +impl PartialEq for Placement { + fn eq(&self, rhs: &Placement) -> bool { self.block == rhs.block && self.rot == rhs.rot } } -impl fmt::Debug for Placement<'_> { +impl fmt::Debug for Placement { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { write!(f, "P<{}[*{}]>", self.block.name(), self.rot.ch()) } } -impl<'l> Placement<'l> { +impl Placement { /// make a placement from a block #[must_use] - pub const fn new(block: &'l Block) -> Self { + pub const fn new(block: &'static Block) -> Self { Self { block, rot: Rotation::Up, @@ -82,20 +82,20 @@ impl<'l> Placement<'l> { } } -impl<'l> BlockState<'l> for Placement<'l> { - fn get_block(&self) -> Option<&'l Block> { +impl BlockState for Placement { + fn get_block(&self) -> Option<&'static Block> { Some(self.block) } } -impl RotationState for Placement<'_> { +impl RotationState for Placement { fn get_rotation(&self) -> Option<Rotation> { Some(self.rot) } } -impl<'l> BlockState<'l> for Option<Placement<'l>> { - fn get_block(&self) -> Option<&'l Block> { +impl BlockState for Option<Placement> { + fn get_block(&self) -> Option<&'static Block> { let Some(p) = self else { return None; }; @@ -103,7 +103,7 @@ impl<'l> BlockState<'l> for Option<Placement<'l>> { } } -impl RotationState for Option<Placement<'_>> { +impl RotationState for Option<Placement> { fn get_rotation(&self) -> Option<Rotation> { let Some(p) = self else { return None; @@ -114,16 +114,16 @@ impl RotationState for Option<Placement<'_>> { #[derive(Clone, Debug)] /// a schematic. -pub struct Schematic<'l> { +pub struct Schematic { pub width: usize, pub height: usize, pub tags: HashMap<String, String>, /// schems can have holes, so [Option] is used. - pub blocks: Array2D<Option<Placement<'l>>>, + pub blocks: Array2D<Option<Placement>>, } -impl<'l> PartialEq for Schematic<'l> { - fn eq(&self, rhs: &Schematic<'l>) -> bool { +impl PartialEq for Schematic { + fn eq(&self, rhs: &Schematic) -> bool { self.width == rhs.width && self.height == rhs.height && self.blocks == rhs.blocks @@ -131,7 +131,7 @@ impl<'l> PartialEq for Schematic<'l> { } } -impl<'l> Schematic<'l> { +impl Schematic { #[must_use] /// create a new schematic, panicking if too big /// ``` @@ -238,7 +238,7 @@ impl<'l> Schematic<'l> { /// s.put(0, 0, &DUO); /// assert!(s.get(0, 0).unwrap().is_some()); /// ``` - pub fn get(&self, x: usize, y: usize) -> Result<Option<&Placement<'l>>, PosError> { + pub fn get(&self, x: usize, y: usize) -> Result<Option<&Placement>, PosError> { if x >= self.width || y >= self.height { return Err(PosError { x, @@ -251,7 +251,7 @@ impl<'l> Schematic<'l> { } /// gets a block, mutably - pub fn get_mut(&mut self, x: usize, y: usize) -> Result<Option<&mut Placement<'l>>, PosError> { + pub fn get_mut(&mut self, x: usize, y: usize) -> Result<Option<&mut Placement>, PosError> { if x >= self.width || y >= self.height { return Err(PosError { x, @@ -272,7 +272,7 @@ impl<'l> Schematic<'l> { /// s.put(0, 0, &ROUTER); /// assert!(s.get(0, 0).unwrap().is_some() == true); /// ``` - pub fn put(&mut self, x: usize, y: usize, block: &'l Block) -> &mut Self { + pub fn put(&mut self, x: usize, y: usize, block: &'static Block) -> &mut Self { self.set(x, y, block, DynData::Empty, Rotation::Up).unwrap(); self } @@ -292,7 +292,7 @@ impl<'l> Schematic<'l> { &mut self, x: usize, y: usize, - block: &'l Block, + block: &'static Block, data: DynData, rot: Rotation, ) -> Result<(), PlaceError> { @@ -334,7 +334,7 @@ impl<'l> Schematic<'l> { /// assert!(s.take(0, 0).unwrap().is_some() == true); /// assert!(s.get(0, 0).unwrap().is_none() == true); /// ``` - pub fn take(&mut self, x: usize, y: usize) -> Result<Option<Placement<'l>>, PosError> { + pub fn take(&mut self, x: usize, y: usize) -> Result<Option<Placement>, PosError> { if x >= self.width || y >= self.height { return Err(PosError { x, @@ -348,7 +348,7 @@ impl<'l> Schematic<'l> { } /// iterate over all the blocks - pub fn block_iter(&self) -> impl Iterator<Item = (GridPos, &Placement<'_>)> { + pub fn block_iter(&self) -> impl Iterator<Item = (GridPos, &Placement)> { self.blocks.iter().enumerate().filter_map(|(i, p)| { let Some(p) = p else { return None; @@ -471,10 +471,10 @@ impl fmt::Display for TruncatedError { const SCHEMATIC_HEADER: u32 = ((b'm' as u32) << 24) | ((b's' as u32) << 16) | ((b'c' as u32) << 8) | (b'h' as u32); -impl<'l> Serializable for Schematic<'l> { +impl Serializable for Schematic { type ReadError = ReadError; type WriteError = WriteError; - fn deserialize(buff: &mut DataRead<'_>) -> Result<Schematic<'l>, Self::ReadError> { + fn deserialize(buff: &mut DataRead<'_>) -> Result<Schematic, Self::ReadError> { let hdr = buff.read_u32()?; if hdr != SCHEMATIC_HEADER { return Err(ReadError::Header(hdr)); @@ -624,7 +624,7 @@ pub enum WriteError { Compress(#[from] super::CompressError), } -impl<'l> Schematic<'l> { +impl Schematic { /// deserializes a schematic from base64 /// ``` /// # use mindus::*; @@ -632,7 +632,7 @@ impl<'l> Schematic<'l> { /// let s = Schematic::deserialize_base64(string).unwrap(); /// assert!(s.get(1, 1).unwrap().unwrap().block.name() == "payload-router"); /// ``` - pub fn deserialize_base64(data: &str) -> Result<Schematic<'l>, R64Error> { + pub fn deserialize_base64(data: &str) -> Result<Schematic, R64Error> { let mut buff = vec![0; data.len() / 4 * 3 + 1]; let n_out = base64::decode(data.as_bytes(), buff.as_mut())?; Ok(Self::deserialize(&mut DataRead::new(&buff[..n_out]))?) diff --git a/mindus/src/item/storage.rs b/mindus/src/item/storage.rs index 8cf3c16..9397b14 100644 --- a/mindus/src/item/storage.rs +++ b/mindus/src/item/storage.rs @@ -330,25 +330,27 @@ where (subbed, self.total, other.total) } - #[must_use] - pub fn iter(&self) -> Iter<'_> { + pub fn clear(&mut self) { + self.base.clear(); + } +} + +impl<T: TryFrom<u16>> Storage<T> { + pub fn iter(&self) -> Iter<'_, T> { Iter { base: self.base.iter().enumerate(), all: true, + _t: PhantomData, } } - #[must_use] - pub fn iter_nonzero(&self) -> Iter<'_> { + pub fn iter_nonzero(&self) -> Iter<'_, T> { Iter { base: self.base.iter().enumerate(), all: false, + _t: PhantomData, } } - - pub fn clear(&mut self) { - self.base.clear(); - } } // manual because padding with zeros doesn't affect equality @@ -369,10 +371,7 @@ impl<T> PartialEq for Storage<T> { } } -impl<T> fmt::Display for Storage<T> -where - u16: From<T>, -{ +impl<T: TryFrom<u16> + fmt::Display> fmt::Display for Storage<T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut iter = self.iter_nonzero(); if let Some((ty, cnt)) = iter.next() { @@ -401,19 +400,31 @@ pub struct TrySubError { pub min: u32, } +impl<'l, T: TryFrom<u16>> IntoIterator for &'l Storage<T> { + type Item = (T, u32); + + type IntoIter = Iter<'l, T>; + + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + #[derive(Clone, Debug)] -pub struct Iter<'l> { +#[must_use = "iterator is lazy"] +pub struct Iter<'l, T: TryFrom<u16>> { base: Enumerate<slice::Iter<'l, u32>>, all: bool, + _t: PhantomData<T>, } -impl<'l> Iterator for Iter<'l> { - type Item = (item::Type, u32); +impl<'l, T: TryFrom<u16>> Iterator for Iter<'l, T> { + type Item = (T, u32); fn next(&mut self) -> Option<Self::Item> { for (idx, cnt) in self.base.by_ref() { if *cnt > 0 || self.all { - if let Ok(ty) = item::Type::try_from(idx as u16) { + if let Ok(ty) = T::try_from(idx as u16) { return Some((ty, *cnt)); } } @@ -426,4 +437,7 @@ impl<'l> Iterator for Iter<'l> { } } -impl<'l> FusedIterator for Iter<'l> where Enumerate<slice::Iter<'l, u32>>: FusedIterator {} +impl<'l, T: TryFrom<u16>> FusedIterator for Iter<'l, T> where + Enumerate<slice::Iter<'l, u32>>: FusedIterator +{ +} |