From c71ecb48fa4368035a852e2d06869a21382a6876 Mon Sep 17 00:00:00 2001 From: troido Date: Tue, 18 Feb 2020 01:11:49 +0100 Subject: Players are now saved/loaded too --- src/componentwrapper.rs | 6 +-- src/encyclopedia.rs | 4 +- src/main.rs | 43 +++++++++++++++--- src/persistence.rs | 23 +++++++++- src/playerstate.rs | 50 ++++++++++++++++----- src/resources.rs | 28 ++++++++++-- src/room.rs | 104 ++++++++++++++++++++++++++++++++++++-------- src/systems/controlinput.rs | 37 +++------------- src/systems/create.rs | 15 +++---- src/systems/take.rs | 2 +- 10 files changed, 223 insertions(+), 89 deletions(-) (limited to 'src') diff --git a/src/componentwrapper.rs b/src/componentwrapper.rs index 951745d..e5f9b9f 100644 --- a/src/componentwrapper.rs +++ b/src/componentwrapper.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -use specs::{Builder, world::LazyBuilder}; +use specs::Builder; use crate::PlayerId; use crate::components::{Visible, Blocking, Player, Floor, Item, Inventory, Health, Serialise}; @@ -20,7 +20,7 @@ macro_rules! components { impl ComponentWrapper { - pub fn build<'a>(&self, builder: LazyBuilder<'a>) -> LazyBuilder<'a> { + pub fn build(&self, builder: A ) -> A { match self.clone() { $( Self::$comp(c) => builder.with(c), @@ -101,7 +101,7 @@ components!( ); - +pub type PreEntity = Vec; diff --git a/src/encyclopedia.rs b/src/encyclopedia.rs index 920f15e..bdb12af 100644 --- a/src/encyclopedia.rs +++ b/src/encyclopedia.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use serde_json::Value; use crate::assemblage::Assemblage; -use crate::componentwrapper::ComponentWrapper; +use crate::componentwrapper::PreEntity; use crate::template::Template; #[derive(Default, Clone)] @@ -20,7 +20,7 @@ impl Encyclopedia { Ok(Encyclopedia{items}) } - pub fn construct(&self, template: &Template) -> Result, &'static str> { + pub fn construct(&self, template: &Template) -> Result { let assemblage = self.items.get(&template.name).ok_or("unknown assemblage name")?; assemblage.instantiate(template) } diff --git a/src/main.rs b/src/main.rs index 5b2bc8a..73c26ca 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,5 @@ - +use std::collections::HashMap; use std::thread::sleep; use std::time::Duration; use std::path::Path; @@ -41,6 +41,8 @@ use self::util::ToJson; use self::roomtemplate::RoomTemplate; use self::defaultencyclopedia::default_encyclopedia; use self::persistence::{FileStorage, PersistentStorage}; +use crate::controls::Action; +use crate::playerstate::PlayerState; @@ -60,7 +62,7 @@ fn main() { let mut room = gen_room(); - let storage = FileStorage::new("~/.rustifarm/saves"); + let storage = FileStorage::new(FileStorage::savedir().expect("couldn't find any save directory")); if let Ok(state) = storage.load_room("room".to_string()) { room.load_saved(&state); println!("loaded saved state successfully"); @@ -74,12 +76,39 @@ fn main() { let mut count = 0; loop { let actions = gameserver.update(); - - room.set_input(actions); + let mut inputs = HashMap::new(); + for action in actions { + match action { + Action::Input(player, control) => {inputs.insert(player, control);} + Action::Join(player) => { + let state = match storage.load_player(player.clone()) { + Ok(state) => state, + Err(_) => PlayerState::new(player.name.clone()) + }; + room.add_player(player.clone(), &state); + } + Action::Leave(player) => { + if let Err(err) = storage.save_player(player.clone(), room.remove_player(player).unwrap()) { + println!("{:?}", err); + } + } + } + } + room.set_input(inputs); room.update(); if count % 50 == 0 { - storage.save_room("room".to_string(), room.save()); - println!("{}", room.save().to_json()); + if let Err(err) = storage.save_room(room.name.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()); + } + } } let messages = room.view(); for (player, message) in messages { @@ -93,7 +122,7 @@ fn main() { fn gen_room<'a, 'b>() -> Room<'a, 'b> { let assemblages = default_encyclopedia(); - let mut room = Room::new(assemblages); + let mut room = Room::new("room", assemblages); let roomtemplate = RoomTemplate::from_json(&json!({ "width": 42, diff --git a/src/persistence.rs b/src/persistence.rs index 1808652..7c15ec0 100644 --- a/src/persistence.rs +++ b/src/persistence.rs @@ -1,6 +1,7 @@ use std::path::PathBuf; use std::fs; +use std::env; use serde_json; use serde_json::Value; use crate::{ @@ -29,9 +30,27 @@ pub struct FileStorage { } impl FileStorage { - pub fn new(path: &str) -> Self { + pub fn new(path: PathBuf) -> Self { Self { - directory: PathBuf::from(path) + directory: path + } + } + + pub fn savedir() -> Option { + if let Some(pathname) = env::var_os("ASCIIFARM_SAVE_DIR") { + Some(PathBuf::from(pathname)) + } else if let Some(pathname) = env::var_os("XDG_DATA_HOME") { + let mut path = PathBuf::from(pathname); + path.push("asciifarm"); + path.push("saves"); + Some(path) + } else if let Some(pathname) = env::var_os("HOME") { + let mut path = PathBuf::from(pathname); + path.push(".asciifarm"); + path.push("saves"); + Some(path) + } else { + None } } } diff --git a/src/playerstate.rs b/src/playerstate.rs index dac463b..e68e890 100644 --- a/src/playerstate.rs +++ b/src/playerstate.rs @@ -2,27 +2,43 @@ use serde_json::{Value, json}; use crate::template::Template; +use crate::{ + componentwrapper::{ComponentWrapper, PreEntity}, + PlayerId, + components::{Visible, Player, Inventory, Health, Item} +}; - +#[derive(Debug, Clone)] pub struct PlayerState { - name: String, - room: String, - inventory_capacity: usize, - inventory: Vec