about summary refs log tree commit diff
path: root/src/entities/raw_types.rs
blob: 8f64e60d9cd47fa3a62294c4ebada253396e2e20 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
use crate::entities::entity_char::EntityChar;
use crate::messages::Message;
use crate::types::Speed;

#[derive(Debug, Deserialize)]
pub struct CreatureType<'a> {
    /// The name of the creature. Used in raw lookups.
    pub name: &'a str,

    /// A description of the entity, used by the "look" command
    pub description: &'a str,

    #[serde(rename = "char")]
    pub chr: EntityChar,
    pub max_hitpoints: u16,
    pub speed: Speed,
    pub friendly: bool,
}

#[derive(Debug, Deserialize)]
pub struct EdibleItem<'a> {
    #[serde(borrow)]
    pub eat_message: Option<Message<'a>>,

    /// The number of hitpoints that eating this item heals
    pub hitpoints_healed: u16,
}

#[derive(Debug, Deserialize)]
pub struct ItemType<'a> {
    pub name: &'a str,

    /// A description of the item, used by the "look" command
    pub description: &'a str,

    pub edible_item: Option<EdibleItem<'a>>,

    #[serde(rename = "char")]
    pub chr: EntityChar,
}

#[cfg(test)]
mod item_type_tests {
    use super::*;

    #[test]
    fn test_deserialize_item_type() {
        let result = serde_json::from_str(
            r#"{
                "Item": {
                    "name": "noodles",
                    "description": "You know exactly what kind of noodles",
                    "char": { "char": "n" },
                    "edible_item": {
                        "eat_message": "You slurp up the noodles",
                        "hitpoints_healed": 2
                    }
                }
            }"#,
        )
        .unwrap();
        assert_matches!(result, EntityRaw::Item(_));
        if let EntityRaw::Item(item) = result {
            assert_eq!(item.name, "noodles");
        }

        let toml_result = toml::from_str(
            r#"[Item]
name = "noodles"
description = "You know exactly what kind of noodles"
char = { char = "🍜" }
edible_item = { eat_message = "You slurp up the noodles", hitpoints_healed = 2 }
"#,
        )
        .unwrap();

        assert_matches!(toml_result, EntityRaw::Item(_));
        if let EntityRaw::Item(item) = toml_result {
            assert_eq!(item.name, "noodles");
        }
    }
}

impl<'a> ItemType<'a> {
    pub fn is_edible(&self) -> bool {
        self.edible_item.is_some()
    }
}

#[derive(Debug, Deserialize)]
pub enum EntityRaw<'a> {
    Creature(#[serde(borrow)] CreatureType<'a>),
    Item(#[serde(borrow)] ItemType<'a>),
}

impl<'a> EntityRaw<'a> {
    pub fn name(&self) -> &'a str {
        use EntityRaw::*;
        match self {
            Creature(typ) => typ.name,
            Item(typ) => typ.name,
        }
    }
}