From 0f413969fa6d9fdf97e9b36dc63964cffac30df4 Mon Sep 17 00:00:00 2001 From: SaolGhra <47499708+SaolGhra@users.noreply.github.com> Date: Thu, 20 Nov 2025 15:22:32 +0000 Subject: [PATCH] Fix: clamp excessive entity velocities to [-4,4] to prevent plugin-caused explosive launches (#13270) - Clamp per-axis velocities to [-4.0, 4.0] for non-projectile/non-minecart entities in CraftEntity#setVelocity. - Preserve existing CraftServer.excessiveVelEx warning when unsafe velocities are attempted. - Add a small clamp helper. This prevents plugins from causing inconsistent or extreme player launches while keeping projectiles/minecarts unchanged. Tested with local runDev and test-plugin harness to confirm NMS deltaMovement is clamped to 4.0. --- .../bukkit/craftbukkit/entity/CraftEntity.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java index b177e23db960..4046c8422f16 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java @@ -200,11 +200,19 @@ public void setVelocity(Vector velocity) { Preconditions.checkArgument(velocity != null, "velocity"); velocity.checkFinite(); // Paper start - Warn server owners when plugins try to set super high velocities + // and clamp overly large velocities for non-projectile / non-minecart entities to + // avoid extreme physics/networking behaviour introduced by very large motion values. if (!(this instanceof org.bukkit.entity.Projectile || this instanceof org.bukkit.entity.Minecart) && isUnsafeVelocity(velocity)) { CraftServer.excessiveVelEx = new Exception("Excessive velocity set detected: tried to set velocity of entity " + entity.getScoreboardName() + " id #" + getEntityId() + " to (" + velocity.getX() + "," + velocity.getY() + "," + velocity.getZ() + ")."); + // Clamp velocity to a sane maximum to retain direction while preventing extreme values + double clampedX = clamp(velocity.getX(), -4.0D, 4.0D); + double clampedY = clamp(velocity.getY(), -4.0D, 4.0D); + double clampedZ = clamp(velocity.getZ(), -4.0D, 4.0D); + this.entity.setDeltaMovement(CraftVector.toVec3(new Vector(clampedX, clampedY, clampedZ))); + } else { + this.entity.setDeltaMovement(CraftVector.toVec3(velocity)); } // Paper end - this.entity.setDeltaMovement(CraftVector.toVec3(velocity)); this.entity.hurtMarked = true; } @@ -231,6 +239,12 @@ private static boolean isUnsafeVelocity(Vector vel) { return false; } + private static double clamp(double value, double min, double max) { + if (value < min) return min; + if (value > max) return max; + return value; + } + @Override public double getHeight() { return this.getHandle().getBbHeight();