aboutsummaryrefslogtreecommitdiff
path: root/src/world/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/world/mod.rs')
-rw-r--r--src/world/mod.rs113
1 files changed, 113 insertions, 0 deletions
diff --git a/src/world/mod.rs b/src/world/mod.rs
new file mode 100644
index 0000000..047ca5c
--- /dev/null
+++ b/src/world/mod.rs
@@ -0,0 +1,113 @@
+//! The world contains all items of a session and the ways to manipulate them.
+//! Generally speaking, manipulation will be done on the server side and then
+//! the changes are sent to the client.
+
+pub mod component;
+pub mod icon;
+pub mod room;
+pub mod wall;
+
+pub use component::*;
+pub use icon::*;
+pub use room::*;
+pub use wall::*;
+
+use crate::stable_vec::StableVec;
+use ron::de::from_reader;
+use ron::ser::{to_string_pretty, PrettyConfig};
+use serde::{Deserialize, Serialize};
+use std::fs::File;
+use std::io::{self, Write};
+use std::path::Path;
+
+/// Main structure that contains all information about a world necessary to argue
+/// about structures in it. It can be persistified and loaded from disk, as well
+/// as sent over the network. Everything in it is assigned an id to make it easy
+/// to argue about a specific item. IDs may only be assigned by the server, not
+/// the client, since otherwise multiple clients may try to create the same item.
+#[derive(Debug, Serialize, Deserialize)]
+pub struct World {
+ rooms: StableVec<Room>,
+ walls: StableVec<Wall>,
+ icons: StableVec<Icon>,
+ used_ids: StableVec<()>,
+}
+
+impl World {
+ /// Load the world data from a file. Fails if the file does not exist or
+ /// cannot be correctly parsed.
+ pub fn load_from_file<P: AsRef<Path>>(path: P) -> io::Result<Self> {
+ let file = File::open(&path)?;
+ let data: Self = match from_reader(file) {
+ Ok(data) => data,
+ Err(err) => {
+ return Err(io::Error::new(io::ErrorKind::InvalidData, err));
+ }
+ };
+
+ Ok(data)
+ }
+
+ /// Write the world data to the file located at `path`. If the file already
+ /// exists, it will be overwritten. If the write fails, an IO-Error is returned.
+ pub fn write_to_file<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
+ let mut file = File::create(&path)?;
+
+ let pretty_conf = PrettyConfig::new()
+ .with_depth_limit(4)
+ .with_decimal_floats(true)
+ .with_separate_tuple_members(true)
+ .with_indentor("\t".to_owned());
+ let string = match to_string_pretty(&self, pretty_conf) {
+ Ok(string) => string,
+ Err(err) => {
+ return Err(io::Error::new(io::ErrorKind::InvalidInput, err));
+ }
+ };
+
+ file.write_all(&string.as_bytes())
+ }
+
+ /// Add a room to the world. Currently, holes are not supported in the polygon, but this might
+ /// change later.
+ pub fn push_room(&mut self, room: Room) -> usize {
+ let id = self.used_ids.insert_anywhere(());
+ self.rooms
+ .try_insert(id, room)
+ .expect("Id vecs out of sync");
+ id
+ }
+
+ /// Add a wall to the world.
+ pub fn push_wall(&mut self, wall: Wall) -> usize {
+ let id = self.used_ids.insert_anywhere(());
+ self.walls
+ .try_insert(id, wall)
+ .expect("Id vecs out of sync");
+ id
+ }
+
+ /// Add an icon to the world.
+ pub fn push_icon(&mut self, icon: Icon) -> usize {
+ let id = self.used_ids.insert_anywhere(());
+ self.icons
+ .try_insert(id, icon)
+ .expect("Id vecs out of sync");
+ id
+ }
+
+ /// Get all icons of the world.
+ pub fn icons(&self) -> &StableVec<Icon> {
+ &self.icons
+ }
+
+ /// Get all rooms of the world.
+ pub fn rooms(&self) -> &StableVec<Room> {
+ &self.rooms
+ }
+
+ /// Get all walls of the world.
+ pub fn walls(&self) -> &StableVec<Wall> {
+ &self.walls
+ }
+}