diff options
| -rw-r--r-- | src/main.rs | 52 | ||||
| -rw-r--r-- | src/room.rs | 12 | ||||
| -rw-r--r-- | src/systems/controlinput.rs | 7 | ||||
| -rw-r--r-- | src/world.rs | 107 | ||||
| -rw-r--r-- | src/worldloader.rs | 8 |
5 files changed, 138 insertions, 48 deletions
diff --git a/src/main.rs b/src/main.rs index 2e4fffb..c8816bf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,4 @@ -use std::collections::HashMap; use std::thread::sleep; use std::time::Duration; use std::path::Path; @@ -30,6 +29,7 @@ mod playerstate; mod roomid; mod persistence; mod worldloader; +mod world; pub use self::pos::Pos; pub use self::playerid::PlayerId; @@ -39,13 +39,12 @@ use self::gameserver::GameServer; use self::server::unixserver::UnixServer; use self::server::tcpserver::TcpServer; use self::server::Server; -use self::room::Room; use self::util::ToJson; use self::defaultencyclopedia::default_encyclopedia; -use self::persistence::{FileStorage, PersistentStorage}; +use self::persistence::FileStorage; use crate::controls::Action; -use crate::playerstate::PlayerState; use crate::worldloader::WorldLoader; +use crate::world::World; @@ -63,17 +62,11 @@ fn main() { let mut gameserver = GameServer::new(servers); - let loader = WorldLoader::new(PathBuf::from_str(&(env!("CARGO_MANIFEST_DIR").to_owned() + "/content/maps/")).unwrap(), RoomId::from_str("room")); - let mut room = Room::new(RoomId::from_str("room"), default_encyclopedia()); - room.load_from_template(&loader.load_room(room.id.clone()).unwrap()); + let loader = WorldLoader::new(PathBuf::from_str(&(env!("CARGO_MANIFEST_DIR").to_owned() + "/content/maps/")).unwrap()); let storage = FileStorage::new(FileStorage::savedir().expect("couldn't find any save directory")); - if let Ok(state) = storage.load_room(RoomId::from_str("room")) { - room.load_saved(&state); - println!("loaded saved state successfully"); - } else { - println!("loading saved state failed"); - } + + let mut world = World::new(default_encyclopedia(), loader, Box::new(storage), RoomId::from_str("room")); println!("asciifarm started"); @@ -81,41 +74,24 @@ fn main() { let mut count = 0; loop { let actions = gameserver.update(); - let mut inputs = HashMap::new(); for action in actions { match action { - Action::Input(player, control) => {inputs.insert(player, control);} + Action::Input(player, control) => { + let _ = world.control_player(player, control); + } Action::Join(player) => { - let state = match storage.load_player(player.clone()) { - Ok(state) => state, - Err(_) => PlayerState::new(player.clone()) - }; - room.add_player(&state); + world.add_player(player).unwrap(); } Action::Leave(player) => { - if let Err(err) = storage.save_player(player.clone(), room.remove_player(player).unwrap()) { - println!("{:?}", err); - } + world.remove_player(player).unwrap(); } } } - room.set_input(inputs); - room.update(); + world.update(); if count % 50 == 0 { - if let Err(err) = storage.save_room(room.id.clone(), room.save()) { - println!("{:?}",err); - } else { - println!("{}", room.save().to_json()); - } - for (playerid, state) in room.save_players() { - if let Err(err) = storage.save_player(playerid.clone(), state.clone()) { - println!("{:?}",err); - } else { - println!("{:?} {}", playerid, state.to_json()); - } - } + world.save(); } - let messages = room.view(); + let messages = world.view(); for (player, message) in messages { let _ = gameserver.send(&player, message.to_json()); } diff --git a/src/room.rs b/src/room.rs index c826c19..c813e0c 100644 --- a/src/room.rs +++ b/src/room.rs @@ -102,6 +102,13 @@ impl <'a, 'b>Room<'a, 'b> { } } + + pub fn create(id: RoomId, encyclopedia: &Encyclopedia, template: &RoomTemplate) -> Room<'a, 'b> { + let mut room = Self::new(id, encyclopedia.clone()); + room.load_from_template(template); + room + } + pub fn view(&self) -> HashMap<PlayerId, WorldMessage> { self.world.fetch::<Output>().output.clone() } @@ -111,8 +118,9 @@ impl <'a, 'b>Room<'a, 'b> { self.world.maintain(); } - pub fn set_input(&mut self, actions: HashMap<PlayerId, Control>){ - self.world.fetch_mut::<Input>().actions = actions; + + pub fn control_player(&mut self, player: PlayerId, control: Control){ + self.world.fetch_mut::<Input>().actions.insert(player, control); } pub fn add_player(&mut self, state: &PlayerState){ diff --git a/src/systems/controlinput.rs b/src/systems/controlinput.rs index a2de78d..bd8b23c 100644 --- a/src/systems/controlinput.rs +++ b/src/systems/controlinput.rs @@ -2,7 +2,7 @@ use specs::{ ReadStorage, WriteStorage, - Read, + Write, Entities, System, Join @@ -16,11 +16,11 @@ pub struct ControlInput; impl <'a> System<'a> for ControlInput { type SystemData = ( Entities<'a>, - Read<'a, Input>, + Write<'a, Input>, WriteStorage<'a, Controller>, ReadStorage<'a, Player> ); - fn run(&mut self, (entities, input, mut controllers, players): Self::SystemData) { + fn run(&mut self, (entities, mut input, mut controllers, players): Self::SystemData) { { let mut ents = Vec::new(); for (ent, _controller) in (&*entities, &controllers).join() { @@ -36,6 +36,7 @@ impl <'a> System<'a> for ControlInput { let _ = controllers.insert(entity, Controller(control.clone())); } } + input.actions.clear(); } } diff --git a/src/world.rs b/src/world.rs new file mode 100644 index 0000000..891e22b --- /dev/null +++ b/src/world.rs @@ -0,0 +1,107 @@ + +use std::collections::HashMap; + +use crate::{ + PlayerId, + RoomId, + room::Room, + worldloader::WorldLoader, + persistence::PersistentStorage, + playerstate::PlayerState, + encyclopedia::Encyclopedia, + controls::Control, + util::Result, + aerr, + worldmessages::WorldMessage +}; + +pub struct World<'a, 'b> { + template_loader: WorldLoader, + persistence: Box<dyn PersistentStorage>, + default_room: RoomId, + players: HashMap<PlayerId, RoomId>, + rooms: HashMap<RoomId, Room<'a, 'b>>, + encyclopedia: Encyclopedia +} + + +impl <'a, 'b>World<'a, 'b> { + + pub fn new(encyclopedia: Encyclopedia, template_loader: WorldLoader, persistence: Box<dyn PersistentStorage>, default_room: RoomId) -> Self { + World { + template_loader, + persistence, + default_room, + encyclopedia, + players: HashMap::new(), + rooms: HashMap::new() + } + } + + fn get_room_mut(&mut self, id: &RoomId) -> Option<&mut Room<'a, 'b>> { + if !self.rooms.contains_key(id){ + let template = self.template_loader.load_room(id.clone()).ok()?; + let mut room: Room = Room::create(id.clone(), &self.encyclopedia, &template); + if let Ok(state) = self.persistence.load_room(id.clone()){ + room.load_saved(&state); + } + self.rooms.insert(id.clone(), room); + } + self.rooms.get_mut(id) + } + + pub fn add_player(&mut self, playerid: PlayerId) -> Result<()> { + let state = self.persistence.load_player(playerid.clone()).unwrap_or(PlayerState::new(playerid.clone())); + let roomid = state.clone().room.unwrap_or(self.default_room.clone()); + let room = self.get_room_mut(&roomid).ok_or(aerr!("room not found"))?; + room.add_player(&state); + self.players.insert(playerid, roomid); + Ok(()) + } + + pub fn remove_player(&mut self, playerid: PlayerId) -> Result<()> { + let roomid = self.players.remove(&playerid).ok_or(aerr!("player not found"))?; + let room = self.get_room_mut(&roomid).ok_or(aerr!("room not found"))?; + let player_state = room.remove_player(playerid.clone())?; + self.persistence.save_player(playerid.clone(), player_state)?; + Ok(()) + } + + pub fn control_player(&mut self, player: PlayerId, control: Control) -> Result<()>{ + let roomid = self.players.get(&player).ok_or(aerr!("player not found"))?.clone(); + Ok(self.get_room_mut(&roomid).ok_or(aerr!("room not found"))?.control_player(player, control)) + } + + pub fn update(&mut self) { + for room in self.rooms.values_mut() { + room.update(); + } + } + + pub fn save(&self) { + for room in self.rooms.values() { + if let Err(err) = self.persistence.save_room(room.id.clone(), room.save()) { + println!("{:?}",err); + } else { + println!("{}", room.save().to_json()); + } + for (playerid, state) in room.save_players() { + if let Err(err) = self.persistence.save_player(playerid.clone(), state.clone()) { + println!("{:?}",err); + } else { + println!("{:?} {}", playerid, state.to_json()); + } + } + } + } + + pub fn view(&self) -> HashMap<PlayerId, WorldMessage> { + let mut views = HashMap::new(); + for room in self.rooms.values() { + for (player, message) in room.view().into_iter() { + views.insert(player, message); + } + } + views + } +} diff --git a/src/worldloader.rs b/src/worldloader.rs index 6660f9d..8745bf4 100644 --- a/src/worldloader.rs +++ b/src/worldloader.rs @@ -11,15 +11,13 @@ use crate::{ pub struct WorldLoader { - pub directory: PathBuf, - pub default_room: RoomId + pub directory: PathBuf } impl WorldLoader { - pub fn new(path: PathBuf, default_room: RoomId) -> Self { + pub fn new(path: PathBuf) -> Self { Self { - directory: path, - default_room + directory: path } } |
