|
@@ -0,0 +1,132 @@
|
|
|
|
+use std::{cmp::Ordering::Greater, fmt::{Debug, Display}, ops::{Index, IndexMut}};
|
|
|
|
+use point::Point;
|
|
|
|
+use serde::{Deserialize, Serialize};
|
|
|
|
+
|
|
|
|
+#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
|
|
|
+pub struct Chunk {
|
|
|
|
+ tiles: Vec<u64>
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl Index<Point<u64>> for Chunk {
|
|
|
|
+ type Output = u64;
|
|
|
|
+ fn index(&self, index: Point<u64>) -> &Self::Output {
|
|
|
|
+ let idx = index.distance_value();
|
|
|
|
+ if idx >= 32*32 {
|
|
|
|
+ panic!("index out of bounds");
|
|
|
|
+ }
|
|
|
|
+ &self.tiles[idx as usize]
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl IndexMut<Point<u64>> for Chunk {
|
|
|
|
+ fn index_mut(&mut self, index: Point<u64>) -> &mut Self::Output {
|
|
|
|
+ let idx = index.distance_value();
|
|
|
|
+ if idx >= 32*32 {
|
|
|
|
+ panic!("index out of bounds");
|
|
|
|
+ }
|
|
|
|
+ &mut self.tiles[idx as usize]
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl Index<&Point<u64>> for Chunk {
|
|
|
|
+ type Output = u64;
|
|
|
|
+ fn index(&self, index: &Point<u64>) -> &Self::Output {
|
|
|
|
+ let idx = index.distance_value();
|
|
|
|
+ if idx >= 32*32 {
|
|
|
|
+ panic!("index out of bounds");
|
|
|
|
+ }
|
|
|
|
+ &self.tiles[idx as usize]
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl IndexMut<&Point<u64>> for Chunk {
|
|
|
|
+ fn index_mut(&mut self, index: &Point<u64>) -> &mut Self::Output {
|
|
|
|
+ let idx = index.distance_value();
|
|
|
|
+ if idx >= 32*32 {
|
|
|
|
+ panic!("index out of bounds");
|
|
|
|
+ }
|
|
|
|
+ &mut self.tiles[idx as usize]
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl Chunk {
|
|
|
|
+ pub fn new() -> Self {
|
|
|
|
+ let mut s = Self { tiles: Vec::with_capacity(1024) };
|
|
|
|
+ for _ in 0..1024 {
|
|
|
|
+ s.tiles.push(0);
|
|
|
|
+ }
|
|
|
|
+ s
|
|
|
|
+ }
|
|
|
|
+ pub fn new_filled(value: u64) -> Self {
|
|
|
|
+ let mut s = Self { tiles: Vec::with_capacity(1024) };
|
|
|
|
+ for _ in 0..1024 {
|
|
|
|
+ s.tiles.push(value);
|
|
|
|
+ }
|
|
|
|
+ s
|
|
|
|
+ }
|
|
|
|
+ pub fn get(&self, pos: &Point<u64>) -> Option<&u64> {
|
|
|
|
+ let idx = pos.distance_value();
|
|
|
|
+ if idx >= 32*32 {
|
|
|
|
+ return None;
|
|
|
|
+ }
|
|
|
|
+ self.tiles.get(idx as usize)
|
|
|
|
+ }
|
|
|
|
+ pub fn get_mut(&mut self, pos: &Point<u64>) -> Option<&mut u64> {
|
|
|
|
+ let idx = pos.distance_value();
|
|
|
|
+ if idx >= 32*32 {
|
|
|
|
+ return None;
|
|
|
|
+ }
|
|
|
|
+ self.tiles.get_mut(idx as usize)
|
|
|
|
+ }
|
|
|
|
+ pub fn set(&mut self, pos: &Point<u64>, value: u64) -> bool {
|
|
|
|
+ let idx = pos.distance_value();
|
|
|
|
+ if idx >= 32*32 {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ self.tiles[idx as usize] = value;
|
|
|
|
+ true
|
|
|
|
+ }
|
|
|
|
+ pub fn fill(&mut self, pos1: &Point<u64>, pos2: &Point<u64>, value: u64) -> bool {
|
|
|
|
+ let (corn1, corn2) = match pos1.partial_cmp(pos2).unwrap() {
|
|
|
|
+ Greater => {
|
|
|
|
+ (pos2.distance_value(), pos1.distance_value())
|
|
|
|
+ },
|
|
|
|
+ _ => {
|
|
|
|
+ (pos1.distance_value(), pos2.distance_value())
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ if corn1 >= 32*32 || corn2 >= 32*32 {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ for idx in corn1..corn2 {
|
|
|
|
+ self.tiles[idx as usize] = value;
|
|
|
|
+ }
|
|
|
|
+ true
|
|
|
|
+ }
|
|
|
|
+ pub fn fill_all(&mut self, value: u64) {
|
|
|
|
+ self.tiles.clear();
|
|
|
|
+ self.tiles.extend_from_slice(&[value; 1024]);
|
|
|
|
+ }
|
|
|
|
+ pub fn clear(&mut self) {
|
|
|
|
+ self.tiles.clear();
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl Default for Chunk {
|
|
|
|
+ fn default() -> Self {
|
|
|
|
+ Self::new()
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl Display for Chunk {
|
|
|
|
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
+ for y in 0..32u64 {
|
|
|
|
+ for x in 0..32u64 {
|
|
|
|
+ let idx = (x + y) as usize;
|
|
|
|
+ f.write_str(format!("{}", self.tiles[idx]).as_str())?;
|
|
|
|
+ }
|
|
|
|
+ f.write_str("\r\n")?;
|
|
|
|
+ }
|
|
|
|
+ Ok(())
|
|
|
|
+ }
|
|
|
|
+}
|