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