mindustry logic execution, map- and schematic- parsing and rendering
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
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}
	}
}