From 8d166e628ceb2072e045b9ff6b1dcc1002a34d8e Mon Sep 17 00:00:00 2001 From: Arne Dußin Date: Wed, 3 Feb 2021 23:00:09 +0100 Subject: Add most of the offline functionality back --- src/client/editor.rs | 28 +++++++++++++++++++---- src/client/map/icon_mark.rs | 5 +++++ src/client/map/mod.rs | 29 ++++++++++++++++++------ src/client/map/wall_mark.rs | 6 +++++ src/server/mod.rs | 54 ++++++++++++++++++++++++++++++++++++++++++++- src/world/mod.rs | 50 +++++++++++++++++++++++++++++++++++++++++ 6 files changed, 160 insertions(+), 12 deletions(-) diff --git a/src/client/editor.rs b/src/client/editor.rs index e416339..fb271d4 100644 --- a/src/client/editor.rs +++ b/src/client/editor.rs @@ -168,12 +168,32 @@ impl Editor { fn poll_net(&mut self) { while let Some(cargo) = self.server().next_packet() { match cargo { - Cargo::SetRoom((id, new_room)) => { - if let Some(mark) = self.map.get_room_mut(id) { - mark.set_room(new_room); - } else { + Cargo::SetRoom((id, new_room)) => match self.map.get_room_mut(id) { + Some(mark) => mark.set_room(new_room), + None => { self.map.add_room(id, new_room); } + }, + Cargo::SetIcon((id, new_icon)) => match self.map.get_icon_mut(id) { + Some(mark) => mark.set_icon(new_icon), + None => { + self.map.add_icon(id, new_icon); + } + }, + Cargo::SetWall((id, new_wall)) => match self.map.get_wall_mut(id) { + Some(mark) => mark.set_wall(new_wall), + None => { + self.map.add_wall(id, new_wall); + } + }, + Cargo::ClearAll => self.map.clear(), + Cargo::Remove(id) => { + self.map.remove(id); + } + Cargo::AddMapData(_) => unimplemented!(), + Cargo::UpdateMapData(_) => unimplemented!(), + Cargo::AddIcon(_) | Cargo::AddRoom(_) | Cargo::AddWall(_) => { + error!("Packet is only valid in Client -> Server direction") } other => error!("Unknown packet received: {:?}", other), } diff --git a/src/client/map/icon_mark.rs b/src/client/map/icon_mark.rs index 39fd554..02ed501 100644 --- a/src/client/map/icon_mark.rs +++ b/src/client/map/icon_mark.rs @@ -45,6 +45,11 @@ impl IconMark { textures, } } + + /// Set the inner icon this icon mark is referencing. + pub fn set_icon(&mut self, icon: Icon) { + self.icon = icon; + } } impl Mappable for IconMark { diff --git a/src/client/map/mod.rs b/src/client/map/mod.rs index 9589e59..7a0613c 100644 --- a/src/client/map/mod.rs +++ b/src/client/map/mod.rs @@ -16,7 +16,7 @@ pub use wall_mark::*; use crate::client::Transform; use crate::stable_vec::StableVec; -use crate::world::{Room, Wall, World}; +use crate::world::{Icon, Room, Wall, World}; use icon_texture_manager::IconTextureManager; use raylib::drawing::RaylibDrawHandle; use raylib::{RaylibHandle, RaylibThread}; @@ -92,9 +92,11 @@ impl Map { } /// Add an icon with a specific id. May fail if there already is an entity with that id. - pub fn add_icon(&mut self, id: usize, icon: IconMark) -> bool { + pub fn add_icon(&mut self, id: usize, icon: Icon) -> bool { if self.used_ids.try_insert(id, ()).is_ok() { - self.icons.try_insert(id, icon).unwrap(); + self.icons + .try_insert(id, IconMark::from_icon(icon, self.icon_renderer.clone())) + .unwrap(); true } else { error!("Unable to add icon. Id already in use."); @@ -162,6 +164,14 @@ impl Map { ) } + /// Remove all items from the map. + pub fn clear(&mut self) { + self.rooms.clear(); + self.walls.clear(); + self.icons.clear(); + self.used_ids.clear(); + } + /// Get the rooms of this map. pub fn rooms(&self) -> &StableVec { &self.rooms @@ -175,11 +185,19 @@ impl Map { pub fn walls(&self) -> &StableVec { &self.walls } + /// Get a wall with the given id mutably, in case it exists. + pub fn get_wall_mut(&mut self, id: usize) -> Option<&mut WallMark> { + self.walls.get_mut(id) + } /// Get the icons of this map. pub fn icons(&self) -> &StableVec { &self.icons } + /// Get an icon with the given id mutably, in case it exists. + pub fn get_icon_mut(&mut self, id: usize) -> Option<&mut IconMark> { + self.icons.get_mut(id) + } /// Replace the internal map data with the data of the world provided. /// (Load and replace) @@ -199,10 +217,7 @@ impl Map { /// items with the same id will therefore be ignored and not added. pub fn add_data(&mut self, world: World) { for (id, i) in world.icons().iter() { - self.add_icon( - *id, - IconMark::from_icon(i.clone(), self.icon_renderer.clone()), - ); + self.add_icon(*id, i.clone()); } for (id, r) in world.rooms().iter() { self.add_room(*id, r.clone()); diff --git a/src/client/map/wall_mark.rs b/src/client/map/wall_mark.rs index c51af9d..76ac03b 100644 --- a/src/client/map/wall_mark.rs +++ b/src/client/map/wall_mark.rs @@ -32,6 +32,12 @@ impl WallMark { } } + /// Set the internal wall of this wall mark. + pub fn set_wall(&mut self, wall: Wall) { + // XXX: Rounded edges?? + self.wall = wall; + } + /// Get the internal data for serialisation pub fn data(&self) -> &Wall { &self.wall diff --git a/src/server/mod.rs b/src/server/mod.rs index fe208ad..7f94453 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -50,7 +50,59 @@ fn start(conn_man: ConnectionManager) -> JoinHandle<()> { let room_id = world.push_room(room.clone()); conn_man.broadcast(Cargo::SetRoom((room_id, room))); } - other => error!("Unknown packet received from `{}`: {:?}", user, other), + Cargo::AddIcon(icon) => { + let icon_id = world.push_icon(icon.clone()); + conn_man.broadcast(Cargo::SetIcon((icon_id, icon))); + } + Cargo::AddWall(wall) => { + let wall_id = world.push_wall(wall.clone()); + conn_man.broadcast(Cargo::SetWall((wall_id, wall))); + } + Cargo::SetRoom((id, new)) => { + if let Some(old) = world.get_room_mut(id) { + *old = new; + } else { + error!( + "Unable to change room. Room with id `{}` does not exist.", + id + ); + } + } + Cargo::SetIcon((id, new)) => { + if let Some(old) = world.get_icon_mut(id) { + *old = new; + } else { + error!( + "Unable to change icon. Icon with id `{}` does not exist.", + id + ); + } + } + Cargo::SetWall((id, new)) => { + if let Some(old) = world.get_wall_mut(id) { + *old = new; + } else { + error!( + "Unable to change wall. Wall with id `{}` does not exist.", + id + ); + } + } + Cargo::ClearAll => { + world.clear(); + conn_man.broadcast(Cargo::ClearAll); + } + Cargo::Remove(id) => { + if world.remove(id) { + conn_man.broadcast(Cargo::Remove(id)); + } else { + error!("Unable to remove item. No item with id `{}` found.", id); + } + } + Cargo::ApplyMatrix((_id, _matrix)) => unimplemented!(), + Cargo::AddMapData(_) | Cargo::UpdateMapData(_) => { + error!("This packet is not allowed in the client -> server direction"); + } } } }) diff --git a/src/world/mod.rs b/src/world/mod.rs index a72031d..9ddd9e9 100644 --- a/src/world/mod.rs +++ b/src/world/mod.rs @@ -44,6 +44,32 @@ impl World { } } + /// Remove all items from the world, leaving it empty. + pub fn clear(&mut self) { + self.rooms.clear(); + self.walls.clear(); + self.icons.clear(); + self.used_ids.clear(); + } + + /// Remove the item with the given id. Returns `false` in case no item with + /// such an id existed in the first place. + pub fn remove(&mut self, id: usize) -> bool { + if self.used_ids.remove(id).is_none() { + return false; + } + + if self.rooms.remove(id).is_some() { + true + } else if self.walls.remove(id).is_some() { + true + } else if self.icons.remove(id).is_some() { + true + } else { + panic!("used_ids and the actual ids are out of sync") + } + } + /// Create a world from the raw parts of the world. The components must fit, /// meaning no id must exist twice and the used ids must correspond to the /// actually used ids. Use with care. @@ -127,16 +153,40 @@ impl World { pub fn icons(&self) -> &StableVec { &self.icons } + /// Get an icon mutably. + pub fn get_icon_mut(&mut self, id: usize) -> Option<&mut Icon> { + self.icons.get_mut(id) + } /// Get all rooms of the world. pub fn rooms(&self) -> &StableVec { &self.rooms } + /// Get a room mutably. + pub fn get_room_mut(&mut self, id: usize) -> Option<&mut Room> { + self.rooms.get_mut(id) + } /// Get all walls of the world. pub fn walls(&self) -> &StableVec { &self.walls } + /// Get a wall mutably. + pub fn get_wall_mut(&mut self, id: usize) -> Option<&mut Wall> { + self.walls.get_mut(id) + } + + pub fn get_mut(&mut self, id: usize) -> Option<&mut dyn Component> { + if let Some(c) = self.rooms.get_mut(id) { + Some(c as &mut dyn Component) + } else if let Some(c) = self.walls.get_mut(id) { + Some(c as &mut dyn Component) + } else if let Some(c) = self.icons.get_mut(id) { + Some(c as &mut dyn Component) + } else { + None + } + } } impl Default for World { -- cgit v1.2.3-70-g09d2