From 34f15d2baf92132f779139bdd4f061136656261c Mon Sep 17 00:00:00 2001 From: Bixilon Date: Sun, 24 Oct 2021 16:35:33 +0200 Subject: [PATCH] fix entity attribute stuff --- .../minosoft/data/entities/entities/Entity.kt | 28 ++++++++-------- .../minosoft/data/player/LocalPlayerEntity.kt | 6 ++-- .../data/registries/effects/StatusEffect.kt | 12 +++---- .../DefaultStatusEffectAttributes.kt | 2 +- ...ttributeInstance.kt => EntityAttribute.kt} | 18 ++++++++--- ...ttribute.kt => EntityAttributeModifier.kt} | 6 ++-- .../elements/hotbar/HotbarHealthElement.kt | 10 ++++-- .../s2c/play/EntityEffectAttributesS2CP.kt | 32 +++++++++++++------ 8 files changed, 71 insertions(+), 43 deletions(-) rename src/main/java/de/bixilon/minosoft/data/registries/effects/attributes/{StatusEffectAttributeInstance.kt => EntityAttribute.kt} (67%) rename src/main/java/de/bixilon/minosoft/data/registries/effects/attributes/{StatusEffectAttribute.kt => EntityAttributeModifier.kt} (90%) diff --git a/src/main/java/de/bixilon/minosoft/data/entities/entities/Entity.kt b/src/main/java/de/bixilon/minosoft/data/entities/entities/Entity.kt index f33fa67e5..a56bf7ec4 100644 --- a/src/main/java/de/bixilon/minosoft/data/entities/entities/Entity.kt +++ b/src/main/java/de/bixilon/minosoft/data/entities/entities/Entity.kt @@ -26,8 +26,8 @@ import de.bixilon.minosoft.data.registries.AABB import de.bixilon.minosoft.data.registries.ResourceLocation import de.bixilon.minosoft.data.registries.blocks.types.FluidBlock import de.bixilon.minosoft.data.registries.effects.StatusEffect -import de.bixilon.minosoft.data.registries.effects.attributes.StatusEffectAttribute -import de.bixilon.minosoft.data.registries.effects.attributes.StatusEffectAttributeInstance +import de.bixilon.minosoft.data.registries.effects.attributes.EntityAttribute +import de.bixilon.minosoft.data.registries.effects.attributes.EntityAttributeModifier import de.bixilon.minosoft.data.registries.effects.attributes.StatusEffectOperations import de.bixilon.minosoft.data.registries.enchantment.Enchantment import de.bixilon.minosoft.data.registries.entities.EntityType @@ -72,7 +72,7 @@ abstract class Entity( protected val random = Random open val equipment: MutableMap = mutableMapOf() val activeStatusEffects: MutableMap = synchronizedMapOf() - val attributes: MutableMap> = synchronizedMapOf() + val attributes: MutableMap = synchronizedMapOf() val id: Int? get() = connection.world.entities.getId(this) @@ -154,28 +154,30 @@ abstract class Entity( activeStatusEffects.remove(effect) } - fun getAttributeValue(attribute: ResourceLocation, baseValue: Double = entityType.attributes[attribute] ?: 1.0): Double { + fun getAttributeValue(name: ResourceLocation, baseValue: Double? = null): Double { // ToDo: Check order and verify value - var ret = baseValue + val attribute = attributes[name] + val realBaseValue = baseValue ?: attribute?.baseValue ?: 1.0 + var ret = realBaseValue - fun addToValue(statusEffectAttribute: StatusEffectAttribute, amplifier: Int) { - val instanceValue = statusEffectAttribute.amount * amplifier - when (statusEffectAttribute.operation) { + fun addToValue(modifier: EntityAttributeModifier, amplifier: Int) { + val instanceValue = modifier.amount * amplifier + when (modifier.operation) { StatusEffectOperations.MULTIPLY_TOTAL -> ret *= 1.0 + instanceValue StatusEffectOperations.ADDITION -> ret += instanceValue - StatusEffectOperations.MULTIPLY_BASE -> ret += baseValue * (instanceValue + 1.0) + StatusEffectOperations.MULTIPLY_BASE -> ret += realBaseValue * (instanceValue + 1.0) } } - attributes[attribute]?.let { - for (instance in it.values) { - addToValue(instance.statusEffectAttribute, instance.amplifier) + attribute?.let { + for (instance in it.modifiers.values) { + addToValue(instance, 1) } } for (statusEffect in activeStatusEffects.values) { for ((instanceResourceLocation, instance) in statusEffect.statusEffect.attributes) { - if (instanceResourceLocation != attribute) { + if (instanceResourceLocation != name) { continue } addToValue(instance, statusEffect.amplifier) diff --git a/src/main/java/de/bixilon/minosoft/data/player/LocalPlayerEntity.kt b/src/main/java/de/bixilon/minosoft/data/player/LocalPlayerEntity.kt index 6a4367b8b..db863377e 100644 --- a/src/main/java/de/bixilon/minosoft/data/player/LocalPlayerEntity.kt +++ b/src/main/java/de/bixilon/minosoft/data/player/LocalPlayerEntity.kt @@ -30,7 +30,7 @@ import de.bixilon.minosoft.data.registries.blocks.types.Block import de.bixilon.minosoft.data.registries.effects.DefaultStatusEffects import de.bixilon.minosoft.data.registries.effects.attributes.DefaultStatusEffectAttributeNames import de.bixilon.minosoft.data.registries.effects.attributes.DefaultStatusEffectAttributes -import de.bixilon.minosoft.data.registries.effects.attributes.StatusEffectAttributeInstance +import de.bixilon.minosoft.data.registries.effects.attributes.EntityAttribute import de.bixilon.minosoft.data.registries.enchantment.DefaultEnchantments import de.bixilon.minosoft.data.registries.items.DefaultItems import de.bixilon.minosoft.data.registries.items.Item @@ -133,10 +133,10 @@ class LocalPlayerEntity( if (value == field) { return } - attributes[DefaultStatusEffectAttributeNames.GENERIC_MOVEMENT_SPEED]?.remove(DefaultStatusEffectAttributes.SPRINT_SPEED_BOOST.uuid) + attributes[DefaultStatusEffectAttributeNames.GENERIC_MOVEMENT_SPEED]?.modifiers?.remove(DefaultStatusEffectAttributes.SPRINT_SPEED_BOOST.uuid) if (value) { - attributes.getOrPut(DefaultStatusEffectAttributeNames.GENERIC_MOVEMENT_SPEED) { synchronizedMapOf() }[DefaultStatusEffectAttributes.SPRINT_SPEED_BOOST.uuid] = StatusEffectAttributeInstance(DefaultStatusEffectAttributes.SPRINT_SPEED_BOOST, 1) + attributes.getOrPut(DefaultStatusEffectAttributeNames.GENERIC_MOVEMENT_SPEED) { EntityAttribute() }.modifiers[DefaultStatusEffectAttributes.SPRINT_SPEED_BOOST.uuid] = DefaultStatusEffectAttributes.SPRINT_SPEED_BOOST } field = value } diff --git a/src/main/java/de/bixilon/minosoft/data/registries/effects/StatusEffect.kt b/src/main/java/de/bixilon/minosoft/data/registries/effects/StatusEffect.kt index e9fee1d68..41c5215bf 100644 --- a/src/main/java/de/bixilon/minosoft/data/registries/effects/StatusEffect.kt +++ b/src/main/java/de/bixilon/minosoft/data/registries/effects/StatusEffect.kt @@ -13,7 +13,7 @@ package de.bixilon.minosoft.data.registries.effects import de.bixilon.minosoft.data.registries.ResourceLocation -import de.bixilon.minosoft.data.registries.effects.attributes.StatusEffectAttribute +import de.bixilon.minosoft.data.registries.effects.attributes.EntityAttributeModifier import de.bixilon.minosoft.data.registries.registries.Registries import de.bixilon.minosoft.data.registries.registries.registry.RegistryItem import de.bixilon.minosoft.data.registries.registries.registry.ResourceLocationDeserializer @@ -32,8 +32,8 @@ data class StatusEffect( val category: StatusEffectCategories, override val translationKey: ResourceLocation?, val color: RGBColor, - val attributes: Map, - val uuidAttributes: Map, + val attributes: Map, + val uuidAttributes: Map, ) : RegistryItem(), Translatable { override fun toString(): String { @@ -42,12 +42,12 @@ data class StatusEffect( companion object : ResourceLocationDeserializer { override fun deserialize(registries: Registries?, resourceLocation: ResourceLocation, data: Map): StatusEffect { - val attributes: MutableMap = mutableMapOf() - val uuidAttributes: MutableMap = mutableMapOf() + val attributes: MutableMap = mutableMapOf() + val uuidAttributes: MutableMap = mutableMapOf() data["attributes"]?.compoundCast()?.let { for ((key, value) in it) { - val attribute = StatusEffectAttribute.deserialize(value.asCompound()) + val attribute = EntityAttributeModifier.deserialize(value.asCompound()) attributes[ResourceLocation.getResourceLocation(key).fix()] = attribute uuidAttributes[attribute.uuid] = attribute } diff --git a/src/main/java/de/bixilon/minosoft/data/registries/effects/attributes/DefaultStatusEffectAttributes.kt b/src/main/java/de/bixilon/minosoft/data/registries/effects/attributes/DefaultStatusEffectAttributes.kt index 16fd14077..951b89df4 100644 --- a/src/main/java/de/bixilon/minosoft/data/registries/effects/attributes/DefaultStatusEffectAttributes.kt +++ b/src/main/java/de/bixilon/minosoft/data/registries/effects/attributes/DefaultStatusEffectAttributes.kt @@ -16,5 +16,5 @@ package de.bixilon.minosoft.data.registries.effects.attributes import de.bixilon.minosoft.util.KUtil.asUUID object DefaultStatusEffectAttributes { - val SPRINT_SPEED_BOOST = StatusEffectAttribute("Sprinting speed boost", "662A6B8D-DA3E-4C1C-8813-96EA6097278D".asUUID(), 0.30000001192092896, StatusEffectOperations.MULTIPLY_TOTAL) + val SPRINT_SPEED_BOOST = EntityAttributeModifier("Sprinting speed boost", "662A6B8D-DA3E-4C1C-8813-96EA6097278D".asUUID(), 0.30000001192092896, StatusEffectOperations.MULTIPLY_TOTAL) } diff --git a/src/main/java/de/bixilon/minosoft/data/registries/effects/attributes/StatusEffectAttributeInstance.kt b/src/main/java/de/bixilon/minosoft/data/registries/effects/attributes/EntityAttribute.kt similarity index 67% rename from src/main/java/de/bixilon/minosoft/data/registries/effects/attributes/StatusEffectAttributeInstance.kt rename to src/main/java/de/bixilon/minosoft/data/registries/effects/attributes/EntityAttribute.kt index 335a9a5b4..5df827af7 100644 --- a/src/main/java/de/bixilon/minosoft/data/registries/effects/attributes/StatusEffectAttributeInstance.kt +++ b/src/main/java/de/bixilon/minosoft/data/registries/effects/attributes/EntityAttribute.kt @@ -13,7 +13,17 @@ package de.bixilon.minosoft.data.registries.effects.attributes -class StatusEffectAttributeInstance( - val statusEffectAttribute: StatusEffectAttribute, - val amplifier: Int, -) +import de.bixilon.minosoft.util.KUtil.synchronizedMapOf +import java.util.* + +data class EntityAttribute( + var baseValue: Double = 1.0, + val modifiers: MutableMap = synchronizedMapOf(), +) { + fun merge(other: EntityAttribute) { + baseValue = other.baseValue + for ((key, modifier) in other.modifiers) { + modifiers[key] = modifier + } + } +} diff --git a/src/main/java/de/bixilon/minosoft/data/registries/effects/attributes/StatusEffectAttribute.kt b/src/main/java/de/bixilon/minosoft/data/registries/effects/attributes/EntityAttributeModifier.kt similarity index 90% rename from src/main/java/de/bixilon/minosoft/data/registries/effects/attributes/StatusEffectAttribute.kt rename to src/main/java/de/bixilon/minosoft/data/registries/effects/attributes/EntityAttributeModifier.kt index a2e12e967..31769da92 100644 --- a/src/main/java/de/bixilon/minosoft/data/registries/effects/attributes/StatusEffectAttribute.kt +++ b/src/main/java/de/bixilon/minosoft/data/registries/effects/attributes/EntityAttributeModifier.kt @@ -16,7 +16,7 @@ import de.bixilon.minosoft.util.KUtil.unsafeCast import de.bixilon.minosoft.util.Util import java.util.* -data class StatusEffectAttribute( +data class EntityAttributeModifier( val name: String, val uuid: UUID, val amount: Double, @@ -27,8 +27,8 @@ data class StatusEffectAttribute( } companion object { - fun deserialize(data: Map): StatusEffectAttribute { - return StatusEffectAttribute( + fun deserialize(data: Map): EntityAttributeModifier { + return EntityAttributeModifier( name = data["name"].unsafeCast(), uuid = Util.getUUIDFromString(data["uuid"].unsafeCast()), amount = data["amount"].unsafeCast(), diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/gui/hud/elements/hotbar/HotbarHealthElement.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/gui/hud/elements/hotbar/HotbarHealthElement.kt index 3e1b663cc..72e6416b7 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/gui/hud/elements/hotbar/HotbarHealthElement.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/gui/hud/elements/hotbar/HotbarHealthElement.kt @@ -26,6 +26,8 @@ import de.bixilon.minosoft.util.KUtil.decide import de.bixilon.minosoft.util.KUtil.unsafeCast import de.bixilon.minosoft.util.MMath.ceil import glm_.vec2.Vec2i +import java.lang.Float.max +import java.lang.Float.min class HotbarHealthElement(hudRenderer: HUDRenderer) : Element(hudRenderer), Pollable { private val witherStatusEffect = hudRenderer.connection.registries.statusEffectRegistry[DefaultStatusEffects.WITHER] @@ -234,13 +236,15 @@ class HotbarHealthElement(hudRenderer: HUDRenderer) : Element(hudRenderer), Poll val wither = witherStatusEffect?.let { player.activeStatusEffects[it] != null } ?: false val frozen = player.ticksFrozen > 0 + val absorptionsAmount = max(0.0f, player.playerAbsorptionHearts) // ToDo: This is (probably) calculated as effect instance + + val maxHealth = max(0.0f, player.getAttributeValue(DefaultStatusEffectAttributeNames.GENERIC_MAX_HEALTH).toFloat()) + var health = player.healthCondition.hp if (health > 0.0f && health < 0.5f) { health = 0.5f } - val absorptionsAmount = player.playerAbsorptionHearts // ToDo: This is (probably) calculated as effect instance - - val maxHealth = player.getAttributeValue(DefaultStatusEffectAttributeNames.GENERIC_MAX_HEALTH).toFloat() + health = min(health, maxHealth) if (this.hardcode == hardcode && this.poison == poison && this.wither == wither && this.frozen == frozen && this.health == health && this.absorptionsAmount == absorptionsAmount && this.maxHealth == maxHealth) { return false diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/EntityEffectAttributesS2CP.kt b/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/EntityEffectAttributesS2CP.kt index d7d732934..ca3721841 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/EntityEffectAttributesS2CP.kt +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/EntityEffectAttributesS2CP.kt @@ -13,8 +13,10 @@ package de.bixilon.minosoft.protocol.packets.s2c.play import de.bixilon.minosoft.data.registries.ResourceLocation -import de.bixilon.minosoft.data.registries.effects.attributes.StatusEffectAttribute +import de.bixilon.minosoft.data.registries.effects.attributes.EntityAttribute +import de.bixilon.minosoft.data.registries.effects.attributes.EntityAttributeModifier import de.bixilon.minosoft.data.registries.effects.attributes.StatusEffectOperations +import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer import de.bixilon.minosoft.protocol.protocol.ProtocolVersions.V_14W04A @@ -26,34 +28,44 @@ import java.util.* class EntityEffectAttributesS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() { val entityId: Int = buffer.readEntityId() - val attributes: Map + val attributes: Map init { - val attributes: MutableMap = mutableMapOf() - val count: Int = if (buffer.versionId < V_21W08A) { + val attributes: MutableMap = mutableMapOf() + val attributeCount: Int = if (buffer.versionId < V_21W08A) { buffer.readInt() } else { buffer.readVarInt() } - for (i in 0 until count) { + for (i in 0 until attributeCount) { val key: ResourceLocation = buffer.readResourceLocation() - val value: Double = buffer.readDouble() // ToDo: For what is this? - val listLength: Int = if (buffer.versionId < V_14W04A) { + val baseValue: Double = buffer.readDouble() + val attribute = EntityAttribute(baseValue = baseValue) + val modifierCount: Int = if (buffer.versionId < V_14W04A) { buffer.readUnsignedShort() } else { buffer.readVarInt() } - for (ii in 0 until listLength) { + for (ii in 0 until modifierCount) { val uuid: UUID = buffer.readUUID() val amount: Double = buffer.readDouble() val operation = StatusEffectOperations[buffer.readUnsignedByte()] - // ToDo: modifiers - attributes[key] = StatusEffectAttribute("", uuid, amount, operation) + attribute.modifiers[uuid] = EntityAttributeModifier(key.toString(), uuid, amount, operation) } + attributes[key] = attribute } this.attributes = attributes.toMap() } + override fun handle(connection: PlayConnection) { + connection.world.entities[entityId]?.let { + for ((key, attribute) in this.attributes) { + it.attributes.getOrPut(key) { EntityAttribute(baseValue = it.entityType.attributes[key] ?: 1.0) }.merge(attribute) + + } + } + } + override fun log() { Log.log(LogMessageType.NETWORK_PACKETS_IN, LogLevels.VERBOSE) { "Entity effect attributes (entityId=$entityId, attributes=$attributes)" } }