azalea_entity/
attributes.rs1use std::collections::{hash_map, HashMap};
4
5use azalea_buf::AzBuf;
6use azalea_core::resource_location::ResourceLocation;
7use bevy_ecs::component::Component;
8use thiserror::Error;
9
10#[derive(Clone, Debug, Component)]
11pub struct Attributes {
12 pub speed: AttributeInstance,
13 pub attack_speed: AttributeInstance,
14 pub water_movement_efficiency: AttributeInstance,
15}
16
17#[derive(Clone, Debug)]
18pub struct AttributeInstance {
19 pub base: f64,
20 modifiers_by_id: HashMap<ResourceLocation, AttributeModifier>,
21}
22
23#[derive(Clone, Debug, Error)]
24#[error("A modifier with this UUID is already present.")]
25pub struct AlreadyPresentError;
26
27impl AttributeInstance {
28 pub fn new(base: f64) -> Self {
29 Self {
30 base,
31 modifiers_by_id: HashMap::new(),
32 }
33 }
34
35 pub fn calculate(&self) -> f64 {
36 let mut total = self.base;
37 for modifier in self.modifiers_by_id.values() {
38 match modifier.operation {
39 AttributeModifierOperation::Addition => total += modifier.amount,
40 AttributeModifierOperation::MultiplyBase => total += self.base * modifier.amount,
41 _ => {}
42 }
43 if let AttributeModifierOperation::MultiplyTotal = modifier.operation {
44 total *= 1.0 + modifier.amount;
45 }
46 }
47 total
48 }
49
50 pub fn insert(&mut self, modifier: AttributeModifier) -> Option<AttributeModifier> {
53 self.modifiers_by_id.insert(modifier.id.clone(), modifier)
54 }
55
56 pub fn try_insert(&mut self, modifier: AttributeModifier) -> Result<(), AlreadyPresentError> {
59 match self.modifiers_by_id.entry(modifier.id.clone()) {
60 hash_map::Entry::Occupied(_) => Err(AlreadyPresentError),
61 hash_map::Entry::Vacant(entry) => {
62 entry.insert(modifier);
63 Ok(())
64 }
65 }
66 }
67
68 pub fn remove(&mut self, id: &ResourceLocation) -> Option<AttributeModifier> {
71 self.modifiers_by_id.remove(id)
72 }
73}
74
75#[derive(Clone, Debug, AzBuf)]
76pub struct AttributeModifier {
77 pub id: ResourceLocation,
78 pub amount: f64,
79 pub operation: AttributeModifierOperation,
80}
81
82#[derive(Clone, Debug, Copy, AzBuf)]
83pub enum AttributeModifierOperation {
84 Addition,
85 MultiplyBase,
86 MultiplyTotal,
87}
88
89pub fn sprinting_modifier() -> AttributeModifier {
90 AttributeModifier {
91 id: ResourceLocation::new("sprinting"),
92 amount: 0.30000001192092896,
93 operation: AttributeModifierOperation::MultiplyTotal,
94 }
95}
96
97pub fn base_attack_speed_modifier(amount: f64) -> AttributeModifier {
98 AttributeModifier {
99 id: ResourceLocation::new("base_attack_speed"),
100 amount,
101 operation: AttributeModifierOperation::Addition,
102 }
103}