use std::collections::HashMap; use serde_json; use serde_json::{Value}; use specs::{ Component, HashMapStorage }; use crate::{ exchange::Exchange, ItemId, components::{Trigger, equipment::Stat}, RoomId }; #[derive(Component, Debug, Clone, PartialEq)] #[storage(HashMapStorage)] pub enum Interactable { Trigger(Trigger), Say(String), Reply(String), Exchange(String, HashMap), Visit(RoomId), Mine(Stat) } use Interactable::*; impl Interactable { pub fn from_json(val: &Value) -> Option { let typ = val.get(0)?; let arg = val.get(1)?; Some(match typ.as_str()? { "trigger" => Trigger(Trigger::from_str(arg.as_str()?)?), "say" => Say(arg.as_str()?.to_string()), "reply" => Reply(arg.as_str()?.to_string()), "exchange" => { let (prefix, change) = serde_json::value::from_value::< (String, HashMap, Vec)>) >(arg.clone()).ok()?; Exchange( prefix, change.into_iter().map( |(id, (cost, offer))| (id, Exchange{cost, offer}) ).collect::>() ) }, "visit" => Visit(RoomId::from_str(arg.as_str()?)), "mine" => Mine(Stat::from_str(arg.as_str()?)?), _ => None? }) } pub fn accepts_arg(&self, arg: &Option) -> bool { match self { Trigger(_) => arg.is_none(), Say(_) => arg.is_none(), Reply(_) => arg.is_some(), Exchange(prefix, _exchanges) => { if let Some(txt) = arg { txt.starts_with(prefix) } else { true } }, Visit(_) => { if let Some(txt) = arg { txt.starts_with("visit ") || txt.starts_with("disallow ") || txt.starts_with("allow ") || txt.starts_with("whitelist") } else { true } } Mine(_) => arg.is_none() } } } #[derive(Component, Debug, Clone, PartialEq)] #[storage(HashMapStorage)] pub struct Talkable { pub text: String }