mindustry logic execution, map- and schematic- parsing and rendering
Diffstat (limited to 'src/item/storage.rs')
-rw-r--r--src/item/storage.rs729
1 files changed, 356 insertions, 373 deletions
diff --git a/src/item/storage.rs b/src/item/storage.rs
index 5f57b75..fd5be32 100644
--- a/src/item/storage.rs
+++ b/src/item/storage.rs
@@ -6,405 +6,388 @@ use std::slice;
use crate::item;
#[derive(Clone, Debug, Eq)]
-pub struct Storage
-{
- base: Vec<u32>,
- total: u64,
+pub struct Storage {
+ base: Vec<u32>,
+ total: u64,
}
-impl Storage
-{
- pub const fn new() -> Self
- {
- Self{base: Vec::new(), total: 0}
- }
-
- pub fn is_empty(&self) -> bool
- {
- self.total == 0
- }
-
- pub fn get_total(&self) -> u64
- {
- self.total
- }
-
- pub fn get(&self, ty: item::Type) -> u32
- {
- match self.base.get(u16::from(ty) as usize)
- {
- None => 0,
- Some(cnt) => *cnt,
- }
- }
-
- pub fn set(&mut self, ty: item::Type, count: u32) -> u32
- {
- let idx = u16::from(ty) as usize;
- match self.base.get_mut(idx)
- {
- None =>
- {
- self.base.resize(idx + 1, 0);
- self.base[idx] = count;
- self.total += count as u64;
- 0
- },
- Some(curr) =>
- {
- let prev = *curr;
- self.total = self.total - prev as u64 + count as u64;
- *curr = count;
- prev
- },
- }
- }
-
- pub fn add(&mut self, ty: item::Type, add: u32, max: u32) -> (u32, u32)
- {
- let idx = u16::from(ty) as usize;
- match self.base.get_mut(idx)
- {
- None =>
- {
- let actual = add.min(max);
- self.base.resize(idx + 1, 0);
- self.base[idx] = actual;
- self.total += add as u64;
- (actual, actual)
- }
- Some(curr) =>
- {
- if *curr < max
- {
- let actual = add.min(max - *curr);
- *curr += actual;
- self.total += actual as u64;
- (actual, *curr)
- }
- else {(0, *curr)}
- },
- }
- }
-
- pub fn try_add(&mut self, ty: item::Type, add: u32, max: u32) -> Result<(u32, u32), TryAddError>
- {
- let idx = u16::from(ty) as usize;
- match self.base.get_mut(idx)
- {
- None =>
- {
- if add <= max
- {
- self.base.resize(idx + 1, 0);
- self.base[idx] = add;
- self.total += add as u64;
- Ok((add, add))
- }
- else {Err(TryAddError{ty, have: 0, add, max})}
- },
- Some(curr) =>
- {
- if *curr <= max && max - *curr <= add
- {
- *curr += add;
- self.total += add as u64;
- Ok((add, *curr))
- }
- else {Err(TryAddError{ty, have: *curr, add, max})}
- },
- }
- }
-
- pub fn sub(&mut self, ty: item::Type, sub: u32, min: u32) -> (u32, u32)
- {
- match self.base.get_mut(u16::from(ty) as usize)
- {
- None => (0, 0),
- Some(curr) =>
- {
- if *curr > min
- {
- let actual = sub.min(*curr - min);
- *curr -= actual;
- self.total -= actual as u64;
- (actual, *curr)
- }
- else {(0, *curr)}
- },
- }
- }
-
- pub fn try_sub(&mut self, ty: item::Type, sub: u32, min: u32) -> Result<(u32, u32), TrySubError>
- {
- let idx = u16::from(ty) as usize;
- match self.base.get_mut(idx)
- {
- None => Err(TrySubError{ty, have: 0, sub, min}),
- Some(curr) =>
- {
- if *curr >= min && *curr - min >= sub
- {
- *curr -= sub;
- self.total -= sub as u64;
- Ok((sub, *curr))
- }
- else {Err(TrySubError{ty, have: *curr, sub, min})}
- },
- }
- }
-
- pub fn add_all(&mut self, other: &Storage, max_each: u32) -> (u64, u64)
- {
- let mut added = 0u64;
- if max_each > 0 && other.get_total() > 0
- {
- let mut iter = other.base.iter().enumerate();
- // resize our vector only once and if necessary
- let (last, add_last) = iter.rfind(|(_, n)| **n != 0).unwrap();
- if self.base.len() <= last
- {
- self.base.resize(last + 1, 0);
- }
- // process items by increasing ID
- for (idx, add) in iter
- {
- let curr = self.base[idx];
- if curr < max_each
- {
- let actual = (*add).min(max_each - curr);
- self.base[idx] += actual;
- added += actual as u64;
- }
- }
- // process the final element (which we've retrieved first)
- let curr = self.base[last];
- if curr < max_each
- {
- let actual = (*add_last).min(max_each - curr);
- self.base[last] += actual;
- added += actual as u64;
- }
- // update total
- self.total += added;
- }
- (added, self.total)
- }
-
- pub fn pull_all(&mut self, other: &mut Storage, max_each: u32) -> (u64, u64, u64)
- {
- let mut added = 0u64;
- if max_each > 0 && other.get_total() > 0
- {
- let mut iter = other.base.iter_mut().enumerate();
- // resize our vector only once and if necessary
- let (last, add_last) = iter.rfind(|(_, n)| **n != 0).unwrap();
- if self.base.len() <= last
- {
- self.base.resize(last + 1, 0);
- }
- // process items by increasing ID
- for (idx, add) in iter
- {
- let curr = self.base[idx];
- if curr < max_each
- {
- let actual = (*add).min(max_each - curr);
- self.base[idx] += actual;
- *add -= actual;
- added += actual as u64;
- }
- }
- // process the final element (which we've retrieved first)
- let curr = self.base[last];
- if curr < max_each
- {
- let actual = (*add_last).min(max_each - curr);
- self.base[last] += actual;
- *add_last -= actual;
- added += actual as u64;
- }
- // update totals
- self.total += added;
- other.total -= added;
- }
- (added, self.total, other.total)
- }
-
- pub fn sub_all(&mut self, other: &Storage, min_each: u32) -> (u64, u64)
- {
- let mut subbed = 0u64;
- if self.get_total() > 0 && other.get_total() > 0
- {
- // no need for resizing, we only remove
- // process items by increasing ID
- for (idx, sub) in other.base.iter().enumerate()
- {
- if let Some(curr) = self.base.get(idx)
- {
- if *curr > min_each
- {
- let actual = (*sub).min(*curr - min_each);
- self.base[idx] -= actual;
- subbed += actual as u64;
- }
- }
- else {break;}
- }
- // update total
- self.total -= subbed;
- }
- (subbed, self.total)
- }
-
- pub fn diff_all(&mut self, other: &mut Storage, min_each: u32) -> (u64, u64, u64)
- {
- let mut subbed = 0u64;
- if self.get_total() > 0 && other.get_total() > 0
- {
- // no need for resizing, we only remove
- // consider only indexes present in both
- let end = self.base.len().min(other.base.len());
- let lhs = &mut self.base[..end];
- let rhs = &mut other.base[..end];
- // process items by increasing ID
- for (l, r) in lhs.into_iter().zip(rhs)
- {
- if *l > min_each && *r > min_each
- {
- let actual = (*l - min_each).min(*r - min_each);
- *l -= actual;
- *r -= actual;
- subbed -= actual as u64;
- }
- }
- // update totals
- self.total -= subbed;
- other.total -= subbed;
- }
- (subbed, self.total, other.total)
- }
-
- pub fn iter<'s>(&'s self) -> Iter<'s>
- {
- Iter{base: self.base.iter().enumerate(), all: true}
- }
-
- pub fn iter_nonzero<'s>(&'s self) -> Iter<'s>
- {
- Iter{base: self.base.iter().enumerate(), all: false}
- }
-
- pub fn clear(&mut self)
- {
- self.base.clear()
- }
+impl Storage {
+ pub const fn new() -> Self {
+ Self {
+ base: Vec::new(),
+ total: 0,
+ }
+ }
+
+ pub fn is_empty(&self) -> bool {
+ self.total == 0
+ }
+
+ pub fn get_total(&self) -> u64 {
+ self.total
+ }
+
+ pub fn get(&self, ty: item::Type) -> u32 {
+ match self.base.get(u16::from(ty) as usize) {
+ None => 0,
+ Some(cnt) => *cnt,
+ }
+ }
+
+ pub fn set(&mut self, ty: item::Type, count: u32) -> u32 {
+ let idx = u16::from(ty) as usize;
+ match self.base.get_mut(idx) {
+ None => {
+ self.base.resize(idx + 1, 0);
+ self.base[idx] = count;
+ self.total += count as u64;
+ 0
+ }
+ Some(curr) => {
+ let prev = *curr;
+ self.total = self.total - prev as u64 + count as u64;
+ *curr = count;
+ prev
+ }
+ }
+ }
+
+ pub fn add(&mut self, ty: item::Type, add: u32, max: u32) -> (u32, u32) {
+ let idx = u16::from(ty) as usize;
+ match self.base.get_mut(idx) {
+ None => {
+ let actual = add.min(max);
+ self.base.resize(idx + 1, 0);
+ self.base[idx] = actual;
+ self.total += add as u64;
+ (actual, actual)
+ }
+ Some(curr) => {
+ if *curr < max {
+ let actual = add.min(max - *curr);
+ *curr += actual;
+ self.total += actual as u64;
+ (actual, *curr)
+ } else {
+ (0, *curr)
+ }
+ }
+ }
+ }
+
+ pub fn try_add(
+ &mut self,
+ ty: item::Type,
+ add: u32,
+ max: u32,
+ ) -> Result<(u32, u32), TryAddError> {
+ let idx = u16::from(ty) as usize;
+ match self.base.get_mut(idx) {
+ None => {
+ if add <= max {
+ self.base.resize(idx + 1, 0);
+ self.base[idx] = add;
+ self.total += add as u64;
+ Ok((add, add))
+ } else {
+ Err(TryAddError {
+ ty,
+ have: 0,
+ add,
+ max,
+ })
+ }
+ }
+ Some(curr) => {
+ if *curr <= max && max - *curr <= add {
+ *curr += add;
+ self.total += add as u64;
+ Ok((add, *curr))
+ } else {
+ Err(TryAddError {
+ ty,
+ have: *curr,
+ add,
+ max,
+ })
+ }
+ }
+ }
+ }
+
+ pub fn sub(&mut self, ty: item::Type, sub: u32, min: u32) -> (u32, u32) {
+ match self.base.get_mut(u16::from(ty) as usize) {
+ None => (0, 0),
+ Some(curr) => {
+ if *curr > min {
+ let actual = sub.min(*curr - min);
+ *curr -= actual;
+ self.total -= actual as u64;
+ (actual, *curr)
+ } else {
+ (0, *curr)
+ }
+ }
+ }
+ }
+
+ pub fn try_sub(
+ &mut self,
+ ty: item::Type,
+ sub: u32,
+ min: u32,
+ ) -> Result<(u32, u32), TrySubError> {
+ let idx = u16::from(ty) as usize;
+ match self.base.get_mut(idx) {
+ None => Err(TrySubError {
+ ty,
+ have: 0,
+ sub,
+ min,
+ }),
+ Some(curr) => {
+ if *curr >= min && *curr - min >= sub {
+ *curr -= sub;
+ self.total -= sub as u64;
+ Ok((sub, *curr))
+ } else {
+ Err(TrySubError {
+ ty,
+ have: *curr,
+ sub,
+ min,
+ })
+ }
+ }
+ }
+ }
+
+ pub fn add_all(&mut self, other: &Storage, max_each: u32) -> (u64, u64) {
+ let mut added = 0u64;
+ if max_each > 0 && other.get_total() > 0 {
+ let mut iter = other.base.iter().enumerate();
+ // resize our vector only once and if necessary
+ let (last, add_last) = iter.rfind(|(_, n)| **n != 0).unwrap();
+ if self.base.len() <= last {
+ self.base.resize(last + 1, 0);
+ }
+ // process items by increasing ID
+ for (idx, add) in iter {
+ let curr = self.base[idx];
+ if curr < max_each {
+ let actual = (*add).min(max_each - curr);
+ self.base[idx] += actual;
+ added += actual as u64;
+ }
+ }
+ // process the final element (which we've retrieved first)
+ let curr = self.base[last];
+ if curr < max_each {
+ let actual = (*add_last).min(max_each - curr);
+ self.base[last] += actual;
+ added += actual as u64;
+ }
+ // update total
+ self.total += added;
+ }
+ (added, self.total)
+ }
+
+ pub fn pull_all(&mut self, other: &mut Storage, max_each: u32) -> (u64, u64, u64) {
+ let mut added = 0u64;
+ if max_each > 0 && other.get_total() > 0 {
+ let mut iter = other.base.iter_mut().enumerate();
+ // resize our vector only once and if necessary
+ let (last, add_last) = iter.rfind(|(_, n)| **n != 0).unwrap();
+ if self.base.len() <= last {
+ self.base.resize(last + 1, 0);
+ }
+ // process items by increasing ID
+ for (idx, add) in iter {
+ let curr = self.base[idx];
+ if curr < max_each {
+ let actual = (*add).min(max_each - curr);
+ self.base[idx] += actual;
+ *add -= actual;
+ added += actual as u64;
+ }
+ }
+ // process the final element (which we've retrieved first)
+ let curr = self.base[last];
+ if curr < max_each {
+ let actual = (*add_last).min(max_each - curr);
+ self.base[last] += actual;
+ *add_last -= actual;
+ added += actual as u64;
+ }
+ // update totals
+ self.total += added;
+ other.total -= added;
+ }
+ (added, self.total, other.total)
+ }
+
+ pub fn sub_all(&mut self, other: &Storage, min_each: u32) -> (u64, u64) {
+ let mut subbed = 0u64;
+ if self.get_total() > 0 && other.get_total() > 0 {
+ // no need for resizing, we only remove
+ // process items by increasing ID
+ for (idx, sub) in other.base.iter().enumerate() {
+ if let Some(curr) = self.base.get(idx) {
+ if *curr > min_each {
+ let actual = (*sub).min(*curr - min_each);
+ self.base[idx] -= actual;
+ subbed += actual as u64;
+ }
+ } else {
+ break;
+ }
+ }
+ // update total
+ self.total -= subbed;
+ }
+ (subbed, self.total)
+ }
+
+ pub fn diff_all(&mut self, other: &mut Storage, min_each: u32) -> (u64, u64, u64) {
+ let mut subbed = 0u64;
+ if self.get_total() > 0 && other.get_total() > 0 {
+ // no need for resizing, we only remove
+ // consider only indexes present in both
+ let end = self.base.len().min(other.base.len());
+ let lhs = &mut self.base[..end];
+ let rhs = &mut other.base[..end];
+ // process items by increasing ID
+ for (l, r) in lhs.into_iter().zip(rhs) {
+ if *l > min_each && *r > min_each {
+ let actual = (*l - min_each).min(*r - min_each);
+ *l -= actual;
+ *r -= actual;
+ subbed -= actual as u64;
+ }
+ }
+ // update totals
+ self.total -= subbed;
+ other.total -= subbed;
+ }
+ (subbed, self.total, other.total)
+ }
+
+ pub fn iter<'s>(&'s self) -> Iter<'s> {
+ Iter {
+ base: self.base.iter().enumerate(),
+ all: true,
+ }
+ }
+
+ pub fn iter_nonzero<'s>(&'s self) -> Iter<'s> {
+ Iter {
+ base: self.base.iter().enumerate(),
+ all: false,
+ }
+ }
+
+ pub fn clear(&mut self) {
+ self.base.clear()
+ }
}
// manual because padding with zeros doesn't affect equality
-impl PartialEq for Storage
-{
- fn eq(&self, other: &Self) -> bool
- {
- let mut li = self.base.iter().fuse();
- let mut ri = other.base.iter().fuse();
- loop
- {
- match (li.next(), ri.next())
- {
- (None, None) => return true,
- (l, r) =>
- {
- if l.unwrap_or(&0) != r.unwrap_or(&0) {return false;}
- },
- }
- }
- }
+impl PartialEq for Storage {
+ fn eq(&self, other: &Self) -> bool {
+ let mut li = self.base.iter().fuse();
+ let mut ri = other.base.iter().fuse();
+ loop {
+ match (li.next(), ri.next()) {
+ (None, None) => return true,
+ (l, r) => {
+ if l.unwrap_or(&0) != r.unwrap_or(&0) {
+ return false;
+ }
+ }
+ }
+ }
+ }
}
-impl fmt::Display for Storage
-{
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
- {
- let mut first = true;
- for (ty, cnt) in self.iter_nonzero()
- {
- if first {first = false;}
- else {f.write_str(", ")?;}
- write!(f, "{cnt} {ty}")?;
- }
- Ok(())
- }
+impl fmt::Display for Storage {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let mut first = true;
+ for (ty, cnt) in self.iter_nonzero() {
+ if first {
+ first = false;
+ } else {
+ f.write_str(", ")?;
+ }
+ write!(f, "{cnt} {ty}")?;
+ }
+ Ok(())
+ }
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
-pub struct TryAddError
-{
- pub ty: item::Type,
- pub have: u32,
- pub add: u32,
- pub max: u32
+pub struct TryAddError {
+ pub ty: item::Type,
+ pub have: u32,
+ pub add: u32,
+ pub max: u32,
}
-impl fmt::Display for TryAddError
-{
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
- {
- write!(f, "adding {} {:?} to current {} would exceed {}", self.add, self.ty, self.have, self.max)
- }
+impl fmt::Display for TryAddError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(
+ f,
+ "adding {} {:?} to current {} would exceed {}",
+ self.add, self.ty, self.have, self.max
+ )
+ }
}
impl Error for TryAddError {}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
-pub struct TrySubError
-{
- pub ty: item::Type,
- pub have: u32,
- pub sub: u32,
- pub min: u32
+pub struct TrySubError {
+ pub ty: item::Type,
+ pub have: u32,
+ pub sub: u32,
+ pub min: u32,
}
-impl fmt::Display for TrySubError
-{
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
- {
- write!(f, "removing {} {:?} from current {} would drop below {}", self.sub, self.ty, self.have, self.min)
- }
+impl fmt::Display for TrySubError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(
+ f,
+ "removing {} {:?} from current {} would drop below {}",
+ self.sub, self.ty, self.have, self.min
+ )
+ }
}
impl Error for TrySubError {}
#[derive(Clone, Debug)]
-pub struct Iter<'l>
-{
- base: Enumerate<slice::Iter<'l, u32>>,
- all: bool,
+pub struct Iter<'l> {
+ base: Enumerate<slice::Iter<'l, u32>>,
+ all: bool,
}
-impl<'l> Iterator for Iter<'l>
-{
- type Item = (item::Type, u32);
-
- fn next(&mut self) -> Option<Self::Item>
- {
- while let Some((idx, cnt)) = self.base.next()
- {
- if *cnt > 0 || self.all
- {
- if let Ok(ty) = item::Type::try_from(idx as u16)
- {
- return Some((ty, *cnt));
- }
- }
- }
- None
- }
-
- fn size_hint(&self) -> (usize, Option<usize>)
- {
- (0, self.base.size_hint().1)
- }
+impl<'l> Iterator for Iter<'l> {
+ type Item = (item::Type, u32);
+
+ fn next(&mut self) -> Option<Self::Item> {
+ while let Some((idx, cnt)) = self.base.next() {
+ if *cnt > 0 || self.all {
+ if let Ok(ty) = item::Type::try_from(idx as u16) {
+ return Some((ty, *cnt));
+ }
+ }
+ }
+ None
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (0, self.base.size_hint().1)
+ }
}
impl<'l> FusedIterator for Iter<'l> where Enumerate<slice::Iter<'l, u32>>: FusedIterator {}