Skip to main content

yog_registry/
effects.rs

1//! Attributes, mob effects and potions a mod adds: data (`.ydef` kinds
2//! `attribute`, `effect`, `potion`), the host registers each with the game.
3
4use yog_data::kinds::Item;
5use yog_data::with::RefTo;
6
7// What these definitions name: `@attribute:mymod:grid_zoom`,
8// `@effect:mymod:clarity`, `@potion:minecraft:awkward`.
9yog_data::kind! {
10    Attribute = "attribute",
11    Effect = "effect",
12    Potion = "potion",
13}
14
15/// A number every player has (`hexcasting:grid_zoom`) — what effects
16/// change (`EffectDef::modifiers`) and the mod reads
17/// (`Server::entity_attribute_value`).
18#[derive(yog_data::Schema, Debug, Clone, PartialEq)]
19pub struct AttributeDef {
20    pub id: String,
21    /// Its value with nothing changing it.
22    pub default: f64,
23    pub min: f64,
24    pub max: f64,
25}
26
27/// Whether an effect is good or bad for whoever has it (its colour in the
28/// inventory, what milk and beacons do with it).
29#[derive(yog_data::Schema, Debug, Clone, Copy, PartialEq, Eq)]
30pub enum EffectCategory {
31    Beneficial,
32    Harmful,
33    Neutral,
34}
35
36/// How a modifier changes an attribute.
37#[derive(yog_data::Schema, Debug, Clone, Copy, PartialEq, Eq)]
38pub enum ModifierOperation {
39    /// Adds `amount`.
40    Add,
41    /// Adds `amount` × the base value.
42    MultiplyBase,
43    /// Multiplies the value by `1 + amount`.
44    MultiplyTotal,
45}
46
47/// An attribute an effect changes while it lasts — by `amount` for each
48/// level.
49#[derive(yog_data::Schema, Debug, Clone, PartialEq)]
50pub struct EffectModifier {
51    /// `@attribute:mymod:grid_zoom`, or the game's (`minecraft:generic.movement_speed`).
52    #[data(with = "RefTo<Attribute>")]
53    pub attribute: String,
54    pub amount: f64,
55    pub operation: ModifierOperation,
56}
57
58/// A mob effect (`hexcasting:enlarge_grid`): its kind, its colour (its
59/// particles, its potions) and the attributes it changes. Its icon is the
60/// mod's `textures/mob_effect/<name>.png`, its name `effect.<ns>.<name>`.
61#[derive(yog_data::Schema, Debug, Clone, PartialEq)]
62pub struct EffectDef {
63    pub id: String,
64    pub category: EffectCategory,
65    /// `0xRRGGBB`.
66    pub color: u32,
67    #[data(default)]
68    pub modifiers: Vec<EffectModifier>,
69}
70
71/// An effect a potion gives.
72#[derive(yog_data::Schema, Debug, Clone, PartialEq)]
73pub struct PotionEffect {
74    /// `@effect:mymod:clarity`, or the game's.
75    #[data(with = "RefTo<Effect>")]
76    pub effect: String,
77    /// Ticks.
78    pub duration: u32,
79    /// 0 is level I.
80    #[data(default)]
81    pub amplifier: u32,
82}
83
84/// A brewing stand recipe making a potion: one potion and an ingredient.
85#[derive(yog_data::Schema, Debug, Clone, PartialEq)]
86pub struct Brew {
87    /// The potion brewed from (`@potion:minecraft:awkward`).
88    #[data(with = "RefTo<Potion>")]
89    pub from: String,
90    /// The ingredient.
91    #[data(with = "RefTo<Item>")]
92    pub with: String,
93}
94
95/// A potion (`hexcasting:enlarge_grid_long`): the effects it gives, and the
96/// brewing that makes it. Its names are the game's `item.minecraft.potion.
97/// effect.<name>` (splash, lingering and tipped arrow alike).
98#[derive(yog_data::Schema, Debug, Clone, PartialEq)]
99pub struct PotionDef {
100    pub id: String,
101    /// The name its translations go by (`item.minecraft.potion.effect.<name>`):
102    /// its id's by default — a longer or stronger kind shares the plain one's.
103    pub name: Option<String>,
104    pub effects: Vec<PotionEffect>,
105    #[data(default)]
106    pub brewed: Vec<Brew>,
107}
108
109#[cfg(test)]
110mod tests {
111    use super::*;
112    use yog_data::Schema;
113
114    #[test]
115    fn effects_and_potions_cross_as_yog_data() {
116        let e = EffectDef {
117            id: "mymod:clarity".into(),
118            category: EffectCategory::Beneficial,
119            color: 0xc875ff,
120            modifiers: vec![EffectModifier { attribute: "mymod:grid_zoom".into(), amount: 0.25, operation: ModifierOperation::MultiplyTotal }],
121        };
122        let back = yog_data::read_bytes::<EffectDef>(&yog_data::binary::encode(&e.write())).unwrap();
123        assert_eq!(back, e);
124        assert_eq!(yog_data::text::to_string(&e.write()).contains("\"multiply_total\"") && yog_data::text::to_string(&e.write()).contains("\"beneficial\""), true, "{}", yog_data::text::to_string(&e.write()));
125        let p = PotionDef {
126            id: "mymod:clarity".into(),
127            name: None,
128            effects: vec![PotionEffect { effect: "mymod:clarity".into(), duration: 3600, amplifier: 0 }],
129            brewed: vec![Brew { from: "minecraft:awkward".into(), with: "mymod:dust".into() }],
130        };
131        assert_eq!(yog_data::read_bytes::<PotionDef>(&yog_data::binary::encode(&p.write())).unwrap(), p);
132    }
133}