rude/src/world/room.rs

94 lines
2.0 KiB

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<String>,
/// Whether users in the room should be visible to the parent zone
pub users_visible: bool,
/// Exits from the room
pub exits: HashMap<Direction, Exit>,
}
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::<Vec<&str>>()
.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<dyn Error>;
fn try_from(row: &Row) -> Result<Self, Self::Error> {
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(),
})
}
}