mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-14 18:05:51 -04:00
fix entity attribute stuff
This commit is contained in:
parent
2008dcba18
commit
34f15d2baf
@ -26,8 +26,8 @@ import de.bixilon.minosoft.data.registries.AABB
|
|||||||
import de.bixilon.minosoft.data.registries.ResourceLocation
|
import de.bixilon.minosoft.data.registries.ResourceLocation
|
||||||
import de.bixilon.minosoft.data.registries.blocks.types.FluidBlock
|
import de.bixilon.minosoft.data.registries.blocks.types.FluidBlock
|
||||||
import de.bixilon.minosoft.data.registries.effects.StatusEffect
|
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.EntityAttribute
|
||||||
import de.bixilon.minosoft.data.registries.effects.attributes.StatusEffectAttributeInstance
|
import de.bixilon.minosoft.data.registries.effects.attributes.EntityAttributeModifier
|
||||||
import de.bixilon.minosoft.data.registries.effects.attributes.StatusEffectOperations
|
import de.bixilon.minosoft.data.registries.effects.attributes.StatusEffectOperations
|
||||||
import de.bixilon.minosoft.data.registries.enchantment.Enchantment
|
import de.bixilon.minosoft.data.registries.enchantment.Enchantment
|
||||||
import de.bixilon.minosoft.data.registries.entities.EntityType
|
import de.bixilon.minosoft.data.registries.entities.EntityType
|
||||||
@ -72,7 +72,7 @@ abstract class Entity(
|
|||||||
protected val random = Random
|
protected val random = Random
|
||||||
open val equipment: MutableMap<EquipmentSlots, ItemStack> = mutableMapOf()
|
open val equipment: MutableMap<EquipmentSlots, ItemStack> = mutableMapOf()
|
||||||
val activeStatusEffects: MutableMap<StatusEffect, StatusEffectInstance> = synchronizedMapOf()
|
val activeStatusEffects: MutableMap<StatusEffect, StatusEffectInstance> = synchronizedMapOf()
|
||||||
val attributes: MutableMap<ResourceLocation, MutableMap<UUID, StatusEffectAttributeInstance>> = synchronizedMapOf()
|
val attributes: MutableMap<ResourceLocation, EntityAttribute> = synchronizedMapOf()
|
||||||
|
|
||||||
val id: Int?
|
val id: Int?
|
||||||
get() = connection.world.entities.getId(this)
|
get() = connection.world.entities.getId(this)
|
||||||
@ -154,28 +154,30 @@ abstract class Entity(
|
|||||||
activeStatusEffects.remove(effect)
|
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
|
// 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) {
|
fun addToValue(modifier: EntityAttributeModifier, amplifier: Int) {
|
||||||
val instanceValue = statusEffectAttribute.amount * amplifier
|
val instanceValue = modifier.amount * amplifier
|
||||||
when (statusEffectAttribute.operation) {
|
when (modifier.operation) {
|
||||||
StatusEffectOperations.MULTIPLY_TOTAL -> ret *= 1.0 + instanceValue
|
StatusEffectOperations.MULTIPLY_TOTAL -> ret *= 1.0 + instanceValue
|
||||||
StatusEffectOperations.ADDITION -> ret += instanceValue
|
StatusEffectOperations.ADDITION -> ret += instanceValue
|
||||||
StatusEffectOperations.MULTIPLY_BASE -> ret += baseValue * (instanceValue + 1.0)
|
StatusEffectOperations.MULTIPLY_BASE -> ret += realBaseValue * (instanceValue + 1.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
attributes[attribute]?.let {
|
attribute?.let {
|
||||||
for (instance in it.values) {
|
for (instance in it.modifiers.values) {
|
||||||
addToValue(instance.statusEffectAttribute, instance.amplifier)
|
addToValue(instance, 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (statusEffect in activeStatusEffects.values) {
|
for (statusEffect in activeStatusEffects.values) {
|
||||||
for ((instanceResourceLocation, instance) in statusEffect.statusEffect.attributes) {
|
for ((instanceResourceLocation, instance) in statusEffect.statusEffect.attributes) {
|
||||||
if (instanceResourceLocation != attribute) {
|
if (instanceResourceLocation != name) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
addToValue(instance, statusEffect.amplifier)
|
addToValue(instance, statusEffect.amplifier)
|
||||||
|
@ -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.DefaultStatusEffects
|
||||||
import de.bixilon.minosoft.data.registries.effects.attributes.DefaultStatusEffectAttributeNames
|
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.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.enchantment.DefaultEnchantments
|
||||||
import de.bixilon.minosoft.data.registries.items.DefaultItems
|
import de.bixilon.minosoft.data.registries.items.DefaultItems
|
||||||
import de.bixilon.minosoft.data.registries.items.Item
|
import de.bixilon.minosoft.data.registries.items.Item
|
||||||
@ -133,10 +133,10 @@ class LocalPlayerEntity(
|
|||||||
if (value == field) {
|
if (value == field) {
|
||||||
return
|
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) {
|
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
|
field = value
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
package de.bixilon.minosoft.data.registries.effects
|
package de.bixilon.minosoft.data.registries.effects
|
||||||
|
|
||||||
import de.bixilon.minosoft.data.registries.ResourceLocation
|
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.Registries
|
||||||
import de.bixilon.minosoft.data.registries.registries.registry.RegistryItem
|
import de.bixilon.minosoft.data.registries.registries.registry.RegistryItem
|
||||||
import de.bixilon.minosoft.data.registries.registries.registry.ResourceLocationDeserializer
|
import de.bixilon.minosoft.data.registries.registries.registry.ResourceLocationDeserializer
|
||||||
@ -32,8 +32,8 @@ data class StatusEffect(
|
|||||||
val category: StatusEffectCategories,
|
val category: StatusEffectCategories,
|
||||||
override val translationKey: ResourceLocation?,
|
override val translationKey: ResourceLocation?,
|
||||||
val color: RGBColor,
|
val color: RGBColor,
|
||||||
val attributes: Map<ResourceLocation, StatusEffectAttribute>,
|
val attributes: Map<ResourceLocation, EntityAttributeModifier>,
|
||||||
val uuidAttributes: Map<UUID, StatusEffectAttribute>,
|
val uuidAttributes: Map<UUID, EntityAttributeModifier>,
|
||||||
) : RegistryItem(), Translatable {
|
) : RegistryItem(), Translatable {
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
@ -42,12 +42,12 @@ data class StatusEffect(
|
|||||||
|
|
||||||
companion object : ResourceLocationDeserializer<StatusEffect> {
|
companion object : ResourceLocationDeserializer<StatusEffect> {
|
||||||
override fun deserialize(registries: Registries?, resourceLocation: ResourceLocation, data: Map<String, Any>): StatusEffect {
|
override fun deserialize(registries: Registries?, resourceLocation: ResourceLocation, data: Map<String, Any>): StatusEffect {
|
||||||
val attributes: MutableMap<ResourceLocation, StatusEffectAttribute> = mutableMapOf()
|
val attributes: MutableMap<ResourceLocation, EntityAttributeModifier> = mutableMapOf()
|
||||||
val uuidAttributes: MutableMap<UUID, StatusEffectAttribute> = mutableMapOf()
|
val uuidAttributes: MutableMap<UUID, EntityAttributeModifier> = mutableMapOf()
|
||||||
|
|
||||||
data["attributes"]?.compoundCast()?.let {
|
data["attributes"]?.compoundCast()?.let {
|
||||||
for ((key, value) in it) {
|
for ((key, value) in it) {
|
||||||
val attribute = StatusEffectAttribute.deserialize(value.asCompound())
|
val attribute = EntityAttributeModifier.deserialize(value.asCompound())
|
||||||
attributes[ResourceLocation.getResourceLocation(key).fix()] = attribute
|
attributes[ResourceLocation.getResourceLocation(key).fix()] = attribute
|
||||||
uuidAttributes[attribute.uuid] = attribute
|
uuidAttributes[attribute.uuid] = attribute
|
||||||
}
|
}
|
||||||
|
@ -16,5 +16,5 @@ package de.bixilon.minosoft.data.registries.effects.attributes
|
|||||||
import de.bixilon.minosoft.util.KUtil.asUUID
|
import de.bixilon.minosoft.util.KUtil.asUUID
|
||||||
|
|
||||||
object DefaultStatusEffectAttributes {
|
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)
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,17 @@
|
|||||||
|
|
||||||
package de.bixilon.minosoft.data.registries.effects.attributes
|
package de.bixilon.minosoft.data.registries.effects.attributes
|
||||||
|
|
||||||
class StatusEffectAttributeInstance(
|
import de.bixilon.minosoft.util.KUtil.synchronizedMapOf
|
||||||
val statusEffectAttribute: StatusEffectAttribute,
|
import java.util.*
|
||||||
val amplifier: Int,
|
|
||||||
)
|
data class EntityAttribute(
|
||||||
|
var baseValue: Double = 1.0,
|
||||||
|
val modifiers: MutableMap<UUID, EntityAttributeModifier> = synchronizedMapOf(),
|
||||||
|
) {
|
||||||
|
fun merge(other: EntityAttribute) {
|
||||||
|
baseValue = other.baseValue
|
||||||
|
for ((key, modifier) in other.modifiers) {
|
||||||
|
modifiers[key] = modifier
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -16,7 +16,7 @@ import de.bixilon.minosoft.util.KUtil.unsafeCast
|
|||||||
import de.bixilon.minosoft.util.Util
|
import de.bixilon.minosoft.util.Util
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
data class StatusEffectAttribute(
|
data class EntityAttributeModifier(
|
||||||
val name: String,
|
val name: String,
|
||||||
val uuid: UUID,
|
val uuid: UUID,
|
||||||
val amount: Double,
|
val amount: Double,
|
||||||
@ -27,8 +27,8 @@ data class StatusEffectAttribute(
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun deserialize(data: Map<String, Any>): StatusEffectAttribute {
|
fun deserialize(data: Map<String, Any>): EntityAttributeModifier {
|
||||||
return StatusEffectAttribute(
|
return EntityAttributeModifier(
|
||||||
name = data["name"].unsafeCast(),
|
name = data["name"].unsafeCast(),
|
||||||
uuid = Util.getUUIDFromString(data["uuid"].unsafeCast()),
|
uuid = Util.getUUIDFromString(data["uuid"].unsafeCast()),
|
||||||
amount = data["amount"].unsafeCast(),
|
amount = data["amount"].unsafeCast(),
|
@ -26,6 +26,8 @@ import de.bixilon.minosoft.util.KUtil.decide
|
|||||||
import de.bixilon.minosoft.util.KUtil.unsafeCast
|
import de.bixilon.minosoft.util.KUtil.unsafeCast
|
||||||
import de.bixilon.minosoft.util.MMath.ceil
|
import de.bixilon.minosoft.util.MMath.ceil
|
||||||
import glm_.vec2.Vec2i
|
import glm_.vec2.Vec2i
|
||||||
|
import java.lang.Float.max
|
||||||
|
import java.lang.Float.min
|
||||||
|
|
||||||
class HotbarHealthElement(hudRenderer: HUDRenderer) : Element(hudRenderer), Pollable {
|
class HotbarHealthElement(hudRenderer: HUDRenderer) : Element(hudRenderer), Pollable {
|
||||||
private val witherStatusEffect = hudRenderer.connection.registries.statusEffectRegistry[DefaultStatusEffects.WITHER]
|
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 wither = witherStatusEffect?.let { player.activeStatusEffects[it] != null } ?: false
|
||||||
val frozen = player.ticksFrozen > 0
|
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
|
var health = player.healthCondition.hp
|
||||||
if (health > 0.0f && health < 0.5f) {
|
if (health > 0.0f && health < 0.5f) {
|
||||||
health = 0.5f
|
health = 0.5f
|
||||||
}
|
}
|
||||||
val absorptionsAmount = player.playerAbsorptionHearts // ToDo: This is (probably) calculated as effect instance
|
health = min(health, maxHealth)
|
||||||
|
|
||||||
val maxHealth = player.getAttributeValue(DefaultStatusEffectAttributeNames.GENERIC_MAX_HEALTH).toFloat()
|
|
||||||
|
|
||||||
if (this.hardcode == hardcode && this.poison == poison && this.wither == wither && this.frozen == frozen && this.health == health && this.absorptionsAmount == absorptionsAmount && this.maxHealth == 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
|
return false
|
||||||
|
@ -13,8 +13,10 @@
|
|||||||
package de.bixilon.minosoft.protocol.packets.s2c.play
|
package de.bixilon.minosoft.protocol.packets.s2c.play
|
||||||
|
|
||||||
import de.bixilon.minosoft.data.registries.ResourceLocation
|
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.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.packets.s2c.PlayS2CPacket
|
||||||
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
|
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
|
||||||
import de.bixilon.minosoft.protocol.protocol.ProtocolVersions.V_14W04A
|
import de.bixilon.minosoft.protocol.protocol.ProtocolVersions.V_14W04A
|
||||||
@ -26,34 +28,44 @@ import java.util.*
|
|||||||
|
|
||||||
class EntityEffectAttributesS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() {
|
class EntityEffectAttributesS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() {
|
||||||
val entityId: Int = buffer.readEntityId()
|
val entityId: Int = buffer.readEntityId()
|
||||||
val attributes: Map<ResourceLocation, StatusEffectAttribute>
|
val attributes: Map<ResourceLocation, EntityAttribute>
|
||||||
|
|
||||||
init {
|
init {
|
||||||
val attributes: MutableMap<ResourceLocation, StatusEffectAttribute> = mutableMapOf()
|
val attributes: MutableMap<ResourceLocation, EntityAttribute> = mutableMapOf()
|
||||||
val count: Int = if (buffer.versionId < V_21W08A) {
|
val attributeCount: Int = if (buffer.versionId < V_21W08A) {
|
||||||
buffer.readInt()
|
buffer.readInt()
|
||||||
} else {
|
} else {
|
||||||
buffer.readVarInt()
|
buffer.readVarInt()
|
||||||
}
|
}
|
||||||
for (i in 0 until count) {
|
for (i in 0 until attributeCount) {
|
||||||
val key: ResourceLocation = buffer.readResourceLocation()
|
val key: ResourceLocation = buffer.readResourceLocation()
|
||||||
val value: Double = buffer.readDouble() // ToDo: For what is this?
|
val baseValue: Double = buffer.readDouble()
|
||||||
val listLength: Int = if (buffer.versionId < V_14W04A) {
|
val attribute = EntityAttribute(baseValue = baseValue)
|
||||||
|
val modifierCount: Int = if (buffer.versionId < V_14W04A) {
|
||||||
buffer.readUnsignedShort()
|
buffer.readUnsignedShort()
|
||||||
} else {
|
} else {
|
||||||
buffer.readVarInt()
|
buffer.readVarInt()
|
||||||
}
|
}
|
||||||
for (ii in 0 until listLength) {
|
for (ii in 0 until modifierCount) {
|
||||||
val uuid: UUID = buffer.readUUID()
|
val uuid: UUID = buffer.readUUID()
|
||||||
val amount: Double = buffer.readDouble()
|
val amount: Double = buffer.readDouble()
|
||||||
val operation = StatusEffectOperations[buffer.readUnsignedByte()]
|
val operation = StatusEffectOperations[buffer.readUnsignedByte()]
|
||||||
// ToDo: modifiers
|
attribute.modifiers[uuid] = EntityAttributeModifier(key.toString(), uuid, amount, operation)
|
||||||
attributes[key] = StatusEffectAttribute("", uuid, amount, operation)
|
|
||||||
}
|
}
|
||||||
|
attributes[key] = attribute
|
||||||
}
|
}
|
||||||
this.attributes = attributes.toMap()
|
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() {
|
override fun log() {
|
||||||
Log.log(LogMessageType.NETWORK_PACKETS_IN, LogLevels.VERBOSE) { "Entity effect attributes (entityId=$entityId, attributes=$attributes)" }
|
Log.log(LogMessageType.NETWORK_PACKETS_IN, LogLevels.VERBOSE) { "Entity effect attributes (entityId=$entityId, attributes=$attributes)" }
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user