diff --git a/patches/server/0044-PandaSpigot-Configurable-knockback.patch b/patches/server/0044-PandaSpigot-Configurable-knockback.patch new file mode 100644 index 00000000..e9af4229 --- /dev/null +++ b/patches/server/0044-PandaSpigot-Configurable-knockback.patch @@ -0,0 +1,182 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: hpfxd +Date: Tue, 2 Jan 2024 01:47:36 -0500 +Subject: [PATCH] PandaSpigot: Configurable knockback + +Original code by hpfxd, licensed under GPL v3 +You can find the original code on https://github.com/hpfxd/PandaSpigot + +This patch allows velocity applied when a player is hit to be modified in the configuration. + +Reference: https://gist.github.com/YoungOG/e3265d98661957abece71594b70d6a01 + +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 0a8e22a7aabca12b3d6391b21d6e431398c01ba9..62e4fa9b5cb4043990c6642df43c8ef5c61caa17 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -1965,7 +1965,13 @@ public abstract class LivingEntity extends Entity implements Attackable { + Vec3 vec3d = this.getDeltaMovement(); + Vec3 vec3d1 = (new Vec3(x, 0.0D, z)).normalize().scale(strength); + +- this.setDeltaMovement(vec3d.x / 2.0D - vec3d1.x, this.onGround() ? Math.min(0.4D, vec3d.y / 2.0D + strength) : vec3d.y, vec3d.z / 2.0D - vec3d1.z); ++ // Leaf start - Configurable PandaSpigot knockback ++ this.setDeltaMovement( ++ vec3d.x / org.dreeam.leaf.LeafConfig.friction - vec3d1.x * org.dreeam.leaf.LeafConfig.horizontal, ++ this.onGround() ? Math.min(org.dreeam.leaf.LeafConfig.vertical, vec3d.y / org.dreeam.leaf.LeafConfig.friction + org.dreeam.leaf.LeafConfig.verticalLimit) : vec3d.y, ++ vec3d.z / org.dreeam.leaf.LeafConfig.friction - vec3d1.z * org.dreeam.leaf.LeafConfig.horizontal ++ ); ++ // Leaf end + // Paper start - call EntityKnockbackByEntityEvent + Vec3 currentMovement = this.getDeltaMovement(); + org.bukkit.util.Vector delta = new org.bukkit.util.Vector(currentMovement.x - vec3d.x, currentMovement.y - vec3d.y, currentMovement.z - vec3d.z); +diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java +index 03d263d7ac7e665fb6bf6b258796426ce2c4827c..4d71346ec51c08f2178c4f20da7e25af4fd70495 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -1371,11 +1371,22 @@ public abstract class Player extends LivingEntity { + + if (flag5) { + if (i > 0) { ++ // Leaf start - Configurable PandaSpigot knockback + if (target instanceof LivingEntity) { +- ((LivingEntity) target).knockback((double) ((float) i * 0.5F), (double) Mth.sin(this.getYRot() * 0.017453292F), (double) (-Mth.cos(this.getYRot() * 0.017453292F)), this); // Paper ++ ((LivingEntity) target).knockback( ++ (float) i * 0.5F, ++ Mth.sin(this.getYRot() * 0.017453292F), ++ -Mth.cos(this.getYRot() * 0.017453292F), ++ this ++ ); // Paper + } else { +- target.push((double) (-Mth.sin(this.getYRot() * 0.017453292F) * (float) i * 0.5F), 0.1D, (double) (Mth.cos(this.getYRot() * 0.017453292F) * (float) i * 0.5F), this); // Paper ++ target.push( ++ -Mth.sin(this.getYRot() * 0.017453292F) * (float) i * org.dreeam.leaf.LeafConfig.extraHorizontal, ++ org.dreeam.leaf.LeafConfig.extraVertical, ++ Mth.cos(this.getYRot() * 0.017453292F) * (float) i * org.dreeam.leaf.LeafConfig.extraHorizontal, ++ this); // Paper + } ++ // Leaf end + + this.setDeltaMovement(this.getDeltaMovement().multiply(0.6D, 1.0D, 0.6D)); + // Paper start - Configuration option to disable automatic sprint interruption +@@ -1406,27 +1417,27 @@ public abstract class Player extends LivingEntity { + this.sweepAttack(); + } + +- if (target instanceof ServerPlayer && target.hurtMarked) { +- // CraftBukkit start - Add Velocity Event +- boolean cancelled = false; +- org.bukkit.entity.Player player = (org.bukkit.entity.Player) target.getBukkitEntity(); +- org.bukkit.util.Vector velocity = CraftVector.toBukkit(vec3d); ++ // Leaf start - Configurable PandaSpigot knockback ++ if (target instanceof ServerPlayer attackedPlayer && target.hurtMarked) { ++ // If the attack caused knockback, send the new velocity to the victim's client immediately, ++ // and undo the change. Otherwise, if movement packets from the victim are processed before ++ // the end of the tick, then friction may reduce the velocity considerably before it's sent ++ // to the client, particularly if the victim was standing on the ground when those packets ++ // were generated. And because this glitch is also likely to make server-side velocity very ++ // inconsistent, we simply reverse the knockback after sending it so that KB, like most other ++ // things, doesn't affect server velocity at all. ++ PlayerVelocityEvent event = new PlayerVelocityEvent(attackedPlayer.getBukkitEntity(), ++ attackedPlayer.getBukkitEntity().getVelocity()); + +- PlayerVelocityEvent event = new PlayerVelocityEvent(player, velocity.clone()); + this.level().getCraftServer().getPluginManager().callEvent(event); +- +- if (event.isCancelled()) { +- cancelled = true; +- } else if (!velocity.equals(event.getVelocity())) { +- player.setVelocity(event.getVelocity()); ++ if (!event.isCancelled()) { ++ attackedPlayer.getBukkitEntity().setVelocityDirect(event.getVelocity()); ++ attackedPlayer.connection.send(new ClientboundSetEntityMotionPacket(attackedPlayer)); + } + +- if (!cancelled) { +- ((ServerPlayer) target).connection.send(new ClientboundSetEntityMotionPacket(target)); +- target.hurtMarked = false; +- target.setDeltaMovement(vec3d); +- } +- // CraftBukkit end ++ attackedPlayer.hurtMarked = false; ++ attackedPlayer.setDeltaMovement(vec3d); ++ // Leaf end + } + + if (flag2) { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index c887f6c6f60acee37ff72568f95e5a34d4db53a2..a42e3084fa2792bd341a6e3e5b93320e37e4a99c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -67,6 +67,7 @@ import net.minecraft.network.protocol.game.ClientboundSetBorderSizePacket; + import net.minecraft.network.protocol.game.ClientboundSetBorderWarningDelayPacket; + import net.minecraft.network.protocol.game.ClientboundSetBorderWarningDistancePacket; + import net.minecraft.network.protocol.game.ClientboundSetDefaultSpawnPositionPacket; ++import net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket; + import net.minecraft.network.protocol.game.ClientboundSetEquipmentPacket; + import net.minecraft.network.protocol.game.ClientboundSetExperiencePacket; + import net.minecraft.network.protocol.game.ClientboundSetHealthPacket; +@@ -3224,6 +3225,40 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + getHandle().resetAttackStrengthTicker(); + } + // Paper end ++ ++ // Leaf start - Configurable PandaSpigot knockback ++ @Override ++ public void setVelocity(org.bukkit.util.Vector vec) { ++ // To be consistent with old behavior, set the velocity before firing the event ++ this.setVelocityDirect(vec); ++ ++ org.bukkit.event.player.PlayerVelocityEvent event = new org.bukkit.event.player.PlayerVelocityEvent(this, vec.clone()); ++ this.getServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ // Set the velocity again in case it was changed by event handlers ++ this.setVelocityDirect(event.getVelocity()); ++ ++ // Send the new velocity to the player's client immediately, so it isn't affected by ++ // any movement packets from this player that may be processed before the end of the tick. ++ // Without this, player velocity changes tend to be very inconsistent. ++ this.getHandle().connection.send(new ClientboundSetEntityMotionPacket(this.getHandle())); ++ } ++ ++ // Note that cancelling the event does not restore the old velocity, it only prevents ++ // the packet from sending. Again, this is to be consistent with old behavior. ++ } ++ ++ public void setVelocityDirect(org.bukkit.util.Vector vec) { ++ entity.xo = vec.getX(); ++ entity.yo = vec.getY(); ++ entity.zo = vec.getZ(); ++ if (entity.yo > 0) { ++ entity.fallDistance = 0.0f; ++ } ++ } ++ // Leaf end ++ + // Spigot start + private final Player.Spigot spigot = new Player.Spigot() + { +diff --git a/src/main/java/org/dreeam/leaf/LeafConfig.java b/src/main/java/org/dreeam/leaf/LeafConfig.java +index 53bde816ca9bf8b704fb2e9794de260a9eba402f..aefac52818ec5457999b1bc70a47b1138c840571 100644 +--- a/src/main/java/org/dreeam/leaf/LeafConfig.java ++++ b/src/main/java/org/dreeam/leaf/LeafConfig.java +@@ -296,4 +296,19 @@ public class LeafConfig { + gg.pufferfish.pufferfish.sentry.SentryManager.init(); + } + } ++ ++ public static double friction = 2.0D; ++ public static double horizontal = 0.4D; ++ public static double vertical = 0.4D; ++ public static double verticalLimit = 0.4000000059604645D; ++ public static double extraHorizontal = 0.5D; ++ public static double extraVertical = 0.1D; ++ private static void knockback() { ++ friction = getDouble("playerKnockback.friction", friction); ++ horizontal = getDouble("playerKnockback.horizontal", horizontal); ++ vertical = getDouble("playerKnockback.vertical", vertical); ++ verticalLimit = getDouble("playerKnockback.verticalLimit", verticalLimit); ++ extraHorizontal = getDouble("playerKnockback.extraHorizontal", extraHorizontal); ++ extraVertical = getDouble("playerKnockback.extraVertical", extraVertical); ++ } + }