use std::collections::HashMap; use std::convert::TryFrom; use std::error::Error; use rusqlite::Row; use serde_derive::{Deserialize, Serialize}; use crate::id::Id; use crate::try_log; use crate::world::{Area, AreaType, Direction, Exit, DIRECTION_LIST}; /// A specific location in the world. #[derive(Debug, Deserialize, Serialize)] pub struct Room { /// Unique identifier pub id: Id, /// Parent zone that the room is in pub zone: Id, /// Name of the room pub name: String, /// Description, each line an entry in a `Vec` pub description: Vec, /// Whether users in the room should be visible to the parent zone pub users_visible: bool, /// Exits from the room pub exits: HashMap, } impl Room { /// Return a list of available exits by the short identifier pub fn exit_string(&self) -> String { if self.exits.is_empty() { return String::new(); } DIRECTION_LIST .iter() .filter_map(|(_, direction)| { if self.exits.contains_key(direction) { Some(direction.short()) } else { None } }) .collect::>() .join(" ") } } impl Area for Room { fn id(&self) -> Id { self.id } fn parent(&self) -> Id { self.zone } fn name(&self) -> String { self.name.to_owned() } fn visible(&self) -> bool { self.users_visible } fn area_type(&self) -> AreaType { AreaType::Room } } impl<'a> TryFrom<&Row<'a>> for Room { type Error = Box; fn try_from(row: &Row) -> Result { Ok(Self { id: try_log!(row.get("id"), "Unable to get column 'id' from row"), zone: try_log!(row.get("zone"), "Unable to get column 'zone' from row"), name: try_log!(row.get("name"), "Unable to get column 'name' from row"), description: try_log!(row.get::<&str, String>("description"), "Unable to get column 'description' from row") .lines() .map(|s| String::from(s)) .collect(), users_visible: try_log!(row.get("users_visible"), "Unable to get column 'users_visible' from row"), exits: HashMap::new(), }) } }