mindustry logic execution, map- and schematic- parsing and rendering
Diffstat (limited to 'src/data/schematic.rs')
-rw-r--r--src/data/schematic.rs97
1 files changed, 42 insertions, 55 deletions
diff --git a/src/data/schematic.rs b/src/data/schematic.rs
index 7ad2a67..d324d7f 100644
--- a/src/data/schematic.rs
+++ b/src/data/schematic.rs
@@ -4,13 +4,12 @@ use std::collections::HashMap;
use std::fmt::{self, Write};
use thiserror::Error;
-use crate::block::{self, Block, BlockRegistry, Rotation, State};
+use crate::block::{self, Block, Rotation, State, BLOCK_REGISTRY};
use crate::data::base64;
-use crate::data::dynamic::{self, DynData, DynSerializer};
+use crate::data::dynamic::{self, DynData};
use crate::data::renderer::*;
-use crate::data::{self, DataRead, DataWrite, GridPos, Serializer};
+use crate::data::{self, DataRead, DataWrite, GridPos, Serializable};
use crate::item::storage::ItemStorage;
-use crate::registry::RegistryEntry;
use crate::utils::array::Array2D;
/// biggest schematic
@@ -232,10 +231,11 @@ impl<'l> Schematic<'l> {
/// ```
/// # use mindus::Schematic;
/// # use mindus::block::Rotation;
+ /// # use mindus::block::DUO;
///
/// let mut s = Schematic::new(5, 5);
/// assert!(s.get(0, 0).unwrap().is_none());
- /// s.put(0, 0, &mindus::block::turrets::DUO);
+ /// 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> {
@@ -266,9 +266,10 @@ impl<'l> Schematic<'l> {
/// put a block in (same as [`Schematic::set`], but less arguments and builder-ness). panics!!!
/// ```
/// # use mindus::Schematic;
+ /// # use mindus::block::ROUTER;
///
/// let mut s = Schematic::new(5, 5);
- /// s.put(0, 0, &mindus::block::distribution::ROUTER);
+ /// 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 {
@@ -279,11 +280,12 @@ impl<'l> Schematic<'l> {
/// set a block
/// ```
/// # use mindus::Schematic;
- /// # use mindus::DynData;
+ /// # use mindus::data::dynamic::DynData;
/// # use mindus::block::Rotation;
+ /// # use mindus::block::ROUTER;
///
/// let mut s = Schematic::new(5, 5);
- /// s.set(0, 0, &mindus::block::distribution::ROUTER, DynData::Empty, Rotation::Right);
+ /// s.set(0, 0, &ROUTER, DynData::Empty, Rotation::Right);
/// assert!(s.get(0, 0).unwrap().is_some() == true);
/// ```
pub fn set(
@@ -323,12 +325,11 @@ impl<'l> Schematic<'l> {
/// take out a block
/// ```
/// # use mindus::Schematic;
- /// # use mindus::DynData;
-
+ /// # use mindus::block::DUO;
/// # use mindus::block::Rotation;
///
/// let mut s = Schematic::new(5, 5);
- /// s.put(0, 0, &mindus::block::turrets::DUO);
+ /// s.put(0, 0, &DUO);
/// assert!(s.get(0, 0).unwrap().is_some() == true);
/// assert!(s.take(0, 0).unwrap().is_some() == true);
/// assert!(s.get(0, 0).unwrap().is_none() == true);
@@ -361,11 +362,11 @@ impl<'l> Schematic<'l> {
/// returns (cost, `is_sandbox`)
/// ```
/// # use mindus::Schematic;
- /// # use mindus::DynData;
/// # use mindus::block::Rotation;
+ /// # use mindus::block::CYCLONE;
///
/// let mut s = Schematic::new(5, 5);
- /// s.put(1, 1, &mindus::block::turrets::CYCLONE);
+ /// s.put(1, 1, &CYCLONE);
/// assert_eq!(s.compute_total_cost().0.get_total(), 405);
/// ```
pub fn compute_total_cost(&self) -> (ItemStorage, bool) {
@@ -470,13 +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);
-/// `serde_schematic`
-pub struct SchematicSerializer<'l>(pub &'l BlockRegistry<'l>);
-
-impl<'l> Serializer<Schematic<'l>> for SchematicSerializer<'l> {
+impl<'l> Serializable for Schematic<'l> {
type ReadError = ReadError;
type WriteError = WriteError;
- fn deserialize(&mut self, buff: &mut DataRead<'_>) -> Result<Schematic<'l>, Self::ReadError> {
+ fn deserialize(buff: &mut DataRead<'_>) -> Result<Schematic<'l>, Self::ReadError> {
let hdr = buff.read_u32()?;
if hdr != SCHEMATIC_HEADER {
return Err(ReadError::Header(hdr));
@@ -502,7 +500,7 @@ impl<'l> Serializer<Schematic<'l>> for SchematicSerializer<'l> {
block_table.reserve(num_table as usize);
for _ in 0..num_table {
let name = buff.read_utf()?;
- match self.0.get(name) {
+ match BLOCK_REGISTRY.get(name) {
None => return Err(ReadError::NoSuchBlock(name.to_owned())),
Some(b) => block_table.push(b),
}
@@ -521,7 +519,7 @@ impl<'l> Serializer<Schematic<'l>> for SchematicSerializer<'l> {
let config = if version < 1 {
block.data_from_i32(buff.read_i32()?, pos)?
} else {
- DynSerializer.deserialize(&mut buff)?
+ DynData::deserialize(&mut buff)?
};
let rot = Rotation::from(buff.read_u8()?);
schematic.set(pos.0, pos.1, block, config, rot)?;
@@ -529,24 +527,20 @@ impl<'l> Serializer<Schematic<'l>> for SchematicSerializer<'l> {
Ok(schematic)
}
- fn serialize(
- &mut self,
- buff: &mut DataWrite<'_>,
- data: &Schematic,
- ) -> Result<(), Self::WriteError> {
+ fn serialize(&self, buff: &mut DataWrite<'_>) -> Result<(), Self::WriteError> {
// write the header first just in case
buff.write_u32(SCHEMATIC_HEADER)?;
buff.write_u8(1)?;
let mut rbuff = DataWrite::default();
// don't have to check dimensions because they're already limited to MAX_DIMENSION
- rbuff.write_i16(data.width as i16)?;
- rbuff.write_i16(data.height as i16)?;
- if data.tags.len() > u8::MAX as usize {
- return Err(WriteError::TagCount(data.tags.len()));
+ rbuff.write_i16(self.width as i16)?;
+ rbuff.write_i16(self.height as i16)?;
+ if self.tags.len() > u8::MAX as usize {
+ return Err(WriteError::TagCount(self.tags.len()));
}
- rbuff.write_u8(data.tags.len() as u8)?;
- for (k, v) in &data.tags {
+ rbuff.write_u8(self.tags.len() as u8)?;
+ for (k, v) in &self.tags {
rbuff.write_utf(k)?;
rbuff.write_utf(v)?;
}
@@ -554,11 +548,11 @@ impl<'l> Serializer<Schematic<'l>> for SchematicSerializer<'l> {
let mut block_map = HashMap::new();
let mut block_table = Vec::new();
let mut block_count = 0i32;
- for curr in data.blocks.iter().filter_map(|b| b.as_ref()) {
+ for curr in self.blocks.iter().filter_map(|b| b.as_ref()) {
block_count += 1;
- if let Entry::Vacant(e) = block_map.entry(curr.block.get_name()) {
+ if let Entry::Vacant(e) = block_map.entry(curr.block.name()) {
e.insert(block_table.len() as u32);
- block_table.push(curr.block.get_name());
+ block_table.push(curr.block.name());
}
}
if block_table.len() > i8::MAX as usize {
@@ -571,14 +565,14 @@ impl<'l> Serializer<Schematic<'l>> for SchematicSerializer<'l> {
}
// don't have to check data.blocks.len() because dimensions don't allow exceeding MAX_BLOCKS
rbuff.write_i32(block_count)?;
- for (pos, curr) in data.block_iter() {
- rbuff.write_i8(block_map[curr.block.get_name()] as i8)?;
+ for (pos, curr) in self.block_iter() {
+ rbuff.write_i8(block_map[curr.block.name()] as i8)?;
rbuff.write_u32(pos.into())?;
let data = match curr.state {
None => DynData::Empty,
Some(ref s) => curr.block.serialize_state(s)?,
};
- DynSerializer.serialize(&mut rbuff, &data)?;
+ data.serialize(&mut rbuff)?;
rbuff.write_u8(curr.rot.into())?;
}
rbuff.inflate(buff)?;
@@ -630,26 +624,24 @@ pub enum WriteError {
Compress(#[from] super::CompressError),
}
-impl<'l> SchematicSerializer<'l> {
+impl<'l> Schematic<'l> {
/// deserializes a schematic from base64
/// ```
/// # use mindus::*;
/// let string = "bXNjaAF4nGNgZmBmZmDJS8xNZeBOyslPzlYAkwzcKanFyUWZBSWZ+XkMDAxsOYlJqTnFDEzRsYwMfAWJlTn5iSm6RfmlJalFQGlGEGJkZWSYxQAAcBkUPA==";
- /// let reg = build_registry();
- /// let mut ss = SchematicSerializer(&reg);
- /// let s = ss.deserialize_base64(string).unwrap();
+ /// let s = Schematic::deserialize_base64(string).unwrap();
/// assert!(s.get(1, 1).unwrap().unwrap().block.name() == "payload-router");
/// ```
- pub fn deserialize_base64(&mut self, data: &str) -> Result<Schematic<'l>, R64Error> {
+ pub fn deserialize_base64(data: &str) -> Result<Schematic<'l>, 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]))?)
+ Ok(Self::deserialize(&mut DataRead::new(&buff[..n_out]))?)
}
/// serialize a schematic to base64
- pub fn serialize_base64(&mut self, data: &Schematic<'l>) -> Result<String, W64Error> {
+ pub fn serialize_base64(&self) -> Result<String, W64Error> {
let mut buff = DataWrite::default();
- self.serialize(&mut buff, data)?;
+ self.serialize(&mut buff)?;
let buff = buff.get_written();
// round up because of padding
let mut text = vec![0; 4 * (buff.len() / 3 + usize::from(buff.len() % 3 != 0))];
@@ -703,14 +695,12 @@ mod test {
($name:ident, $($val:expr);+;) => {
#[test]
fn $name() {
- let reg = crate::block::build_registry();
- let mut ser = SchematicSerializer(&reg);
$(
- let parsed = unwrap_pretty(ser.deserialize_base64($val));
+ let parsed = unwrap_pretty(Schematic::deserialize_base64($val));
println!("\x1b[38;5;2mdeserialized\x1b[0m {}", parsed.tags.get("name").unwrap());
- let unparsed = unwrap_pretty(ser.serialize_base64(&parsed));
+ let unparsed = unwrap_pretty(parsed.serialize_base64());
println!("\x1b[38;5;2mserialized\x1b[0m {}", parsed.tags.get("name").unwrap());
- let parsed2 = unwrap_pretty(ser.deserialize_base64(&unparsed));
+ let parsed2 = unwrap_pretty(Schematic::deserialize_base64(&unparsed));
println!("\x1b[38;5;2mredeserialized\x1b[0m {}", parsed.tags.get("name").unwrap());
if parsed != parsed2 {
#[cfg(feature = "bin")]
@@ -752,7 +742,7 @@ mod test {
None
};
}
- use crate::block::all::*;
+ use crate::block::*;
let mut s = Schematic::new(3, 3);
s.put(0, 0, &DISTRIBUTOR)
.put(0, 1, &JUNCTION)
@@ -768,10 +758,7 @@ mod test {
pair!(2, 0, ROUTER);
pair!( );
];
- let reg = crate::block::build_registry();
- let mut s = SchematicSerializer(&reg);
-
- let s = s.deserialize_base64("bXNjaAF4nDXKywqAIBQA0fFRBH1itDC7C8E01IT+vgia1VkMFmOwyR3C0N0VG/Mu1ZdwtpATMEa3SazoZdVMPqcudy7/DJovpV4peAAt0xF6").unwrap();
+ let s = Schematic::deserialize_base64("bXNjaAF4nDXKywqAIBQA0fFRBH1itDC7C8E01IT+vgia1VkMFmOwyR3C0N0VG/Mu1ZdwtpATMEa3SazoZdVMPqcudy7/DJovpV4peAAt0xF6").unwrap();
let mut it = s.block_iter();
test_iter![it,
pair!(0, 0, CONVEYOR);