summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main.rs52
-rw-r--r--src/room.rs12
-rw-r--r--src/systems/controlinput.rs7
-rw-r--r--src/world.rs107
-rw-r--r--src/worldloader.rs8
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
}
}