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