From 0832032f2eb26691f741842767f674e0baf5d5d6 Mon Sep 17 00:00:00 2001 From: Moulberry Date: Tue, 8 Aug 2023 10:51:09 +0800 Subject: [PATCH] Add and implement PlayerFailMoveEvent (#9535) --- patches/api/Add-PlayerFailMoveEvent.patch | 121 ++++++++++++++++++ .../Implement-PlayerFailMoveEvent.patch | 104 +++++++++++++++ 2 files changed, 225 insertions(+) create mode 100644 patches/api/Add-PlayerFailMoveEvent.patch create mode 100644 patches/server/Implement-PlayerFailMoveEvent.patch diff --git a/patches/api/Add-PlayerFailMoveEvent.patch b/patches/api/Add-PlayerFailMoveEvent.patch new file mode 100644 index 0000000000..41bcf75af3 --- /dev/null +++ b/patches/api/Add-PlayerFailMoveEvent.patch @@ -0,0 +1,121 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Moulberry +Date: Wed, 26 Jul 2023 20:57:11 +0800 +Subject: [PATCH] Add PlayerFailMoveEvent + + +diff --git a/src/main/java/io/papermc/paper/event/player/PlayerFailMoveEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerFailMoveEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/player/PlayerFailMoveEvent.java +@@ -0,0 +0,0 @@ ++package io.papermc.paper.event.player; ++ ++import org.bukkit.Location; ++import org.bukkit.entity.Player; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Runs when a player attempts to move, but is prevented from doing so by the server ++ */ ++public class PlayerFailMoveEvent extends PlayerEvent { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private final FailReason failReason; ++ private boolean allowed; ++ private boolean logWarning; ++ private final Location from; ++ private final Location to; ++ ++ public PlayerFailMoveEvent(@NotNull Player who, @NotNull FailReason failReason, boolean allowed, ++ boolean logWarning, @NotNull Location from, @NotNull Location to) { ++ super(who); ++ this.failReason = failReason; ++ this.allowed = allowed; ++ this.logWarning = logWarning; ++ this.from = from; ++ this.to = to; ++ } ++ ++ /** ++ * Gets the reason this movement was prevented by the server ++ * @return The reason the movement was prevented ++ */ ++ @NotNull ++ public FailReason getFailReason() { ++ return failReason; ++ } ++ ++ /** ++ * Gets the location this player moved from ++ * @return Location the player moved from ++ */ ++ @NotNull ++ public Location getFrom() { ++ return from; ++ } ++ ++ /** ++ * Gets the location this player tried to move to ++ * @return Location the player tried to move to ++ */ ++ @NotNull ++ public Location getTo() { ++ return to; ++ } ++ ++ /** ++ * Gets if the check should be bypassed, allowing the movement ++ * @return whether to bypass the check ++ */ ++ public boolean isAllowed() { ++ return allowed; ++ } ++ ++ /** ++ * Set if the check should be bypassed and the movement should be allowed ++ * @param allowed whether to bypass the check ++ */ ++ public void setAllowed(boolean allowed) { ++ this.allowed = allowed; ++ } ++ ++ /** ++ * Gets if warnings will be printed to console. eg. "Player123 moved too quickly!" ++ * @return whether to log warnings ++ */ ++ public boolean getLogWarning() { ++ return logWarning; ++ } ++ ++ /** ++ * Set if a warning is printed to console. eg. "Player123 moved too quickly!" ++ * @param logWarning whether to log warnings ++ */ ++ public void setLogWarning(boolean logWarning) { ++ this.logWarning = logWarning; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++ ++ public enum FailReason { ++ MOVED_INTO_UNLOADED_CHUNK, // Only fired if the world setting prevent-moving-into-unloaded-chunks is true ++ MOVED_TOO_QUICKLY, ++ MOVED_WRONGLY, ++ CLIPPED_INTO_BLOCK ++ } ++ ++} diff --git a/patches/server/Implement-PlayerFailMoveEvent.patch b/patches/server/Implement-PlayerFailMoveEvent.patch new file mode 100644 index 0000000000..8b1bdd601e --- /dev/null +++ b/patches/server/Implement-PlayerFailMoveEvent.patch @@ -0,0 +1,104 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Moulberry +Date: Wed, 26 Jul 2023 20:13:31 +0800 +Subject: [PATCH] Implement PlayerFailMoveEvent + + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic + double d0 = ServerGamePacketListenerImpl.clampHorizontal(packet.getX(this.player.getX())); final double toX = d0; // Paper - OBFHELPER + double d1 = ServerGamePacketListenerImpl.clampVertical(packet.getY(this.player.getY())); final double toY = d1; + double d2 = ServerGamePacketListenerImpl.clampHorizontal(packet.getZ(this.player.getZ())); final double toZ = d2; // Paper - OBFHELPER +- float f = Mth.wrapDegrees(packet.getYRot(this.player.getYRot())); +- float f1 = Mth.wrapDegrees(packet.getXRot(this.player.getXRot())); ++ float f = Mth.wrapDegrees(packet.getYRot(this.player.getYRot())); final float toYaw = f; // Paper - OBFHELPER ++ float f1 = Mth.wrapDegrees(packet.getXRot(this.player.getXRot())); final float toPitch = f1; // Paper - OBFHELPER + + if (this.player.isPassenger()) { + this.player.absMoveTo(this.player.getX(), this.player.getY(), this.player.getZ(), f, f1); +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic + } + // Paper start - Prevent moving into unloaded chunks + if (this.player.level().paperConfig().chunks.preventMovingIntoUnloadedChunks && (this.player.getX() != toX || this.player.getZ() != toZ) && !worldserver.areChunksLoadedForMove(this.player.getBoundingBox().expandTowards(new Vec3(toX, toY, toZ).subtract(this.player.position())))) { ++ // Paper start - Add fail move event ++ io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.MOVED_INTO_UNLOADED_CHUNK, ++ toX, toY, toZ, toYaw, toPitch, false); ++ if (!event.isAllowed()) { + this.internalTeleport(this.player.getX(), this.player.getY(), this.player.getZ(), this.player.getYRot(), this.player.getXRot(), Collections.emptySet()); + return; ++ } ++ // Paper end + } + // Paper end + +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic + + if (d10 - d9 > Math.max(f2, Math.pow((double) (org.spigotmc.SpigotConfig.movedTooQuicklyMultiplier * (float) i * speed), 2)) && !this.isSingleplayerOwner()) { + // CraftBukkit end ++ // Paper start - Add fail move event ++ io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.MOVED_TOO_QUICKLY, ++ toX, toY, toZ, toYaw, toPitch, true); ++ if (!event.isAllowed()) { ++ if (event.getLogWarning()) + ServerGamePacketListenerImpl.LOGGER.warn("{} moved too quickly! {},{},{}", new Object[]{this.player.getName().getString(), d6, d7, d8}); + this.teleport(this.player.getX(), this.player.getY(), this.player.getZ(), this.player.getYRot(), this.player.getXRot()); + return; ++ } ++ // Paper end + } + } + +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic + boolean flag2 = false; + + if (!this.player.isChangingDimension() && d10 > org.spigotmc.SpigotConfig.movedWronglyThreshold && !this.player.isSleeping() && !this.player.gameMode.isCreative() && this.player.gameMode.getGameModeForPlayer() != GameType.SPECTATOR) { // Spigot ++ // Paper start - Add fail move event ++ io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.MOVED_WRONGLY, ++ toX, toY, toZ, toYaw, toPitch, true); ++ if (!event.isAllowed()) { + flag2 = true; // Paper - diff on change, this should be moved wrongly ++ if (event.getLogWarning()) + ServerGamePacketListenerImpl.LOGGER.warn("{} moved wrongly!", this.player.getName().getString()); ++ } ++ // Paper end + } + + // Paper start - optimise out extra getCubes +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic + if (didCollide || !axisalignedbb.equals(newBox)) { + // note: only call after setLocation, or else getBoundingBox is wrong + teleportBack = this.hasNewCollision(worldserver, this.player, axisalignedbb, newBox); ++ // Paper start - Add fail move event ++ if (teleportBack) { ++ io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.CLIPPED_INTO_BLOCK, ++ toX, toY, toZ, toYaw, toPitch, false); ++ if (event.isAllowed()) { ++ teleportBack = false; ++ } ++ } ++ // Paper end + } // else: no collision at all detected, why do we care? + } + if (!this.player.noPhysics && !this.player.isSleeping() && teleportBack) { // Paper end - optimise out extra getCubes +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic + } + } + ++ // Paper start - Add fail move event ++ private io.papermc.paper.event.player.PlayerFailMoveEvent fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason failReason, ++ double toX, double toY, double toZ, float toYaw, float toPitch, boolean logWarning) { ++ Player player = this.getCraftPlayer(); ++ Location from = new Location(player.getWorld(), this.lastPosX, this.lastPosY, this.lastPosZ, this.lastYaw, this.lastPitch); ++ Location to = new Location(player.getWorld(), toX, toY, toZ, toYaw, toPitch); ++ io.papermc.paper.event.player.PlayerFailMoveEvent event = new io.papermc.paper.event.player.PlayerFailMoveEvent(player, failReason, ++ false, logWarning, from, to); ++ event.callEvent(); ++ return event; ++ } ++ // Paper end + // Paper start - optimise out extra getCubes + private boolean hasNewCollision(final ServerLevel world, final Entity entity, final AABB oldBox, final AABB newBox) { + final List collisions = io.papermc.paper.util.CachedLists.getTempCollisionList();