Compare commits

...
Author SHA1 Message Date
Florian Reuth f491837395 Fix formatting
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-10-19 00:55:27 +02:00
Florian Reuth 086b638eb8 Handle negative jump boost effect in 1.20.3->1.20.5
Closes https://github.com/ViaVersion/ViaVersion/issues/4350

Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-10-19 00:54:30 +02:00
5 changed files with 53 additions and 4 deletions

No files matched your search

@@ -544,6 +544,14 @@ public interface ViaVersionConfig extends Config {
*/
boolean use1_8HitboxMargin();
/**
* If enabled, 1.20.5+ clients on 1.20.4 (or older) servers can't jump with negative jump boost,
* emulated through the jump strength attribute while hiding the effect.
*
* @return true if enabled
*/
boolean emulateNegativeJumpBoost();
/**
* If enabled, ViaVersion will send the native client version to the server on connect via a plugin message.
*
@@ -101,6 +101,7 @@ public class AbstractViaConfig extends Config implements ViaVersionConfig {
private boolean cancelSwingInInventory;
private int maxErrorLength;
private boolean use1_8HitboxMargin;
private boolean emulateNegativeJumpBoost;
private boolean sendPlayerDetails;
private boolean sendServerDetails;
@@ -177,6 +178,7 @@ public class AbstractViaConfig extends Config implements ViaVersionConfig {
fix1_21PlacementRotation = getBoolean("fix-1_21-placement-rotation", true);
cancelSwingInInventory = getBoolean("cancel-swing-in-inventory", true);
use1_8HitboxMargin = getBoolean("use-1_8-hitbox-margin", true);
emulateNegativeJumpBoost = getBoolean("emulate-negative-jump-boost", true);
sendPlayerDetails = getBoolean("send-player-details", true);
sendServerDetails = getBoolean("send-server-details", true);
packetTrackerConfig = loadRateLimitConfig(getSection("packet-limiter"), "%pps", 1);
@@ -652,6 +654,11 @@ public class AbstractViaConfig extends Config implements ViaVersionConfig {
return use1_8HitboxMargin;
}
@Override
public boolean emulateNegativeJumpBoost() {
return emulateNegativeJumpBoost;
}
@Override
public boolean sendPlayerDetails() {
return sendPlayerDetails;
@@ -40,8 +40,8 @@ public final class ConfigurationRegistrations {
ctx.clientbound(ClientboundPackets1_20_2.START_CONFIGURATION, packetType -> ctx.protocol().registerClientbound(packetType, wrapper -> {
wrapper.user().getProtocolInfo().setServerState(State.CONFIGURATION);
// Mimic client behaviour by resetting tracked entities when configuration starts.
final EntityTracker tracker = wrapper.user().getEntityTracker(ctx.protocol().getClass());
// Mimic client behavior by resetting tracked entities when configuration starts.
final EntityTracker tracker = wrapper.user().getEntityTracker(ctx.protocol());
if (tracker != null) {
tracker.clear();
}
@@ -69,6 +69,8 @@ public final class EntityPacketRewriter1_20_5 extends EntityRewriter<Clientbound
private static final UUID CREATIVE_BLOCK_INTERACTION_RANGE = UUID.fromString("736565d2-e1a7-403d-a3f8-1aeb3e302542");
private static final UUID CREATIVE_ENTITY_INTERACTION_RANGE = UUID.fromString("98491ef6-97b1-4584-ae82-71a8cc85cf73");
private static final UUID NEGATIVE_JUMP_BOOST = UUID.fromString("5d0a3b8e-2f6c-4b1e-9a47-c3e1f0b7d264");
private static final int JUMP_BOOST_EFFECT = 7;
public EntityPacketRewriter1_20_5(final Protocol1_20_3To1_20_5 protocol) {
super(protocol);
@@ -307,10 +309,24 @@ public final class EntityPacketRewriter1_20_5 extends EntityRewriter<Clientbound
});
protocol.registerClientbound(ClientboundPackets1_20_3.UPDATE_MOB_EFFECT, wrapper -> {
wrapper.passthrough(Types.VAR_INT); // Entity ID
wrapper.passthrough(Types.VAR_INT); // Effect ID
final int entityId = wrapper.passthrough(Types.VAR_INT);
final int effectId = wrapper.passthrough(Types.VAR_INT);
final byte amplifier = wrapper.read(Types.BYTE);
if (effectId == JUMP_BOOST_EFFECT && entityId == tracker(wrapper.user()).clientEntityId() && Via.getConfig().emulateNegativeJumpBoost()) {
if (amplifier < 0) {
// Negative amplifiers are clamped to 0 by the client, emulate the reduced jump power with the jump strength attribute instead
final PacketWrapper removeEffect = wrapper.create(ClientboundPackets1_20_5.REMOVE_MOB_EFFECT);
removeEffect.write(Types.VAR_INT, entityId);
removeEffect.write(Types.VAR_INT, effectId);
removeEffect.send(Protocol1_20_3To1_20_5.class);
sendJumpStrength(wrapper.user(), 0.1D * (amplifier + 1));
wrapper.cancel();
return;
}
sendJumpStrength(wrapper.user(), 0D);
}
wrapper.write(Types.VAR_INT, (int) amplifier);
wrapper.passthrough(Types.VAR_INT); // Duration
@@ -318,6 +334,14 @@ public final class EntityPacketRewriter1_20_5 extends EntityRewriter<Clientbound
wrapper.read(Types.OPTIONAL_COMPOUND_TAG); // Remove factor data
});
protocol.registerClientbound(ClientboundPackets1_20_3.REMOVE_MOB_EFFECT, wrapper -> {
final int entityId = wrapper.passthrough(Types.VAR_INT);
final int effectId = wrapper.passthrough(Types.VAR_INT);
if (effectId == JUMP_BOOST_EFFECT && entityId == tracker(wrapper.user()).clientEntityId() && Via.getConfig().emulateNegativeJumpBoost()) {
sendJumpStrength(wrapper.user(), 0D);
}
});
protocol.registerClientbound(ClientboundPackets1_20_3.UPDATE_ATTRIBUTES, wrapper -> {
wrapper.passthrough(Types.VAR_INT); // Entity ID
final int size = wrapper.passthrough(Types.VAR_INT);
@@ -434,6 +458,14 @@ public final class EntityPacketRewriter1_20_5 extends EntityRewriter<Clientbound
wrapper.scheduleSend(Protocol1_20_3To1_20_5.class);
}
private void sendJumpStrength(final UserConnection connection, final double jumpBoost) {
final PacketWrapper wrapper = PacketWrapper.create(ClientboundPackets1_20_5.UPDATE_ATTRIBUTES, connection);
wrapper.write(Types.VAR_INT, tracker(connection).clientEntityId());
wrapper.write(Types.VAR_INT, 1); // Number of attributes
this.writeAttribute(wrapper, "generic.jump_strength", 0.42D, jumpBoost != 0D ? NEGATIVE_JUMP_BOOST : null, jumpBoost);
wrapper.scheduleSend(Protocol1_20_3To1_20_5.class);
}
private void writeAttribute(final PacketWrapper wrapper, final String attributeId, final double base, @Nullable final UUID modifierId, final double amount) {
wrapper.write(Types.VAR_INT, Attributes1_20_5.keyToId(attributeId));
wrapper.write(Types.DOUBLE, base);
@@ -248,3 +248,5 @@ left-handed-handling: true
cancel-block-sounds: true
# If enabled, 1.21.11+ clients on 1.8 servers will get wider entity hitboxes when attacking with items
use-1_8-hitbox-margin: true
# If enabled, 1.20.5+ clients on 1.20.4 or older servers can't jump with negative jump boost levels (the effect icon is hidden while active)
emulate-negative-jump-boost: true