mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-08-14 23:57:35 +00:00
Entity scale attribute is now applied
This commit is contained in:
parent
8b7b8cdffd
commit
c963503fef
12 changed files with 56 additions and 33 deletions
|
@ -673,7 +673,7 @@ public final class EntityDefinitions {
|
|||
SLIME = EntityDefinition.inherited(SlimeEntity::new, mobEntityBase)
|
||||
.type(EntityType.SLIME)
|
||||
.heightAndWidth(0.51f)
|
||||
.addTranslator(MetadataType.INT, SlimeEntity::setScale)
|
||||
.addTranslator(MetadataType.INT, SlimeEntity::setSlimeScale)
|
||||
.build();
|
||||
MAGMA_CUBE = EntityDefinition.inherited(MagmaCubeEntity::new, SLIME)
|
||||
.type(EntityType.MAGMA_CUBE)
|
||||
|
|
|
@ -49,6 +49,7 @@ public enum GeyserAttributeType {
|
|||
ATTACK_KNOCKBACK("minecraft:generic.attack_knockback", null, 1.5f, Float.MAX_VALUE, 0f),
|
||||
ATTACK_SPEED("minecraft:generic.attack_speed", null, 0f, 1024f, 4f),
|
||||
MAX_HEALTH("minecraft:generic.max_health", null, 0f, 1024f, 20f),
|
||||
SCALE("minecraft:generic.scale", null, 0.0625f, 16f, 1f), // Unused. Do we need this?
|
||||
|
||||
// Bedrock Attributes
|
||||
ABSORPTION(null, "minecraft:absorption", 0f, 1024f, 0f),
|
||||
|
|
|
@ -86,6 +86,19 @@ public class LivingEntity extends Entity {
|
|||
*/
|
||||
private boolean isMaxFrozenState = false;
|
||||
|
||||
/**
|
||||
* The base scale entity data, without attributes applied. Used for such cases as baby variants.
|
||||
*/
|
||||
@Getter(AccessLevel.NONE)
|
||||
@Setter(AccessLevel.NONE)
|
||||
private float scale;
|
||||
/**
|
||||
* The scale sent through the Java attributes packet
|
||||
*/
|
||||
@Getter(AccessLevel.NONE)
|
||||
@Setter(AccessLevel.NONE)
|
||||
private float attributeScale;
|
||||
|
||||
public LivingEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
@ -122,6 +135,9 @@ public class LivingEntity extends Entity {
|
|||
|
||||
@Override
|
||||
protected void initializeMetadata() {
|
||||
// Initialize here so overriding classes don't have 0 values
|
||||
this.scale = 1f;
|
||||
this.attributeScale = 1f;
|
||||
super.initializeMetadata();
|
||||
// Matches Bedrock behavior; is always set to this
|
||||
dirtyMetadata.put(EntityDataTypes.STRUCTURAL_INTEGRITY, 1);
|
||||
|
@ -230,6 +246,21 @@ public class LivingEntity extends Entity {
|
|||
return freezingPercentage;
|
||||
}
|
||||
|
||||
protected void setScale(float scale) {
|
||||
this.scale = scale;
|
||||
applyScale();
|
||||
}
|
||||
|
||||
private void setAttributeScale(float scale) {
|
||||
this.attributeScale = scale;
|
||||
applyScale();
|
||||
}
|
||||
|
||||
private void applyScale() {
|
||||
// Take any adjustments Bedrock requires, and compute it alongside the attribute's additional changes
|
||||
this.dirtyMetadata.put(EntityDataTypes.SCALE, scale * attributeScale);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a Bedrock health attribute constructed from the data sent from the server
|
||||
*/
|
||||
|
@ -366,6 +397,11 @@ public class LivingEntity extends Entity {
|
|||
case GENERIC_FOLLOW_RANGE -> newAttributes.add(calculateAttribute(javaAttribute, GeyserAttributeType.FOLLOW_RANGE));
|
||||
case GENERIC_KNOCKBACK_RESISTANCE -> newAttributes.add(calculateAttribute(javaAttribute, GeyserAttributeType.KNOCKBACK_RESISTANCE));
|
||||
case GENERIC_JUMP_STRENGTH -> newAttributes.add(calculateAttribute(javaAttribute, GeyserAttributeType.HORSE_JUMP_STRENGTH));
|
||||
case GENERIC_SCALE -> {
|
||||
// Attribute on Java, entity data on Bedrock
|
||||
setAttributeScale((float) AttributeUtils.calculateValue(javaAttribute));
|
||||
updateBedrockMetadata();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
package org.geysermc.geyser.entity.type.living;
|
||||
|
||||
import org.cloudburstmc.math.vector.Vector3f;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
@ -44,12 +43,12 @@ public class AgeableEntity extends CreatureEntity {
|
|||
protected void initializeMetadata() {
|
||||
super.initializeMetadata();
|
||||
// Required as of 1.19.3 Java
|
||||
dirtyMetadata.put(EntityDataTypes.SCALE, getAdultSize());
|
||||
setScale(getAdultSize());
|
||||
}
|
||||
|
||||
public void setBaby(BooleanEntityMetadata entityMetadata) {
|
||||
boolean isBaby = entityMetadata.getPrimitiveValue();
|
||||
dirtyMetadata.put(EntityDataTypes.SCALE, isBaby ? getBabySize() : getAdultSize());
|
||||
setScale(isBaby ? getBabySize() : getAdultSize());
|
||||
setFlag(EntityFlag.BABY, isBaby);
|
||||
|
||||
setBoundingBoxHeight(definition.height() * (isBaby ? getBabySize() : getAdultSize()));
|
||||
|
|
|
@ -311,7 +311,7 @@ public class ArmorStandEntity extends LivingEntity {
|
|||
if (!isInvisible) {
|
||||
// The armor stand isn't invisible. We good.
|
||||
setFlag(EntityFlag.INVISIBLE, false);
|
||||
dirtyMetadata.put(EntityDataTypes.SCALE, getScale());
|
||||
setScale(getScale());
|
||||
updateOffsetRequirement(false);
|
||||
|
||||
if (secondEntity != null) {
|
||||
|
@ -327,7 +327,7 @@ public class ArmorStandEntity extends LivingEntity {
|
|||
if (!isNametagEmpty && (!helmet.equals(ItemData.AIR) || !chestplate.equals(ItemData.AIR) || !leggings.equals(ItemData.AIR)
|
||||
|| !boots.equals(ItemData.AIR) || !hand.equals(ItemData.AIR) || !offhand.equals(ItemData.AIR))) {
|
||||
// Reset scale of the proper armor stand
|
||||
this.dirtyMetadata.put(EntityDataTypes.SCALE, getScale());
|
||||
setScale(getScale());
|
||||
// Set the proper armor stand to invisible to show armor
|
||||
setFlag(EntityFlag.INVISIBLE, true);
|
||||
// Update the position of the armor stand
|
||||
|
@ -350,7 +350,7 @@ public class ArmorStandEntity extends LivingEntity {
|
|||
// Guarantee this copy is NOT invisible
|
||||
secondEntity.setFlag(EntityFlag.INVISIBLE, false);
|
||||
// Scale to 0 to show nametag
|
||||
secondEntity.getDirtyMetadata().put(EntityDataTypes.SCALE, 0.0f);
|
||||
secondEntity.setScale(0f);
|
||||
// No bounding box as we don't want to interact with this entity
|
||||
secondEntity.getDirtyMetadata().put(EntityDataTypes.WIDTH, 0.0f);
|
||||
secondEntity.getDirtyMetadata().put(EntityDataTypes.HEIGHT, 0.0f);
|
||||
|
@ -360,7 +360,7 @@ public class ArmorStandEntity extends LivingEntity {
|
|||
} else if (isNametagEmpty) {
|
||||
// We can just make an invisible entity
|
||||
// Reset scale of the proper armor stand
|
||||
dirtyMetadata.put(EntityDataTypes.SCALE, getScale());
|
||||
setScale(getScale());
|
||||
// Set the proper armor stand to invisible to show armor
|
||||
setFlag(EntityFlag.INVISIBLE, true);
|
||||
// Update offset
|
||||
|
@ -374,7 +374,7 @@ public class ArmorStandEntity extends LivingEntity {
|
|||
// Nametag is not empty and there is no armor
|
||||
// We don't need to make a new entity
|
||||
setFlag(EntityFlag.INVISIBLE, false);
|
||||
dirtyMetadata.put(EntityDataTypes.SCALE, 0.0f);
|
||||
setScale(0f);
|
||||
// As the above is applied, we need an offset
|
||||
updateOffsetRequirement(!isMarker);
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
package org.geysermc.geyser.entity.type.living;
|
||||
|
||||
import org.cloudburstmc.math.vector.Vector3f;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata;
|
||||
|
@ -39,8 +38,8 @@ public class SlimeEntity extends MobEntity {
|
|||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
public void setScale(IntEntityMetadata entityMetadata) {
|
||||
dirtyMetadata.put(EntityDataTypes.SCALE, 0.10f + entityMetadata.getPrimitiveValue());
|
||||
public void setSlimeScale(IntEntityMetadata entityMetadata) {
|
||||
setScale(0.10f + entityMetadata.getPrimitiveValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
package org.geysermc.geyser.entity.type.living.monster;
|
||||
|
||||
import org.cloudburstmc.math.vector.Vector3f;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
||||
|
@ -36,7 +35,11 @@ public class GiantEntity extends MonsterEntity {
|
|||
|
||||
public GiantEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
dirtyMetadata.put(EntityDataTypes.SCALE, 6f);
|
||||
@Override
|
||||
protected void initializeMetadata() {
|
||||
super.initializeMetadata();
|
||||
setScale(6f);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
package org.geysermc.geyser.entity.type.living.monster;
|
||||
|
||||
import org.cloudburstmc.math.vector.Vector3f;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.entity.type.living.FlyingEntity;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
@ -46,7 +45,7 @@ public class PhantomEntity extends FlyingEntity {
|
|||
|
||||
setBoundingBoxWidth(boundsScale * definition.width());
|
||||
setBoundingBoxHeight(boundsScale * definition.height());
|
||||
dirtyMetadata.put(EntityDataTypes.SCALE, modelScale);
|
||||
setScale(modelScale);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -27,7 +27,6 @@ package org.geysermc.geyser.entity.type.living.monster;
|
|||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.cloudburstmc.math.vector.Vector3f;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
|
@ -49,7 +48,7 @@ public class PiglinEntity extends BasePiglinEntity {
|
|||
|
||||
public void setBaby(BooleanEntityMetadata entityMetadata) {
|
||||
boolean isBaby = entityMetadata.getPrimitiveValue();
|
||||
dirtyMetadata.put(EntityDataTypes.SCALE, isBaby? .55f : 1f);
|
||||
setScale(isBaby? .55f : 1f);
|
||||
setFlag(EntityFlag.BABY, isBaby);
|
||||
|
||||
updateMountOffset();
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
package org.geysermc.geyser.entity.type.living.monster;
|
||||
|
||||
import org.cloudburstmc.math.vector.Vector3f;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
@ -43,7 +42,7 @@ public class ZoglinEntity extends MonsterEntity {
|
|||
public void setBaby(BooleanEntityMetadata entityMetadata) {
|
||||
boolean isBaby = entityMetadata.getPrimitiveValue();
|
||||
if (isBaby != getFlag(EntityFlag.BABY)) {
|
||||
dirtyMetadata.put(EntityDataTypes.SCALE, isBaby ? .55f : 1f);
|
||||
setScale(isBaby ? .55f : 1f);
|
||||
setFlag(EntityFlag.BABY, isBaby);
|
||||
|
||||
updatePassengerOffsets();
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
package org.geysermc.geyser.entity.type.living.monster;
|
||||
|
||||
import org.cloudburstmc.math.vector.Vector3f;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
@ -43,7 +42,7 @@ public class ZombieEntity extends MonsterEntity {
|
|||
|
||||
public void setZombieBaby(BooleanEntityMetadata entityMetadata) {
|
||||
boolean isBaby = entityMetadata.getPrimitiveValue();
|
||||
dirtyMetadata.put(EntityDataTypes.SCALE, isBaby ? .55f : 1.0f);
|
||||
setScale(isBaby ? .55f : 1.0f);
|
||||
setFlag(EntityFlag.BABY, isBaby);
|
||||
|
||||
updateMountOffset();
|
||||
|
|
|
@ -168,17 +168,6 @@ public class MathUtils {
|
|||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the resulting object is a byte. Java Edition does not care whether a byte is encoded as an integer or not;
|
||||
* it converts it into a byte anyway.
|
||||
*
|
||||
* @param value The value to convert
|
||||
* @return The converted byte
|
||||
*/
|
||||
public static byte getNbtByte(Object value) {
|
||||
return ((Number) value).byteValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Packs a chunk's X and Z coordinates into a single {@code long}.
|
||||
*
|
||||
|
|
Loading…
Reference in a new issue