mindustry logic execution, map- and schematic- parsing and rendering
Diffstat (limited to 'src/data/schematic.rs')
| -rw-r--r-- | src/data/schematic.rs | 91 |
1 files changed, 49 insertions, 42 deletions
diff --git a/src/data/schematic.rs b/src/data/schematic.rs index 6331606..a3b104d 100644 --- a/src/data/schematic.rs +++ b/src/data/schematic.rs @@ -29,14 +29,17 @@ pub struct Placement<'l> { } impl<'l> Placement<'l> { + #[must_use] pub fn get_pos(&self) -> GridPos { self.pos } + #[must_use] pub fn get_block(&self) -> &'l Block { self.block } + #[must_use] pub fn get_state(&self) -> Option<&dyn Any> { match self.state { None => None, @@ -59,6 +62,7 @@ impl<'l> Placement<'l> { Ok(std::mem::replace(&mut self.state, state)) } + #[must_use] pub fn get_rotation(&self) -> Rotation { self.rot } @@ -93,6 +97,7 @@ pub struct Schematic<'l> { } impl<'l> Schematic<'l> { + #[must_use] pub fn new(width: u16, height: u16) -> Self { match Self::try_new(width, height) { Ok(s) => s, @@ -121,14 +126,17 @@ impl<'l> Schematic<'l> { }) } + #[must_use] pub fn get_width(&self) -> u16 { self.width } + #[must_use] pub fn get_height(&self) -> u16 { self.height } + #[must_use] pub fn get_tags(&self) -> &HashMap<String, String> { &self.tags } @@ -137,16 +145,19 @@ impl<'l> Schematic<'l> { &mut self.tags } + #[must_use] pub fn is_empty(&self) -> bool { self.blocks.is_empty() } + #[must_use] pub fn get_block_count(&self) -> usize { self.blocks.len() } + #[must_use] pub fn is_region_empty(&self, x: u16, y: u16, w: u16, h: u16) -> bool { - if self.blocks.len() == 0 { + if self.blocks.is_empty() { return true; } if x >= self.width || y >= self.height || w == 0 || h == 0 { @@ -188,7 +199,7 @@ impl<'l> Schematic<'l> { h: self.height, }); } - if self.blocks.len() == 0 { + if self.blocks.is_empty() { return Ok(None); } let pos = (x as usize) + (y as usize) * (self.width as usize); @@ -207,7 +218,7 @@ impl<'l> Schematic<'l> { h: self.height, }); } - if self.blocks.len() == 0 { + if self.blocks.is_empty() { return Ok(None); } let pos = (x as usize) + (y as usize) * (self.width as usize); @@ -240,12 +251,12 @@ impl<'l> Schematic<'l> { } fn fill_lookup(&mut self, x: usize, y: usize, sz: usize, val: Option<usize>) { - if self.lookup.len() == 0 { + if self.lookup.is_empty() { self.lookup .resize((self.width as usize) * (self.height as usize), None); } if sz > 1 { - let off = ((sz - 1) / 2) as usize; + let off = (sz - 1) / 2; let (x0, y0) = (x - off, y - off); for dy in 0..sz { for dx in 0..sz { @@ -265,7 +276,7 @@ impl<'l> Schematic<'l> { data: DynData, rot: Rotation, ) -> Result<&Placement<'l>, PlaceError> { - let sz = block.get_size() as u16; + let sz = u16::from(block.get_size()); let off = (sz - 1) / 2; if x < off || y < off { return Err(PlaceError::Bounds { @@ -310,7 +321,7 @@ impl<'l> Schematic<'l> { rot: Rotation, collect: bool, ) -> Result<Option<Vec<Placement<'l>>>, PlaceError> { - let sz = block.get_size() as u16; + let sz = u16::from(block.get_size()); let off = (sz - 1) / 2; if x < off || y < off { return Err(PlaceError::Bounds { @@ -403,20 +414,20 @@ impl<'l> Schematic<'l> { h: self.height, }); } - if self.blocks.len() > 0 { + if self.blocks.is_empty() { + Ok(None) + } else { let pos = (x as usize) + (y as usize) * (self.width as usize); match self.lookup[pos] { None => Ok(None), Some(idx) => Ok(Some(self.swap_remove(idx))), } - } else { - Ok(None) } } fn rebuild_lookup(&mut self) { self.lookup.clear(); - if self.blocks.len() > 0 { + if !self.blocks.is_empty() { self.lookup .resize((self.width as usize) * (self.height as usize), None); for (i, curr) in self.blocks.iter().enumerate() { @@ -438,9 +449,9 @@ impl<'l> Schematic<'l> { pub fn mirror(&mut self, horizontally: bool, vertically: bool) { if !self.blocks.is_empty() && (horizontally || vertically) { - for curr in self.blocks.iter_mut() { + for curr in &mut self.blocks { // because position is the bottom left of the center (which changes during mirroring) - let shift = (curr.block.get_size() as u16 - 1) % 2; + let shift = (u16::from(curr.block.get_size()) - 1) % 2; if horizontally { curr.pos.0 = self.width - 1 - curr.pos.0 - shift; } @@ -465,11 +476,11 @@ impl<'l> Schematic<'l> { self.width = h; self.height = w; if !self.blocks.is_empty() { - for curr in self.blocks.iter_mut() { + for curr in &mut self.blocks { let x = curr.pos.0; let y = curr.pos.1; // because position is the bottom left of the center (which changes during rotation) - let shift = (curr.block.get_size() as u16 - 1) % 2; + let shift = (u16::from(curr.block.get_size()) - 1) % 2; if clockwise { curr.pos.0 = y; curr.pos.1 = w - 1 - x - shift; @@ -518,8 +529,8 @@ impl<'l> Schematic<'l> { let top_bound = dy + h as i16 - 1; let left_bound = dx; let bottom_bound = dy; - for Placement { pos, block, .. } in self.blocks.iter() { - let sz = block.get_size() as u16; + for Placement { pos, block, .. } in &self.blocks { + let sz = u16::from(block.get_size()); let (x0, y0, x1, y1) = ( pos.0 - (sz - 1) / 2, pos.1 - (sz - 1) / 2, @@ -539,7 +550,7 @@ impl<'l> Schematic<'l> { bottom = bottom_bound as u16 - y0; } } - if left > 0 || top > 0 || left > 0 || bottom > 0 { + if left > 0 || top > 0 || right > 0 || bottom > 0 { return Err(ResizeError::Truncated { right, top, @@ -549,7 +560,7 @@ impl<'l> Schematic<'l> { } self.width = w; self.height = h; - for Placement { pos, .. } in self.blocks.iter_mut() { + for Placement { pos, .. } in &mut self.blocks { pos.0 = (pos.0 as i16 + dx) as u16; pos.1 = (pos.1 as i16 + dy) as u16; } @@ -560,6 +571,7 @@ impl<'l> Schematic<'l> { self.mirror(true, true); } + #[must_use] pub fn pos_iter(&self) -> PosIter { PosIter { x: 0, @@ -573,10 +585,11 @@ impl<'l> Schematic<'l> { self.blocks.iter() } + #[must_use] pub fn compute_total_cost(&self) -> (ItemStorage, bool) { let mut cost = ItemStorage::new(); let mut sandbox = false; - for &Placement { block, .. } in self.blocks.iter() { + for &Placement { block, .. } in &self.blocks { if let Some(curr) = block.get_build_cost() { cost.add_all(curr, u32::MAX); } else { @@ -753,7 +766,7 @@ impl<'l> fmt::Display for Schematic<'l> { // find unique letters for each block, more common blocks pick first let mut name_cnt = HashMap::<&str, u16>::new(); - for p in self.blocks.iter() { + for p in &self.blocks { match name_cnt.entry(p.block.get_name()) { Entry::Occupied(mut e) => *e.get_mut() += 1, Entry::Vacant(e) => { @@ -770,7 +783,7 @@ impl<'l> fmt::Display for Schematic<'l> { 0x70u8, 0x00u8, 0x00u8, 0x40u8, 0x90u8, ]; let mut types = HashMap::<&str, char>::new(); - for &(name, _) in name_cnt.iter() { + for &(name, _) in &name_cnt { let mut found = false; for c in name.chars() { if c > ' ' && c <= '~' { @@ -807,7 +820,9 @@ impl<'l> fmt::Display for Schematic<'l> { } // coordinates start in the bottom left, so y starts at self.height - 1 - if self.blocks.len() > 0 { + if self.blocks.is_empty() { + write!(f, "<empty {} * {}>", self.width, self.height)?; + } else { for y in (0..self.height as usize).rev() { let mut x = 0usize; while x < self.width as usize { @@ -902,8 +917,6 @@ impl<'l> fmt::Display for Schematic<'l> { let v = *types.get(k).unwrap(); write!(f, "\n({v}) {k}")?; } - } else { - write!(f, "<empty {} * {}>", self.width, self.height)?; } Ok(()) } @@ -1007,7 +1020,7 @@ impl<'l> Serializer<Schematic<'l>> for SchematicSerializer<'l> { buff.write_u32(SCHEMATIC_HEADER)?; buff.write_u8(1)?; - let mut rbuff = DataWrite::new(); + 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)?; @@ -1015,20 +1028,17 @@ impl<'l> Serializer<Schematic<'l>> for SchematicSerializer<'l> { return Err(WriteError::TagCount(data.tags.len())); } rbuff.write_u8(data.tags.len() as u8)?; - for (k, v) in data.tags.iter() { + for (k, v) in &data.tags { rbuff.write_utf(k)?; rbuff.write_utf(v)?; } // use string keys here to avoid issues with different block refs with the same name let mut block_map = HashMap::<&str, u32>::new(); let mut block_table = Vec::<&str>::new(); - for curr in data.blocks.iter() { - match block_map.entry(curr.block.get_name()) { - Entry::Vacant(e) => { - e.insert(block_table.len() as u32); - block_table.push(curr.block.get_name()); - } - _ => (), + for curr in &data.blocks { + if let Entry::Vacant(e) = block_map.entry(curr.block.get_name()) { + e.insert(block_table.len() as u32); + block_table.push(curr.block.get_name()); } } if block_table.len() > i8::MAX as usize { @@ -1036,13 +1046,13 @@ impl<'l> Serializer<Schematic<'l>> for SchematicSerializer<'l> { } // else: implies contents are also valid i8 (they're strictly less than the map length) rbuff.write_i8(block_table.len() as i8)?; - for &name in block_table.iter() { + for &name in &block_table { rbuff.write_utf(name)?; } // don't have to check data.blocks.len() because dimensions don't allow exceeding MAX_BLOCKS rbuff.write_i32(data.blocks.len() as i32)?; let mut num = 0; - for curr in data.blocks.iter() { + for curr in &data.blocks { rbuff.write_i8(block_map[curr.block.get_name()] as i8)?; rbuff.write_u32(u32::from(curr.pos))?; let data = match curr.state { @@ -1056,10 +1066,7 @@ impl<'l> Serializer<Schematic<'l>> for SchematicSerializer<'l> { assert_eq!(num, data.blocks.len()); // compress into the provided buffer - let raw = match rbuff.data { - data::WriteBuff::Vec(v) => v, - _ => unreachable!("write buffer not owned"), - }; + let data::WriteBuff::Vec(raw) = rbuff.data else { unreachable!("write buffer not owned") }; let mut comp = Compress::new(Compression::default(), true); // compress the immediate buffer into a temp buffer to copy it to buff? no thanks match buff.data { @@ -1261,11 +1268,11 @@ impl<'l> SchematicSerializer<'l> { } pub fn serialize_base64(&mut self, data: &Schematic<'l>) -> Result<String, W64Error> { - let mut buff = DataWrite::new(); + let mut buff = DataWrite::default(); self.serialize(&mut buff, data)?; let buff = buff.get_written(); // round up because of padding - let required = 4 * (buff.len() / 3 + if buff.len() % 3 != 0 { 1 } else { 0 }); + let required = 4 * (buff.len() / 3 + usize::from(buff.len() % 3 != 0)); let mut text = Vec::<u8>::new(); text.resize(required, 0); let n_out = base64::encode(buff, text.as_mut())?; |