Browse Source

Merge branch 'master' of ssh://gitgreen/david/rmmo

Apollo 1 month ago
parent
commit
95cdee485a
6 changed files with 214 additions and 150 deletions
  1. 1 0
      .gitignore
  2. 98 85
      src/chunk.rs
  3. 2 2
      src/lib.rs
  4. 49 11
      src/main.rs
  5. 1 1
      src/tile.rs
  6. 63 51
      src/tile_index.rs

+ 1 - 0
.gitignore

@@ -1,2 +1,3 @@
 /target
 /data
+*.json

+ 98 - 85
src/chunk.rs

@@ -1,116 +1,129 @@
-use crate::Tile;
-use std::ops::{Index, IndexMut};
+use std::{cmp::Ordering::Greater, fmt::{Debug, Display}, ops::{Index, IndexMut}};
+use point::Point;
+use serde::{Deserialize, Serialize};
 
-struct ChunkRow {
-    pub row: [Tile; 32],
-    pub empty: bool
+#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
+pub struct Chunk {
+    tiles: Vec<u64>
 }
 
-impl ChunkRow {
-    pub fn rescan_empty(&mut self) {
-        let mut now_empty: bool = true;
-        for i in 1..=32_usize {
-            if self[i].is_visible() {
-                now_empty = false;
-            }
-        }
-        if now_empty {
-            self.empty = true;
-        } else {
-            self.empty = false;
-        }
-    }
-    pub fn is_empty(&self) -> bool {
-        self.empty
-    }
-    pub fn set(&mut self, idx: usize, t: Tile) -> bool {
-        if idx > 32 {
-            return false;
-        }
-        if t.is_visible() {
-            self.empty = false;
-        } else {
-            let mut now_empty: bool = true;
-            for i in 1..=32_usize {
-                if i == idx {
-                    continue;
-                }
-                if self[i].is_visible() {
-                    now_empty = false;
-                }
-            }
-            if now_empty {
-                self.empty = true;
-            } else {
-                self.empty = false;
-            }
-        }
-        if idx == 0 {
-            if !t.is_visible() {
-                self.empty = true;
-            }
-            self.row.fill(t);
-            return true;
+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.row[idx-1] = t;
-        true
-    }
-    pub fn get(&self, idx: usize) -> Option<Tile> {
-        if idx > 32 || idx == 0 {
-            return None;
-        }
-        Some(self.row[idx-1].clone())
+        &self.tiles[idx as usize]
     }
 }
 
-impl Index<usize> for ChunkRow {
-    type Output = Tile;
-    fn index(&self, index: usize) -> &Self::Output {
-        &self.row[index-1]
+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 IndexMut<usize> for ChunkRow {
-    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
-        &mut self.row[index-1]
+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]
     }
 }
 
-pub struct Chunk {
-    row: [ChunkRow; 32]
+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 rescan_empty(&mut self) {
-        for i in 1..=32_usize {
-            self.row[i-1].rescan_empty();
+    pub fn new() -> Self {
+        let mut s = Self { tiles: Vec::with_capacity(1024) };
+        s.tiles.extend_from_slice(&[0u64; 1024]);
+        s
+    }
+    pub fn new_filled(value: u64) -> Self {
+        let mut s = Self { tiles: Vec::with_capacity(1024) };
+        s.tiles.extend_from_slice(&[value; 1024]);
+        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 is_empty(&self) -> bool {
-        for i in 1..=32_usize {
-            if !self.row[i-1].is_empty() {
-                return false;
-            }
+    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 is_row_empty(&self, idx: usize) -> bool {
-        if idx > 32 || idx == 0 {
+    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;
         }
-        self.row[idx-1].is_empty()
+        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();
+        self.tiles.extend_from_slice(&[0u64; 1024]);
     }
 }
 
-impl Index<(usize, usize)> for Chunk {
-    type Output = Tile;
-    fn index(&self, index: (usize, usize)) -> &Self::Output {
-        &self.row[index.1][index.0]
+impl Default for Chunk {
+    fn default() -> Self {
+        Self::new()
     }
 }
 
-impl IndexMut<(usize, usize)> for Chunk {
-    fn index_mut(&mut self, index: (usize, usize)) -> &mut Self::Output {
-        &mut self.row[index.1][index.0]
+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(())
     }
 }

+ 2 - 2
src/lib.rs

@@ -5,5 +5,5 @@ pub use tile::Tile;
 mod tile_index;
 pub use tile_index::TileIndex;
 
-//mod chunk;
-//pub use chunk::Chunk;
+mod chunk;
+pub use chunk::Chunk;

+ 49 - 11
src/main.rs

@@ -8,19 +8,57 @@ use server::AppServer;
 
 use std::path::PathBuf;
 
-use rmmo::{Tile, TileIndex};
+use point::Point;
+use rmmo::*;
 
-fn main() {
+fn main() -> Result<(), anyhow::Error> {
     println!("Hello, World!");
-    let r = TileIndex::load(PathBuf::from("data/tiles.json"));
-    if let Err(_) = r {
-        let mut ti = TileIndex::new();
-        ti.set(Tile::with_description("player", "@", "lime", "You"));
-        ti.set(Tile::with_description("player-neutral", "@", "silver", "Someone else"));
-        ti.set(Tile::with_description("player-ally", "@", "green", "Someone friendly"));
-        ti.set(Tile::with_description("player-enemy", "@", "red", "Someone mean"));
-        if let Err(err) = ti.save(PathBuf::from("data/tiles.json")) {
-            println!("Oh no, an error: {}", err);
+    let r = TileIndex::load(PathBuf::from("tiles.json"));
+    match r {
+        Ok(index) => {
+            println!("Located {} tiles", index.len());
+            let mut idx: usize = 0;
+            for t in index.clone() {
+                if let Some(desc) = &t.description {
+                    println!("{:3}] \"{:25}\" = '{:1}' {:25} \"{}\"", idx, t.name, t.symbol, t.color, desc);
+                } else {
+                    println!("{:3}] \"{:25}\" = '{:1}' {:25}", idx, t.name, t.symbol, t.color);
+                }
+                idx += 1;
+            }
+            let mut c = Chunk::new();
+            if let Some(floor) = index.lookup_index("ground-stone") {
+                c.fill(&Point::from((3, 3)), &Point::from((4, 4)), floor);
+            }
+            println!("{}", c);
+        }
+        Err(err) => {
+            if err.to_string() != "The system cannot find the file specified. (os error 2)".to_string() {
+                anyhow::bail!(err);
+            }
+            let mut index = TileIndex::new();
+            // index.define(Tile::with_description("", "", "", ""));
+            index.define(Tile::with_description("void", "", "", "You can fly over it, or fall into it"));
+            index.define(Tile::with_description("player", "@", "bright green", "You"));
+            index.define(Tile::with_description("player-neutral", "@", "bright white", "Somebody else"));
+            index.define(Tile::with_description("player-enemy", "@", "bright red", "Somebody else, that's mean"));
+            index.define(Tile::with_description("player-ally", "@", "green", "Somebody else, that's nice"));
+            index.define(Tile::with_description("ground-stone", ".", "white", "A stone path"));
+            index.define(Tile::with_description("ground-grass", ".", "green", "A grassy path"));
+            index.define(Tile::with_description("wall-v-stone", "|", "white", "A stone wall"));
+            index.define(Tile::with_description("wall-h-stone", "-", "white", "A stone wall"));
+            index.define(Tile::with_description("door-c-wood", "+", "brown", "A closed door"));
+            index.define(Tile::with_description("door-o-wood", "-", "brown", "A open door, you can move thru it"));
+            index.define(Tile::with_description("water-shallow", "~", "cyan", "Shallow water, you can wade thru it"));
+            index.define(Tile::with_description("water-deep", "~", "bright blue", "Deep water, you can swim thru it"));
+            index.define(Tile::with_description("gold", "$", "bright yellow", "Gold, a common currency"));
+            index.define(Tile::with_description("gem-blue", "*", "bright cyan", "Sapphire, a rare currency"));
+            index.define(Tile::with_description("gem-red", "*", "red", "Ruby, a rare currency"));
+            index.define(Tile::with_description("gem-green", "*", "bright green", "Emerald, a rare currency"));
+            index.define(Tile::with_description("gem-magenta", "*", "bright magenta", "Amethyst, a rare currency"));
+            index.save(PathBuf::from("tiles.json"))?;
+            println!("Created {} tiles", index.len());
         }
     }
+    Ok(())
 }

+ 1 - 1
src/tile.rs

@@ -30,7 +30,7 @@ impl Tile {
         if self.described() || self.named() {
             return false;
         }
-        self.symbol.is_empty() && self.color.is_empty()
+        self.name.is_empty() && self.symbol.is_empty() && self.color.is_empty()
     }
     pub fn is_visible(&self) -> bool {
         if !self.symbol.is_empty() {

+ 63 - 51
src/tile_index.rs

@@ -1,4 +1,4 @@
-use std::{fs, path::PathBuf};
+use std::{fs, path::PathBuf, iter::Iterator};
 
 use serde::{Deserialize, Serialize};
 
@@ -9,85 +9,97 @@ pub struct TileIndex {
     tiles: Vec<Tile>
 }
 
-impl Default for TileIndex {
-    fn default() -> Self {
-        let mut s = Self{tiles: Vec::with_capacity(1)};
-        s.set(Tile::new("void", "", ""));
-        s
-    }
-}
-
 impl TileIndex {
     pub fn new() -> Self {
-        Self::default()
+        Self { tiles: Vec::new() }
     }
-    pub fn load(path: PathBuf) -> Result<TileIndex, anyhow::Error> {
+    pub fn load(path: PathBuf) -> Result<Self, anyhow::Error> {
         let content = fs::read_to_string(path)?;
-        let ti: TileIndex = serde_json::from_str(&content)?;
-        Ok(ti)
+        let index = serde_json::from_str::<TileIndex>(&content)?;
+        Ok(index)
     }
     pub fn save(&self, path: PathBuf) -> Result<(), anyhow::Error> {
-        let contents = serde_json::to_string_pretty(self)?;
-        let p = path.as_path().to_string_lossy().to_string();
-        let p2 = PathBuf::from(p.strip_suffix(path.file_name().unwrap_or_default().to_str().unwrap_or_default()).unwrap_or_default());
-        if !p2.exists() {
-            fs::create_dir_all(p2)?;
-        }
-        fs::write(path, contents)?;
+        let content = serde_json::to_string_pretty(self)?;
+        fs::write(path, content)?;
         Ok(())
     }
-    pub fn has(&self, name: &str) -> bool {
-        for t in self.tiles.iter() {
-            if t.name == name {
-                return true;
-            }
-        }
-        false
-    }
-    pub fn has_index(&self, idx: usize) -> bool {
-        idx >= self.tiles.len()
+    pub fn len(&self) -> usize {
+        self.tiles.len()
     }
-    pub fn get(&self, name: &str) -> Option<&Tile> {
+    pub fn lookup_index(&self, name: &str) -> Option<u64> {
+        let mut idx: u64 = 0;
         for t in self.tiles.iter() {
-            if t.name == name {
-                return Some(t);
+            if t.name == name.to_string() {
+                return Some(idx);
             }
+            idx += 1;
         }
         None
     }
-    pub fn lookup_index(&self, name: &str) -> Option<usize> {
-        let mut i: usize = 0;
+    pub fn get_name(&self, name: &str) -> Option<&Tile> {
         for t in self.tiles.iter() {
-            if t.name == name {
-                return Some(i);
+            if t.name == name.to_string() {
+                return Some(t);
             }
-            i += 1;
         }
         None
     }
-    pub fn get_index(&self, idx: usize) -> Option<&Tile> {
-        let mut i: usize = 0;
-        for t in self.tiles.iter() {
-            if i == idx {
-                return Some(t);
-            }
-            i += 1;
+    pub fn get_index(&self, index: u64) -> Option<&Tile> {
+        if index >= self.tiles.len() as u64 {
+            return None;
         }
-        None
+        Some(&self.tiles[index as usize])
     }
     pub fn set(&mut self, t: Tile) -> usize {
         if let Some(idx) = self.lookup_index(&t.name) {
-            self.tiles[idx] = t;
-            return idx;
+            self.tiles[idx as usize] = t;
+            return idx as usize;
         }
         self.tiles.push(t);
         self.tiles.len()
     }
-    pub fn set_index(&mut self, idx: usize, t: Tile) -> bool {
-        if !self.has_index(idx) {
+    pub fn define(&mut self, t: Tile) -> bool {
+        if let Some(_idx) = self.lookup_index(&t.name) {
             return false;
         }
-        self.tiles[idx] = t;
+        self.tiles.push(t);
         true
     }
 }
+
+impl Default for TileIndex {
+    fn default() -> Self {
+        Self::new()
+    }
+}
+
+pub struct TileIndexIter {
+    tile_index: TileIndex,
+    index: u64,
+}
+
+impl TileIndexIter {
+    pub fn new(index: TileIndex) -> Self {
+        Self { tile_index: index, index: 0 }
+    }
+}
+
+impl Iterator for TileIndexIter {
+    type Item = Tile;
+    fn next(&mut self) -> Option<Self::Item> {
+        self.index += 1;
+        if let Some(t) = self.tile_index.get_index(self.index-1) {
+            Some(t.clone())
+        } else {
+            None
+        }
+    }
+}
+
+impl IntoIterator for TileIndex {
+    type IntoIter = TileIndexIter;
+    type Item = Tile;
+    fn into_iter(self) -> Self::IntoIter {
+        TileIndexIter::new(self)
+    }
+}