Merge remote-tracking branch 'upstream/feature/1.20.5' into feature/1.20.5

This commit is contained in:
onebeastchris 2024-04-30 21:48:41 +02:00
commit 51cbbba47c
17 changed files with 75 additions and 44 deletions

View File

@ -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)

View File

@ -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),

View File

@ -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();
}
}
}
}

View File

@ -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()));

View File

@ -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);

View File

@ -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

View File

@ -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);
}
}

View File

@ -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

View File

@ -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();

View File

@ -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();

View File

@ -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();

View File

@ -25,6 +25,7 @@
package org.geysermc.geyser.inventory;
import net.kyori.adventure.text.Component;
import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType;
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundRenameItemPacket;
import lombok.Getter;
@ -72,10 +73,9 @@ public class AnvilContainer extends Container {
String correctRename;
newName = rename;
// TODO 1.20.5 fix properly - this name is apparently nullable??
String originalName = MessageTranslator.convertMessage(ItemUtils.getCustomName(getInput().getComponents()));
Component originalName = ItemUtils.getCustomName(getInput().getComponents());
String plainOriginalName = MessageTranslator.convertToPlainTextLenient(originalName, session.locale());
String plainOriginalName = MessageTranslator.convertToPlainText(originalName, session.locale());
String plainNewName = MessageTranslator.convertToPlainText(rename);
if (!plainOriginalName.equals(plainNewName)) {
// Strip out formatting since Java Edition does not allow it
@ -85,7 +85,7 @@ public class AnvilContainer extends Container {
session.sendDownstreamGamePacket(renameItemPacket);
} else {
// Restore formatting for item since we're not renaming
correctRename = MessageTranslator.convertMessageLenient(originalName);
correctRename = MessageTranslator.convertMessage(originalName, session.locale());
// Java Edition sends the original custom name when not renaming,
// if there isn't a custom name an empty string is sent
ServerboundRenameItemPacket renameItemPacket = new ServerboundRenameItemPacket(plainOriginalName);

View File

@ -118,8 +118,7 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
// Changing the item in the input slot resets the name field on Bedrock, but
// does not result in a FilterTextPacket
// TODO test
String originalName = MessageTranslator.convertToPlainText(ItemUtils.getCustomName(input.getComponents()));
String originalName = MessageTranslator.convertToPlainText(ItemUtils.getCustomName(input.getComponents()), session.locale());
ServerboundRenameItemPacket renameItemPacket = new ServerboundRenameItemPacket(originalName);
session.sendDownstreamGamePacket(renameItemPacket);
@ -388,7 +387,7 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
}
return enchantments;
}
return Object2IntMaps.emptyMap();
return new Object2IntOpenHashMap<>();
}
private boolean isEnchantedBook(GeyserItemStack itemStack) {

View File

@ -146,6 +146,11 @@ public class Item {
if (!enchantNbtList.isEmpty()) {
builder.putList("ench", NbtType.COMPOUND, enchantNbtList);
}
Integer repairCost = components.get(DataComponentType.REPAIR_COST);
if (repairCost != null) {
builder.putInt("RepairCost", repairCost);
}
}
/**

View File

@ -260,13 +260,17 @@ public class MessageTranslator {
}
/**
* Convert legacy format message to plain text
* Convert a Java message to plain text
*
* @param message Message to convert
* @param locale Locale to use for translation strings
* @return The plain text of the message
*/
public static String convertToPlainText(Component message) {
return PlainTextComponentSerializer.plainText().serialize(message);
public static String convertToPlainText(Component message, String locale) {
if (message == null) {
return "";
}
return PlainTextComponentSerializer.plainText().serialize(RENDERER.render(message, locale));
}
/**

View File

@ -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}.
*

View File

@ -15,7 +15,7 @@ protocol-connection = "3.0.0.Beta1-20240411.165033-128"
raknet = "1.0.0.CR3-20240416.144209-1"
blockstateupdater="1.20.80-20240411.142413-1"
mcauthlib = "d9d773e"
mcprotocollib = "400f1b4" # Revert from jitpack after release
mcprotocollib = "bc8526b" # Revert from jitpack after release
adventure = "4.14.0"
adventure-platform = "4.3.0"
junit = "5.9.2"