azalea_entity/
attributes.rs1use std::collections::{HashMap, hash_map};
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 sneaking_speed: AttributeInstance,
14 pub attack_speed: AttributeInstance,
15 pub water_movement_efficiency: AttributeInstance,
16
17 pub block_interaction_range: AttributeInstance,
18 pub entity_interaction_range: AttributeInstance,
19}
20
21#[derive(Clone, Debug)]
22pub struct AttributeInstance {
23 pub base: f64,
24 modifiers_by_id: HashMap<ResourceLocation, AttributeModifier>,
25}
26
27#[derive(Clone, Debug, Error)]
28#[error("A modifier with this UUID is already present.")]
29pub struct AlreadyPresentError;
30
31impl AttributeInstance {
32 pub fn new(base: f64) -> Self {
33 Self {
34 base,
35 modifiers_by_id: HashMap::new(),
36 }
37 }
38
39 pub fn calculate(&self) -> f64 {
40 let mut total = self.base;
41 for modifier in self.modifiers_by_id.values() {
42 match modifier.operation {
43 AttributeModifierOperation::Addition => total += modifier.amount,
44 AttributeModifierOperation::MultiplyBase => total += self.base * modifier.amount,
45 _ => {}
46 }
47 if let AttributeModifierOperation::MultiplyTotal = modifier.operation {
48 total *= 1.0 + modifier.amount;
49 }
50 }
51 total
52 }
53
54 pub fn insert(&mut self, modifier: AttributeModifier) -> Option<AttributeModifier> {
57 self.modifiers_by_id.insert(modifier.id.clone(), modifier)
58 }
59
60 pub fn try_insert(&mut self, modifier: AttributeModifier) -> Result<(), AlreadyPresentError> {
63 match self.modifiers_by_id.entry(modifier.id.clone()) {
64 hash_map::Entry::Occupied(_) => Err(AlreadyPresentError),
65 hash_map::Entry::Vacant(entry) => {
66 entry.insert(modifier);
67 Ok(())
68 }
69 }
70 }
71
72 pub fn remove(&mut self, id: &ResourceLocation) -> Option<AttributeModifier> {
75 self.modifiers_by_id.remove(id)
76 }
77}
78
79#[derive(Clone, Debug, AzBuf)]
80pub struct AttributeModifier {
81 pub id: ResourceLocation,
82 pub amount: f64,
83 pub operation: AttributeModifierOperation,
84}
85
86#[derive(Clone, Debug, Copy, AzBuf)]
87pub enum AttributeModifierOperation {
88 Addition,
89 MultiplyBase,
90 MultiplyTotal,
91}
92
93pub fn sprinting_modifier() -> AttributeModifier {
94 AttributeModifier {
95 id: ResourceLocation::new("sprinting"),
96 amount: 0.3f32 as f64,
97 operation: AttributeModifierOperation::MultiplyTotal,
98 }
99}
100pub fn base_attack_speed_modifier(amount: f64) -> AttributeModifier {
101 AttributeModifier {
102 id: ResourceLocation::new("base_attack_speed"),
103 amount,
104 operation: AttributeModifierOperation::Addition,
105 }
106}
107pub fn creative_block_interaction_range_modifier() -> AttributeModifier {
108 AttributeModifier {
109 id: ResourceLocation::new("creative_mode_block_range"),
110 amount: 0.5,
111 operation: AttributeModifierOperation::Addition,
112 }
113}
114
115pub fn creative_entity_interaction_range_modifier() -> AttributeModifier {
116 AttributeModifier {
117 id: ResourceLocation::new("creative_mode_entity_range"),
118 amount: 2.0,
119 operation: AttributeModifierOperation::Addition,
120 }
121}