diff --git a/src/main/java/ac/grim/grimac/predictionengine/MovementCheckRunner.java b/src/main/java/ac/grim/grimac/predictionengine/MovementCheckRunner.java index 6973fadc08..8371ecca4a 100644 --- a/src/main/java/ac/grim/grimac/predictionengine/MovementCheckRunner.java +++ b/src/main/java/ac/grim/grimac/predictionengine/MovementCheckRunner.java @@ -445,24 +445,14 @@ private void check(PositionUpdate update) { wasChecked = true; // Depth strider was added in 1.8 - final boolean hasAttributes = player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_21); - if (hasAttributes && PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_21)) { + if (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_8)) { player.depthStriderLevel = (float) player.compensatedEntities.getSelf().getAttribute(Attributes.GENERIC_WATER_MOVEMENT_EFFICIENCY).get(); } else { - if (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_8)) { - player.depthStriderLevel = EnchantmentHelper.getMaximumEnchantLevel(player.getInventory(), EnchantmentTypes.DEPTH_STRIDER, PacketEvents.getAPI().getServerManager().getVersion().toClientVersion()); - if (hasAttributes && PacketEvents.getAPI().getServerManager().getVersion().isOlderThan(ServerVersion.V_1_21)) { - // This is what via does - player.depthStriderLevel /= 3.0; - } - } else { - player.depthStriderLevel = 0; - } + player.depthStriderLevel = 0; } if (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_19)) { - ItemStack leggings = player.getInventory().getLeggings(); - player.sneakingSpeedMultiplier = GrimMath.clampFloat(0.3F + (leggings.getEnchantmentLevel(EnchantmentTypes.SWIFT_SNEAK, player.getClientVersion()) * 0.15F), 0f, 1f); + player.sneakingSpeedMultiplier = (float) player.compensatedEntities.getSelf().getAttribute(Attributes.PLAYER_SNEAKING_SPEED).get(); } else { player.sneakingSpeedMultiplier = 0.3F; } diff --git a/src/main/java/ac/grim/grimac/predictionengine/movementtick/MovementTicker.java b/src/main/java/ac/grim/grimac/predictionengine/movementtick/MovementTicker.java index 0addca4dd6..3bb8904c30 100644 --- a/src/main/java/ac/grim/grimac/predictionengine/movementtick/MovementTicker.java +++ b/src/main/java/ac/grim/grimac/predictionengine/movementtick/MovementTicker.java @@ -341,16 +341,10 @@ public void livingEntityTravel() { player.depthStriderLevel *= 0.5F; } - if (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_21)) { - if (player.depthStriderLevel > 0.0F) { - swimFriction += (0.54600006F - swimFriction) * player.depthStriderLevel; - swimSpeed += (player.speed - swimSpeed) * player.depthStriderLevel; - } - } else { - if (player.depthStriderLevel > 0.0F) { - swimFriction += (0.54600006F - swimFriction) * player.depthStriderLevel / 3.0F; - swimSpeed += (player.speed - swimSpeed) * player.depthStriderLevel / 3.0F; - } + if (player.depthStriderLevel > 0.0F) { + final float divisor = player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_21) ? 1.0F : 3.0F; + swimFriction += (0.54600006F - swimFriction) * player.depthStriderLevel / divisor; + swimSpeed += (player.speed - swimSpeed) * player.depthStriderLevel / divisor; } if (player.compensatedEntities.getDolphinsGraceAmplifier() != null) { diff --git a/src/main/java/ac/grim/grimac/utils/data/attribute/ValuedAttribute.java b/src/main/java/ac/grim/grimac/utils/data/attribute/ValuedAttribute.java index 30dd6774d5..e7ebff0fa4 100644 --- a/src/main/java/ac/grim/grimac/utils/data/attribute/ValuedAttribute.java +++ b/src/main/java/ac/grim/grimac/utils/data/attribute/ValuedAttribute.java @@ -1,16 +1,23 @@ package ac.grim.grimac.utils.data.attribute; +import ac.grim.grimac.player.GrimPlayer; import ac.grim.grimac.utils.math.GrimMath; import com.github.retrooper.packetevents.protocol.attribute.Attribute; +import com.github.retrooper.packetevents.protocol.player.ClientVersion; import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerUpdateAttributes; import java.util.List; import java.util.Optional; +import java.util.function.BiConsumer; +import java.util.function.BiFunction; +import java.util.function.Function; import static ac.grim.grimac.utils.latency.CompensatedEntities.SPRINTING_MODIFIER_UUID; public final class ValuedAttribute { + private static final Function DEFAULT_GET_REWRITE = Function.identity(); + private final Attribute attribute; // Attribute limits defined by https://minecraft.wiki/w/Attribute // These seem to be clamped on the client, but not the server @@ -20,6 +27,11 @@ public final class ValuedAttribute { private final double defaultValue; private double value; + // BiFunction of + // This allows us to rewrite the value based on client & server version + private BiFunction rewriteFunction; + private Function getRewriteFunction; + private ValuedAttribute(Attribute attribute, double defaultValue, double min, double max) { if (defaultValue < min || defaultValue > max) { throw new IllegalArgumentException("Default value must be between min and max!"); @@ -30,12 +42,39 @@ private ValuedAttribute(Attribute attribute, double defaultValue, double min, do this.value = defaultValue; this.min = min; this.max = max; + this.getRewriteFunction = DEFAULT_GET_REWRITE; } public static ValuedAttribute ranged(Attribute attribute, double defaultValue, double min, double max) { return new ValuedAttribute(attribute, defaultValue, min, max); } + public ValuedAttribute withRewriter(BiFunction rewriteFunction) { + this.rewriteFunction = rewriteFunction; + return this; + } + + /** + * Creates a rewriter that prevents the value from ever being modified unless the player meets the required version. + * @param player the player + * @param requiredVersion the required version for the attribute + * @return this instance for chaining + */ + public ValuedAttribute versionedRewriter(GrimPlayer player, ClientVersion requiredVersion) { + withRewriter((oldValue, newValue) -> { + if (player.getClientVersion().isOlderThan(requiredVersion)) { + return oldValue; + } + return newValue; + }); + return this; + } + + public ValuedAttribute withGetRewriter(Function getRewriteFunction) { + this.getRewriteFunction = getRewriteFunction; + return this; + } + public Attribute attribute() { return attribute; } @@ -45,7 +84,7 @@ public void reset() { } public double get() { - return value; + return getRewriteFunction.apply(this.value); } public void override(double value) { @@ -84,7 +123,16 @@ public double with(WrapperPlayServerUpdateAttributes.Property property) { d1 *= 1.0D + attributemodifier.getAmount(); } + double newValue = GrimMath.clampFloat((float) d1, (float) min, (float) max); + if (rewriteFunction != null) { + newValue = rewriteFunction.apply(this.value, newValue); + } + + if (newValue < min || newValue > max) { + throw new IllegalArgumentException("New value must be between min and max!"); + } + this.lastProperty = property; - return this.value = GrimMath.clampFloat((float) d1, (float) min, (float) max); + return this.value = newValue; } } diff --git a/src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntitySelf.java b/src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntitySelf.java index 4524e970d8..d86c12ceaf 100644 --- a/src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntitySelf.java +++ b/src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntitySelf.java @@ -3,10 +3,13 @@ import ac.grim.grimac.player.GrimPlayer; import ac.grim.grimac.utils.collisions.datatypes.SimpleCollisionBox; import ac.grim.grimac.utils.data.attribute.ValuedAttribute; +import ac.grim.grimac.utils.inventory.EnchantmentHelper; +import ac.grim.grimac.utils.math.GrimMath; import com.github.retrooper.packetevents.PacketEvents; import com.github.retrooper.packetevents.manager.server.ServerVersion; import com.github.retrooper.packetevents.protocol.attribute.Attributes; import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; +import com.github.retrooper.packetevents.protocol.item.enchantment.type.EnchantmentTypes; import com.github.retrooper.packetevents.protocol.player.ClientVersion; import com.github.retrooper.packetevents.protocol.player.GameMode; import com.github.retrooper.packetevents.protocol.potion.PotionType; @@ -44,12 +47,53 @@ public PacketEntitySelf(GrimPlayer player) { final ValuedAttribute movementSpeed = ValuedAttribute.ranged(Attributes.GENERIC_MOVEMENT_SPEED, 0.1f, 0, 1024); movementSpeed.with(new WrapperPlayServerUpdateAttributes.Property("MOVEMENT_SPEED", 0.1f, new ArrayList<>())); attributeMap.put(Attributes.GENERIC_MOVEMENT_SPEED, movementSpeed); - attributeMap.put(Attributes.GENERIC_JUMP_STRENGTH, ValuedAttribute.ranged(Attributes.GENERIC_JUMP_STRENGTH, 0.42f, 0, 32)); - attributeMap.put(Attributes.PLAYER_BLOCK_BREAK_SPEED, ValuedAttribute.ranged(Attributes.PLAYER_BLOCK_BREAK_SPEED, 1.0, 0, 1024)); - attributeMap.put(Attributes.PLAYER_ENTITY_INTERACTION_RANGE, ValuedAttribute.ranged(Attributes.PLAYER_ENTITY_INTERACTION_RANGE, 3, 0, 64)); - attributeMap.put(Attributes.PLAYER_BLOCK_INTERACTION_RANGE, ValuedAttribute.ranged(Attributes.PLAYER_BLOCK_INTERACTION_RANGE, 4.5, 0, 64)); - attributeMap.put(Attributes.GENERIC_WATER_MOVEMENT_EFFICIENCY, ValuedAttribute.ranged(Attributes.GENERIC_WATER_MOVEMENT_EFFICIENCY, 0, 0, 1)); - attributeMap.put(Attributes.PLAYER_SNEAKING_SPEED, ValuedAttribute.ranged(Attributes.PLAYER_SNEAKING_SPEED, 0.3, 0, 1)); + attributeMap.put(Attributes.GENERIC_JUMP_STRENGTH, ValuedAttribute.ranged(Attributes.GENERIC_JUMP_STRENGTH, 0.42f, 0, 32) + .versionedRewriter(player, ClientVersion.V_1_20_5)); + attributeMap.put(Attributes.PLAYER_BLOCK_BREAK_SPEED, ValuedAttribute.ranged(Attributes.PLAYER_BLOCK_BREAK_SPEED, 1.0, 0, 1024) + .versionedRewriter(player, ClientVersion.V_1_20_5)); + attributeMap.put(Attributes.PLAYER_ENTITY_INTERACTION_RANGE, ValuedAttribute.ranged(Attributes.PLAYER_ENTITY_INTERACTION_RANGE, 3, 0, 64) + .versionedRewriter(player, ClientVersion.V_1_20_5)); + attributeMap.put(Attributes.PLAYER_BLOCK_INTERACTION_RANGE, ValuedAttribute.ranged(Attributes.PLAYER_BLOCK_INTERACTION_RANGE, 4.5, 0, 64) + .versionedRewriter(player, ClientVersion.V_1_20_5)); + attributeMap.put(Attributes.GENERIC_WATER_MOVEMENT_EFFICIENCY, ValuedAttribute.ranged(Attributes.GENERIC_WATER_MOVEMENT_EFFICIENCY, 0, 0, 1) + .withGetRewriter(value -> { + // On clients < 1.21, use depth strider enchant level always + final double depthStrider = EnchantmentHelper.getMaximumEnchantLevel(player.getInventory(), EnchantmentTypes.DEPTH_STRIDER, PacketEvents.getAPI().getServerManager().getVersion().toClientVersion()); + if (depthStrider == 0) { + return 0d; + } + + if (player.getClientVersion().isOlderThan(ClientVersion.V_1_21)) { + return depthStrider; + } + + // Server is older than 1.21, but player is on 1.21+ so return depth strider value / 3 to simulate via + // https://github.com/ViaVersion/ViaVersion/blob/dc503cd613f5cf00a6f11b78e52b1a76a42acf91/common/src/main/java/com/viaversion/viaversion/protocols/v1_20_5to1_21/storage/EfficiencyAttributeStorage.java#L34 + if (PacketEvents.getAPI().getServerManager().getVersion().isOlderThan(ServerVersion.V_1_21)) { + return depthStrider / 3; + } + + // We are on a version that fully supports this value! + return value; + }) + .versionedRewriter(player, ClientVersion.V_1_21)); + attributeMap.put(Attributes.PLAYER_SNEAKING_SPEED, ValuedAttribute.ranged(Attributes.PLAYER_SNEAKING_SPEED, 0.3, 0, 1) + .withGetRewriter(value -> { + final int swiftSneak = player.getInventory().getLeggings().getEnchantmentLevel(EnchantmentTypes.SWIFT_SNEAK, player.getClientVersion()); + final double clamped = GrimMath.clampFloat(0.3F + (swiftSneak * 0.15F), 0f, 1f); + if (player.getClientVersion().isOlderThan(ClientVersion.V_1_21)) { + return clamped; + } + + // https://github.com/ViaVersion/ViaVersion/blob/dc503cd613f5cf00a6f11b78e52b1a76a42acf91/common/src/main/java/com/viaversion/viaversion/protocols/v1_20_5to1_21/storage/EfficiencyAttributeStorage.java#L32 + if (PacketEvents.getAPI().getServerManager().getVersion().isOlderThan(ServerVersion.V_1_21)) { + return clamped; + } + + // We are on a version that fully supports this value! + return value; + }) + .versionedRewriter(player, ClientVersion.V_1_21)); } public PacketEntitySelf(GrimPlayer player, PacketEntitySelf old) {