+ * WARNING: The scaling attribute was introduced in {@code 1.20.5}.
+ * Do NOT attempt to use this helper for protocols older than {@code 1.20.4 -> 1.20.3}.
+ * Sending the {@code minecraft:scale} attribute to older clients will cause an instant disconnect!
+ *
+ * @param type The entity type that requires scaling when it is a baby.
+ * @param babyScaleFactor The multiplier to apply to the generic.scale attribute when it is a baby.
+ * @param babyIndex The metadata index for the is_baby property in this specific protocol
+ */
+ public void addBabyScale(EntityType type, float babyScaleFactor, int babyIndex) {
+ babyScales.put(type, new BabyScale(babyScaleFactor, babyIndex));
+ }
+
+ public Iterable
+ * WARNING: The scaling attribute was introduced in {@code 1.20.5}.
+ * Do NOT attempt to register this listener for protocols older than {@code 1.20.4 -> 1.20.3}.
+ *
+ * @param packetType The UPDATE_ATTRIBUTES packet type for the protocol.
+ */
+ @Override
+ public void register1_21(C packetType) {
+ scaleProtocol.registerClientbound(packetType, wrapper -> {
+ final int entityId = wrapper.passthrough(Types.VAR_INT);
+
+ // Fast lookup for scaling factor, negligible overhead if not present
+ float scale = 1.0f;
+ com.viaversion.viaversion.api.data.entity.EntityTracker tracker = wrapper.user().getEntityTracker(scaleProtocol.getClass());
+ if (tracker != null) {
+ StoredEntityData data = tracker.entityDataIfPresent(entityId);
+ if (data != null && data.has(EntityScaleData.class)) {
+ scale = data.get(EntityScaleData.class).getScale();
+ }
+ }
+
+ final int size = wrapper.passthrough(Types.VAR_INT);
+ int newSize = size;
+
+ int scaleId = -1;
+ if (scaleProtocol.getMappingData().getAttributeMappings() != null) {
+ scaleId = scaleProtocol.getMappingData().getAttributeMappings().id("minecraft:scale");
+ }
+
+ for (int i = 0; i < size; i++) {
+ final int attributeId = wrapper.read(Types.VAR_INT);
+ final int mappedId = scaleProtocol.getMappingData().getNewAttributeId(attributeId);
+ if (mappedId == -1) {
+ newSize--;
+
+ wrapper.read(Types.DOUBLE); // Base
+ final int modifierSize = wrapper.read(Types.VAR_INT);
+ for (int j = 0; j < modifierSize; j++) {
+ wrapper.read(Types.STRING); // ID
+ wrapper.read(Types.DOUBLE); // Amount
+ wrapper.read(Types.BYTE); // Operation
+ }
+ continue;
+ }
+
+ wrapper.write(Types.VAR_INT, mappedId);
+ double value = wrapper.read(Types.DOUBLE); // Base
+
+ // Multiply the server's requested scale by our tracked scale modifier
+ if (scale != 1.0f && scaleId != -1 && attributeId == scaleId) {
+ value *= scale;
+ }
+ wrapper.write(Types.DOUBLE, value);
+
+ final int modifierSize = wrapper.passthrough(Types.VAR_INT);
+ for (int j = 0; j < modifierSize; j++) {
+ wrapper.passthrough(Types.STRING); // ID
+ wrapper.passthrough(Types.DOUBLE); // Amount
+ wrapper.passthrough(Types.BYTE); // Operation
+ }
+ }
+
+ if (size != newSize) {
+ wrapper.set(Types.VAR_INT, 1, newSize);
+ }
+ });
+ }
+}
diff --git a/common/src/main/java/com/viaversion/viabackwards/protocol/v1_21_2to1_21/Protocol1_21_2To1_21.java b/common/src/main/java/com/viaversion/viabackwards/protocol/v1_21_2to1_21/Protocol1_21_2To1_21.java
index f69ff0ab..c47c7d7d 100644
--- a/common/src/main/java/com/viaversion/viabackwards/protocol/v1_21_2to1_21/Protocol1_21_2To1_21.java
+++ b/common/src/main/java/com/viaversion/viabackwards/protocol/v1_21_2to1_21/Protocol1_21_2To1_21.java
@@ -88,7 +88,7 @@ protected void registerPackets() {
particleRewriter.registerLevelParticles1_20_5(ClientboundPackets1_21_2.LEVEL_PARTICLES);
new StatisticsRewriter<>(this).register(ClientboundPackets1_21_2.AWARD_STATS);
- new AttributeRewriter<>(this).register1_21(ClientboundPackets1_21_2.UPDATE_ATTRIBUTES);
+ new com.viaversion.viabackwards.api.rewriters.EntityScaleAttributeRewriter<>(this).register1_21(ClientboundPackets1_21_2.UPDATE_ATTRIBUTES);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_2.SET_ACTION_BAR_TEXT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_2.SET_TITLE_TEXT);
diff --git a/common/src/main/java/com/viaversion/viabackwards/protocol/v1_21_2to1_21/rewriter/EntityPacketRewriter1_21_2.java b/common/src/main/java/com/viaversion/viabackwards/protocol/v1_21_2to1_21/rewriter/EntityPacketRewriter1_21_2.java
index 82be0892..6290d567 100644
--- a/common/src/main/java/com/viaversion/viabackwards/protocol/v1_21_2to1_21/rewriter/EntityPacketRewriter1_21_2.java
+++ b/common/src/main/java/com/viaversion/viabackwards/protocol/v1_21_2to1_21/rewriter/EntityPacketRewriter1_21_2.java
@@ -23,6 +23,7 @@
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viabackwards.ViaBackwards;
+import com.viaversion.viabackwards.api.entities.EntityScaleHelper;
import com.viaversion.viabackwards.api.rewriters.BackwardsRegistryRewriter;
import com.viaversion.viabackwards.api.rewriters.EntityRewriter;
import com.viaversion.viabackwards.protocol.v1_21_2to1_21.Protocol1_21_2To1_21;
@@ -30,6 +31,7 @@
import com.viaversion.viabackwards.protocol.v1_21_2to1_21.storage.SignStorage;
import com.viaversion.viabackwards.utils.VelocityUtil;
import com.viaversion.viaversion.api.data.entity.EntityTracker;
+import com.viaversion.viaversion.api.data.entity.StoredEntityData;
import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.minecraft.Particle;
import com.viaversion.viaversion.api.minecraft.RegistryEntry;
@@ -643,6 +645,17 @@ protected void registerRewrites() {
);
registerBlockStateHandler(EntityTypes1_21_2.ABSTRACT_MINECART, 11);
+ final EntityScaleHelper scaleHelper = new EntityScaleHelper(ClientboundPackets1_21.UPDATE_ATTRIBUTES);
+ scaleHelper.addBabyScale(EntityTypes1_21_2.SQUID, 0.5f, 16);
+ scaleHelper.addBabyScale(EntityTypes1_21_2.GLOW_SQUID, 0.5f, 16);
+ scaleHelper.addBabyScale(EntityTypes1_21_2.DOLPHIN, 0.65f, 16);
+
+ for (EntityType type : scaleHelper.getRegisteredTypes()) {
+ filter().type(type).handler((event, meta) -> {
+ scaleHelper.trackAndInject(event, meta, protocol);
+ });
+ }
+
filter().type(EntityTypes1_21_2.CREAKING).cancel(17); // Active
filter().type(EntityTypes1_21_2.CREAKING).cancel(16); // Can move
diff --git a/common/src/main/java/com/viaversion/viabackwards/protocol/v1_21_6to1_21_5/Protocol1_21_6To1_21_5.java b/common/src/main/java/com/viaversion/viabackwards/protocol/v1_21_6to1_21_5/Protocol1_21_6To1_21_5.java
index 2d1e08eb..ae172e07 100644
--- a/common/src/main/java/com/viaversion/viabackwards/protocol/v1_21_6to1_21_5/Protocol1_21_6To1_21_5.java
+++ b/common/src/main/java/com/viaversion/viabackwards/protocol/v1_21_6to1_21_5/Protocol1_21_6To1_21_5.java
@@ -24,6 +24,10 @@
import com.viaversion.viabackwards.api.data.BackwardsMappingData;
import com.viaversion.viabackwards.api.rewriters.SoundRewriter;
import com.viaversion.viabackwards.api.rewriters.text.NBTComponentRewriter;
+import com.viaversion.viabackwards.api.entities.EntityScaleHelper;
+import com.viaversion.viabackwards.api.entities.EntityScaleData;
+import com.viaversion.viaversion.api.data.entity.StoredEntityData;
+import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viabackwards.protocol.v1_21_6to1_21_5.data.Dialog;
import com.viaversion.viabackwards.protocol.v1_21_6to1_21_5.provider.ChestDialogViewProvider;
import com.viaversion.viabackwards.protocol.v1_21_6to1_21_5.provider.DialogViewProvider;
@@ -113,7 +117,9 @@ protected void registerPackets() {
});
new StatisticsRewriter<>(this).register(ClientboundPackets1_21_6.AWARD_STATS);
- new AttributeRewriter<>(this).register1_21(ClientboundPackets1_21_6.UPDATE_ATTRIBUTES);
+
+ new com.viaversion.viabackwards.api.rewriters.EntityScaleAttributeRewriter<>(this).register1_21(ClientboundPackets1_21_6.UPDATE_ATTRIBUTES);
+
new CommandRewriter1_19_4<>(this) {
@Override
public void handleArgument(final PacketWrapper wrapper, final String argumentType) {
diff --git a/common/src/main/java/com/viaversion/viabackwards/protocol/v1_21_6to1_21_5/rewriter/EntityPacketRewriter1_21_6.java b/common/src/main/java/com/viaversion/viabackwards/protocol/v1_21_6to1_21_5/rewriter/EntityPacketRewriter1_21_6.java
index b02da50c..01958adc 100644
--- a/common/src/main/java/com/viaversion/viabackwards/protocol/v1_21_6to1_21_5/rewriter/EntityPacketRewriter1_21_6.java
+++ b/common/src/main/java/com/viaversion/viabackwards/protocol/v1_21_6to1_21_5/rewriter/EntityPacketRewriter1_21_6.java
@@ -17,8 +17,11 @@
*/
package com.viaversion.viabackwards.protocol.v1_21_6to1_21_5.rewriter;
+import com.viaversion.viabackwards.api.entities.EntityScaleData;
+import com.viaversion.viabackwards.api.entities.EntityScaleHelper;
import com.viaversion.viabackwards.api.rewriters.EntityRewriter;
import com.viaversion.viabackwards.protocol.v1_21_6to1_21_5.Protocol1_21_6To1_21_5;
+import com.viaversion.viaversion.api.data.entity.StoredEntityData;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_21_6;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_21_5;
@@ -105,6 +108,15 @@ protected void registerRewrites() {
filter().type(EntityTypes1_21_6.HANGING_ENTITY).removeIndex(8); // Direction
filter().type(EntityTypes1_21_6.HAPPY_GHAST).cancel(17); // Leash holder
filter().type(EntityTypes1_21_6.HAPPY_GHAST).cancel(18); // Stays still
+
+ final EntityScaleHelper scaleHelper = new EntityScaleHelper(ClientboundPackets1_21_5.UPDATE_ATTRIBUTES);
+ scaleHelper.addBabyScale(EntityTypes1_21_6.HAPPY_GHAST, 0.2375f, 16);
+
+ for (EntityType type : scaleHelper.getRegisteredTypes()) {
+ filter().type(type).handler((event, meta) -> {
+ scaleHelper.trackAndInject(event, meta, protocol);
+ });
+ }
}
@Override