aboutsummaryrefslogtreecommitdiff
path: root/azalea-world/src/entity/attributes.rs
diff options
context:
space:
mode:
authormat <27899617+mat-1@users.noreply.github.com>2022-11-12 23:54:05 -0600
committerGitHub <noreply@github.com>2022-11-12 23:54:05 -0600
commit6eee543a3367d38a6f0e9bffb457a2bd76a8f9cc (patch)
treea5e493ccd7ec24293b8d866242c3836146517122 /azalea-world/src/entity/attributes.rs
parentfa57d03627aa20b1df44caed7cb025b6db1d9b53 (diff)
downloadazalea-drasl-6eee543a3367d38a6f0e9bffb457a2bd76a8f9cc.tar.xz
Pathfinder (#25)
Pathfinding is very much not done, but it works enough and I want to get this merged. TODO: fast replanning, goals that aren't a single node, falling moves (it should be able to play the dropper), parkour moves
Diffstat (limited to 'azalea-world/src/entity/attributes.rs')
-rw-r--r--azalea-world/src/entity/attributes.rs116
1 files changed, 116 insertions, 0 deletions
diff --git a/azalea-world/src/entity/attributes.rs b/azalea-world/src/entity/attributes.rs
new file mode 100644
index 00000000..1050615c
--- /dev/null
+++ b/azalea-world/src/entity/attributes.rs
@@ -0,0 +1,116 @@
+//! https://minecraft.fandom.com/wiki/Attribute
+
+use std::{
+ collections::HashMap,
+ io::{Cursor, Write},
+};
+
+use azalea_buf::{BufReadError, McBuf, McBufReadable, McBufWritable};
+use thiserror::Error;
+use uuid::{uuid, Uuid};
+
+#[derive(Clone, Debug)]
+pub struct AttributeModifiers {
+ pub speed: AttributeInstance,
+}
+
+#[derive(Clone, Debug)]
+pub struct AttributeInstance {
+ pub base: f64,
+ modifiers_by_uuid: HashMap<Uuid, AttributeModifier>,
+}
+
+#[derive(Clone, Debug, Error)]
+#[error("A modifier with this UUID is already present.")]
+pub struct AlreadyPresentError;
+
+impl AttributeInstance {
+ pub fn new(base: f64) -> Self {
+ Self {
+ base,
+ modifiers_by_uuid: HashMap::new(),
+ }
+ }
+
+ pub fn calculate(&self) -> f64 {
+ let mut total = self.base;
+ for modifier in self.modifiers_by_uuid.values() {
+ match modifier.operation {
+ AttributeModifierOperation::Addition => total += modifier.amount,
+ AttributeModifierOperation::MultiplyBase => total += self.base * modifier.amount,
+ _ => {}
+ }
+ match modifier.operation {
+ AttributeModifierOperation::MultiplyTotal => total *= 1.0 + modifier.amount,
+ _ => {}
+ }
+ }
+ total
+ }
+
+ /// Add a new modifier to this attribute.
+ pub fn insert(&mut self, modifier: AttributeModifier) -> Result<(), AlreadyPresentError> {
+ if self
+ .modifiers_by_uuid
+ .insert(modifier.uuid, modifier)
+ .is_some()
+ {
+ Err(AlreadyPresentError)
+ } else {
+ Ok(())
+ }
+ }
+
+ /// Remove the modifier with the given UUID from this attribute, returning
+ /// the previous modifier is present.
+ pub fn remove(&mut self, uuid: &Uuid) -> Option<AttributeModifier> {
+ self.modifiers_by_uuid.remove(uuid)
+ }
+}
+
+#[derive(Clone, Debug)]
+pub struct AttributeModifier {
+ pub uuid: Uuid,
+ pub name: String,
+ pub amount: f64,
+ pub operation: AttributeModifierOperation,
+}
+
+#[derive(Clone, Debug, Copy, McBuf)]
+pub enum AttributeModifierOperation {
+ Addition,
+ MultiplyBase,
+ MultiplyTotal,
+}
+
+pub fn sprinting_modifier() -> AttributeModifier {
+ AttributeModifier {
+ uuid: uuid!("662A6B8D-DA3E-4C1C-8813-96EA6097278D"),
+ name: "Sprinting speed boost".to_string(),
+ amount: 0.30000001192092896,
+ operation: AttributeModifierOperation::MultiplyTotal,
+ }
+}
+
+impl McBufReadable for AttributeModifier {
+ fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
+ let uuid = Uuid::read_from(buf)?;
+ let amount = f64::read_from(buf)?;
+ let operation = AttributeModifierOperation::read_from(buf)?;
+ Ok(Self {
+ uuid,
+ name: "Unknown synced attribute modifier".to_string(),
+ amount,
+ operation,
+ })
+ }
+}
+
+impl McBufWritable for AttributeModifier {
+ fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ self.uuid.write_into(buf)?;
+ self.amount.write_into(buf)?;
+ self.operation.write_into(buf)?;
+ Ok(())
+ }
+}