mindustry logic execution, map- and schematic- parsing and rendering
Diffstat (limited to 'src/data/schematic.rs')
-rw-r--r--src/data/schematic.rs119
1 files changed, 119 insertions, 0 deletions
diff --git a/src/data/schematic.rs b/src/data/schematic.rs
new file mode 100644
index 0000000..b52e402
--- /dev/null
+++ b/src/data/schematic.rs
@@ -0,0 +1,119 @@
+use std::collections::HashMap;
+
+use crate::block::{Block, Rotation};
+
+pub const MAX_DIMENSION: u16 = 128;
+pub const MAX_BLOCKS: u32 = 128 * 128;
+
+#[derive(Clone, Copy)]
+struct Storage(&'static Block, Rotation);
+
+#[derive(Clone)]
+pub struct Schematic
+{
+ width: u16,
+ height: u16,
+ tags: HashMap<String, String>,
+ blocks: Vec<Option<Storage>>,
+ block_cnt: u32,
+}
+
+impl Schematic
+{
+ pub fn new(width: u16, height: u16) -> Self
+ {
+ if width > MAX_DIMENSION
+ {
+ panic!("invalid schematic width ({width})");
+ }
+ if height > MAX_DIMENSION
+ {
+ panic!("invalid schematic width ({height})");
+ }
+ let mut tags = HashMap::<String, String>::new();
+ tags.insert("name".to_string(), String::new());
+ tags.insert("description".to_string(), String::new());
+ tags.insert("labels".to_string(), "[]".to_string());
+ Self{width, height, tags, blocks: Vec::new(), block_cnt: 0}
+ }
+
+ pub fn get_width(&self) -> u16
+ {
+ self.width
+ }
+
+ pub fn get_height(&self) -> u16
+ {
+ self.height
+ }
+
+ pub fn get_tags(&self) -> &HashMap<String, String>
+ {
+ &self.tags
+ }
+
+ pub fn get_tags_mut(&mut self) -> &mut HashMap<String, String>
+ {
+ &mut self.tags
+ }
+
+ pub fn get(&self, x: u16, y: u16) -> Option<(&'static Block, Rotation)>
+ {
+ if x >= self.width || y >= self.height
+ {
+ panic!("position {x} / {y} out of bounds ({} / {})", self.width, self.height);
+ }
+ if self.block_cnt == 0 {return None;}
+ let index = (x as usize) + (y as usize) * (self.width as usize);
+ match self.blocks.get(index)
+ {
+ None => None,
+ Some(None) => None,
+ Some(Some(Storage(b, r))) => Some((*b, *r)),
+ }
+ }
+
+ pub fn set(&mut self, x: u16, y: u16, block: &'static Block, rot: Rotation) -> Option<(&'static Block, Rotation)>
+ {
+ if x >= self.width || y >= self.height
+ {
+ panic!("position {x} / {y} out of bounds ({} / {})", self.width, self.height);
+ }
+ if self.blocks.len() == 0
+ {
+ self.blocks.resize_with((self.width as usize) * (self.height as usize), || None);
+ }
+ let index = (x as usize) + (y as usize) * (self.width as usize);
+ match self.blocks[index].replace(Storage(block, rot))
+ {
+ None =>
+ {
+ self.block_cnt += 1;
+ None
+ },
+ Some(s) => Some((s.0, s.1)),
+ }
+ }
+
+ pub fn take(&mut self, x: u16, y: u16) -> Option<(&'static Block, Rotation)>
+ {
+ if x >= self.width || y >= self.height
+ {
+ panic!("position {x} / {y} out of bounds ({} / {})", self.width, self.height);
+ }
+ if self.blocks.len() > 0
+ {
+ let index = (x as usize) + (y as usize) * (self.width as usize);
+ match self.blocks[index].take()
+ {
+ None => None,
+ Some(s) =>
+ {
+ self.block_cnt -= 1;
+ Some((s.0, s.1))
+ },
+ }
+ }
+ else {None}
+ }
+}