summaryrefslogtreecommitdiff
path: root/src/playerstate.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/playerstate.rs')
-rw-r--r--src/playerstate.rs164
1 files changed, 72 insertions, 92 deletions
diff --git a/src/playerstate.rs b/src/playerstate.rs
index f159567..658aeb2 100644
--- a/src/playerstate.rs
+++ b/src/playerstate.rs
@@ -1,5 +1,6 @@
-use serde_json::{Value, json};
+use std::collections::HashMap;
+use serde::{Serialize, Deserialize, Serializer, Deserializer};
use crate::{
componentwrapper::{ComponentWrapper, PreEntity},
PlayerId,
@@ -26,10 +27,13 @@ use crate::{
Sprite,
Encyclopedia,
Pos,
- PResult,
- perr
};
+#[allow(non_upper_case_globals)]
+const maximum_health: i64 = 50;
+#[allow(non_upper_case_globals)]
+const inventory_capacity: usize = 20;
+
#[derive(Debug, Clone)]
#[allow(dead_code)]
pub enum RoomPos {
@@ -43,10 +47,8 @@ pub struct PlayerState {
pub id: PlayerId,
pub room: Option<RoomId>,
pub pos: RoomPos,
- pub inventory_capacity: usize,
pub inventory: Vec<(ItemId, bool)>,
- pub health: i64,
- pub maximum_health: i64
+ pub health: i64
}
impl PlayerState {
@@ -57,105 +59,24 @@ impl PlayerState {
room: None,
pos: RoomPos::Unknown,
inventory: Vec::new(),
- inventory_capacity: 10,
- health: 25,
- maximum_health: 50
+ health: maximum_health/2,
}
}
- pub fn create(id: PlayerId, room: RoomId, inventory: Vec<(ItemId, bool)>, inventory_capacity: usize, health: i64, maximum_health: i64) -> Self {
+ pub fn create(id: PlayerId, room: RoomId, inventory: Vec<(ItemId, bool)>, health: i64) -> Self {
Self {
id,
room: Some(room),
pos: RoomPos::Unknown,
inventory,
health,
- inventory_capacity,
- maximum_health
}
}
-
- pub fn to_json(&self) -> Value {
- json!({
- "name": self.id,
- "roomname": match &self.room {
- Some(id) => json!(id.to_string()),
- None => json!(null)
- },
- "inventory": {
- "items": self.inventory.iter().map(|(item, e)| (json!(item.0), *e)).collect::<Vec<(Value, bool)>>()
- },
- "health": self.health
- })
- }
-
- pub fn from_json(val: &Value) -> PResult<Self> {
- let inventory = val.get("inventory").ok_or(perr!("player json does not have inventory"))?;
- let mut items =
- inventory
- .get("items")
- .ok_or(perr!("inventory does not have items"))?
- .as_array()
- .ok_or(perr!("inventory items not an array"))?
- .iter()
- .map(|entry| {
- if entry.is_array() {
- let itemid = ItemId(
- entry
- .get(0)
- .ok_or(perr!("item does not have name"))?
- .as_str()
- .ok_or(perr!("item name not a string"))?
- .to_string()
- );
- let is_equipped =
- entry
- .get(1)
- .ok_or(perr!("item does not have equipped flag"))?
- .as_bool()
- .ok_or(perr!("item is_equipped not a bool"))?;
- Ok((itemid, is_equipped))
- } else if entry.is_string() {
- Ok((ItemId(entry.as_str().unwrap().to_string()), false))
- } else {
- Err(perr!("item entry must be a string or array, not {:?}", entry))
- }
- })
- .collect::<PResult<Vec<(ItemId, bool)>>>()?;
- if let Some(equipment) = val.get("equipment") {
- for (slot, item) in equipment.as_object().ok_or(perr!("equipment not a json object: {:?}", equipment))?.iter() {
- if item.is_null(){
- continue
- }
- let itemid = ItemId(
- item
- .as_str()
- .ok_or(perr!("equipment item not a string: {:?}", item))?
- .to_string()
- );
- // validate the slot, but don't do anything with it
- Slot::from_str(slot).ok_or(perr!("invalid slot: {:?}", slot))?;
- items.push((itemid, true))
- }
- }
- Ok(Self {
- id: PlayerId(val.get("name").ok_or(perr!("player json does not have name"))?.as_str().ok_or(perr!("player name not a string"))?.to_string()),
- room: match val.get("roomname").ok_or(perr!("player json does not have room name"))? {
- Value::String(name) => Some(RoomId(name.clone())),
- _ => None
- },
- pos: RoomPos::Unknown,
- inventory: items,
- health: val.get("health").ok_or(perr!("player json does not have health"))?.as_i64().ok_or(perr!("player health not a number"))?,
- inventory_capacity: 12,
- maximum_health: 50,
- })
- }
pub fn respawn(&mut self) {
self.room = None;
self.pos = RoomPos::Unknown;
- self.health = self.maximum_health / 2;
+ self.health = maximum_health / 2;
}
pub fn construct(&self, encyclopedia: &Encyclopedia) -> Result<PreEntity> {
@@ -167,9 +88,9 @@ impl PlayerState {
let item = encyclopedia.get_item(&itemid).ok_or(aerr!("failed to load item '{:?} in inventory of player {:?}", itemid, self))?;
Ok(InventoryEntry{itemid: itemid.clone(), item, is_equipped: *is_equipped})
}).collect::<Result<Vec<InventoryEntry>>>()?,
- capacity: self.inventory_capacity
+ capacity: inventory_capacity
}),
- ComponentWrapper::Health(Health{health: self.health, maxhealth: self.maximum_health}),
+ ComponentWrapper::Health(Health{health: self.health, maxhealth: maximum_health}),
ComponentWrapper::Fighter(Fighter{attack: AttackType::Attack(5), cooldown: 8, range: 1}),
ComponentWrapper::Healing(Healing{delay: 50, health: 1, next_heal: None}),
ComponentWrapper::Movable(Movable{cooldown: 2}),
@@ -180,3 +101,62 @@ impl PlayerState {
])
}
}
+
+impl Serialize for PlayerState {
+ fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
+ where S: Serializer {
+ PlayerStateSave::New{name: self.id.clone(), roomname: self.room.clone(), inventory: NewInventorySave{items: self.inventory.clone()}, health: self.health}.serialize(serializer)
+ }
+}
+impl<'de> Deserialize<'de> for PlayerState {
+ fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
+ where D: Deserializer<'de> {
+ Ok(match PlayerStateSave::deserialize(deserializer)? {
+ PlayerStateSave::New{name, roomname, inventory, health} => PlayerState{id: name, room: roomname, inventory: inventory.items, health, pos: RoomPos::Unknown},
+ PlayerStateSave::Old{name, roomname, inventory, equipment, health} => {
+ PlayerState{
+ id: name,
+ room: roomname,
+ inventory: {
+ let mut inv = Vec::new();
+ for item in inventory.items {
+ inv.push((item, false));
+ }
+ for (_slot, item) in equipment.into_iter() {
+ inv.push((item, true));
+ }
+ inv
+ },
+ health,
+ pos: RoomPos::Unknown
+ }
+ }
+ })
+ }
+}
+
+#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
+struct OldInventorySave {
+ pub items: Vec<ItemId>
+}
+#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
+struct NewInventorySave {
+ pub items: Vec<(ItemId, bool)>
+}
+#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
+#[serde(untagged)]
+enum PlayerStateSave {
+ New {
+ name: PlayerId,
+ roomname: Option<RoomId>,
+ inventory: NewInventorySave,
+ health: i64
+ },
+ Old {
+ name: PlayerId,
+ roomname: Option<RoomId>,
+ inventory: OldInventorySave,
+ equipment: HashMap<Slot, ItemId>,
+ health: i64
+ }
+}