-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add PlayerMoveControllableVehicleEvent
Useful if you want to actually control what the player is moving, because VehicleMoveEvent does not let you cancel nor change the location. Also useful to detect BoatFly hacks.
- Loading branch information
1 parent
0fd98d6
commit 81aca64
Showing
8 changed files
with
407 additions
and
0 deletions.
There are no files selected for viewing
141 changes: 141 additions & 0 deletions
141
patches/api/0004-Add-PlayerMoveControllableVehicleEvent.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 | ||
From: MrPowerGamerBR <[email protected]> | ||
Date: Sat, 4 Jan 2025 23:58:34 -0300 | ||
Subject: [PATCH] Add PlayerMoveControllableVehicleEvent | ||
|
||
|
||
diff --git a/src/main/java/net/sparklypower/sparklypaper/event/player/PlayerMoveControllableVehicleEvent.java b/src/main/java/net/sparklypower/sparklypaper/event/player/PlayerMoveControllableVehicleEvent.java | ||
new file mode 100644 | ||
index 0000000000000000000000000000000000000000..a646251feb6b8bf7ff07e6b4b84bb5751ee4b90b | ||
--- /dev/null | ||
+++ b/src/main/java/net/sparklypower/sparklypaper/event/player/PlayerMoveControllableVehicleEvent.java | ||
@@ -0,0 +1,129 @@ | ||
+package net.sparklypower.sparklypaper.event.player; | ||
+ | ||
+import com.google.common.base.Preconditions; | ||
+import org.bukkit.Location; | ||
+import org.bukkit.entity.Entity; | ||
+import org.bukkit.entity.Player; | ||
+import org.bukkit.entity.Vehicle; | ||
+import org.bukkit.event.Cancellable; | ||
+import org.bukkit.event.HandlerList; | ||
+import org.bukkit.event.player.PlayerEvent; | ||
+import org.jetbrains.annotations.NotNull; | ||
+ | ||
+/** | ||
+ * Raised when a player moves a controllable vehicle. Controllable vehicles are vehicles that the client can control, such as boats, horses, striders, pigs, etc. | ||
+ * <p> | ||
+ * Minecarts are NOT affected by this event! | ||
+ */ | ||
+public class PlayerMoveControllableVehicleEvent extends PlayerEvent implements Cancellable { | ||
+ private static final HandlerList handlers = new HandlerList(); | ||
+ private boolean cancel = false; | ||
+ private final Vehicle vehicle; | ||
+ private Location from; | ||
+ private Location to; | ||
+ | ||
+ public PlayerMoveControllableVehicleEvent(@NotNull final Player player, @NotNull final Vehicle vehicle, @NotNull final Location from, @NotNull final Location to) { | ||
+ super(player); | ||
+ | ||
+ this.vehicle = vehicle; | ||
+ this.from = from; | ||
+ this.to = to; | ||
+ } | ||
+ | ||
+ /** | ||
+ * Get the previous position. | ||
+ * | ||
+ * @return Old position. | ||
+ */ | ||
+ @NotNull | ||
+ public Location getFrom() { | ||
+ return from.clone(); // Paper - clone to avoid changes | ||
+ } | ||
+ | ||
+ /** | ||
+ * Sets the location to mark as where the player moved from | ||
+ * | ||
+ * @param from New location to mark as the players previous location | ||
+ */ | ||
+ public void setFrom(@NotNull Location from) { | ||
+ validateLocation(from, this.from); | ||
+ this.from = from; | ||
+ } | ||
+ | ||
+ /** | ||
+ * Get the next position. | ||
+ * | ||
+ * @return New position. | ||
+ */ | ||
+ @NotNull | ||
+ public Location getTo() { | ||
+ return to.clone(); // Paper - clone to avoid changes | ||
+ } | ||
+ | ||
+ /** | ||
+ * Sets the location that this player will move to | ||
+ * | ||
+ * @param to New Location this player will move to | ||
+ */ | ||
+ public void setTo(@NotNull Location to) { | ||
+ validateLocation(to, this.to); | ||
+ this.to = to; | ||
+ } | ||
+ | ||
+ /** | ||
+ * Get the vehicle. | ||
+ * | ||
+ * @return the vehicle | ||
+ */ | ||
+ @NotNull | ||
+ public final Entity getVehicle() { | ||
+ return vehicle; | ||
+ } | ||
+ | ||
+ /** | ||
+ * Gets the cancellation state of this event. A cancelled event will not | ||
+ * be executed in the server, but will still pass to other plugins | ||
+ * <p> | ||
+ * If a move or teleport event is cancelled, the vehicle and player will be moved or | ||
+ * teleported back to the Location as defined by getFrom(). This will not | ||
+ * fire an event | ||
+ * | ||
+ * @return true if this event is cancelled | ||
+ */ | ||
+ @Override | ||
+ public boolean isCancelled() { | ||
+ return cancel; | ||
+ } | ||
+ | ||
+ /** | ||
+ * Sets the cancellation state of this event. A cancelled event will not | ||
+ * be executed in the server, but will still pass to other plugins | ||
+ * <p> | ||
+ * If a move or teleport event is cancelled, the vehicle and player will be moved or | ||
+ * teleported back to the Location as defined by getFrom(). This will not | ||
+ * fire an event | ||
+ * | ||
+ * @param cancel true if you wish to cancel this event | ||
+ */ | ||
+ @Override | ||
+ public void setCancelled(boolean cancel) { | ||
+ this.cancel = cancel; | ||
+ } | ||
+ | ||
+ @NotNull | ||
+ @Override | ||
+ public HandlerList getHandlers() { | ||
+ return handlers; | ||
+ } | ||
+ | ||
+ @NotNull | ||
+ public static HandlerList getHandlerList() { | ||
+ return handlers; | ||
+ } | ||
+ | ||
+ private void validateLocation(@NotNull Location loc, @NotNull Location originalLoc) { | ||
+ Preconditions.checkArgument(loc != null, "Cannot use null location!"); | ||
+ Preconditions.checkArgument(loc.getWorld() != null, "Cannot use null location with null world!"); | ||
+ Preconditions.checkArgument(loc.getWorld() != originalLoc, "New location should be in the original world!"); | ||
+ } | ||
+} |
File renamed without changes.
109 changes: 109 additions & 0 deletions
109
patches/removed/api/0005-Extend-AsyncPlayerPreLoginEvent-to-allow-plugins-to-.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 | ||
From: MrPowerGamerBR <[email protected]> | ||
Date: Fri, 13 Dec 2024 16:35:03 -0300 | ||
Subject: [PATCH] Extend AsyncPlayerPreLoginEvent to allow plugins to send | ||
Login Plugin Requests to the client | ||
|
||
|
||
diff --git a/src/main/java/net/sparklypower/sparklypaper/PendingConnection.java b/src/main/java/net/sparklypower/sparklypaper/PendingConnection.java | ||
new file mode 100644 | ||
index 0000000000000000000000000000000000000000..11d64d825c15c122192359b86561808d0d7f5fbb | ||
--- /dev/null | ||
+++ b/src/main/java/net/sparklypower/sparklypaper/PendingConnection.java | ||
@@ -0,0 +1,41 @@ | ||
+package net.sparklypower.sparklypaper; | ||
+ | ||
+import org.bukkit.NamespacedKey; | ||
+import org.jetbrains.annotations.NotNull; | ||
+ | ||
+import java.util.concurrent.CompletableFuture; | ||
+ | ||
+public interface PendingConnection { | ||
+ /** | ||
+ * Sends a login plugin request to the client, the client must reply with a login plugin response. | ||
+ * <br> | ||
+ * The vanilla client always replies with "not acknowledged", however mods, and proxies, can change | ||
+ * the response. | ||
+ * | ||
+ * @param transactionId the ID of the transaction, must be unique for each connection | ||
+ * @param channel the chanenl where the data will be sent | ||
+ * @param data the data that will be sent | ||
+ * @return a {@link CompletableFuture} that will be completed when the | ||
+ * login plugin response is received or otherwise available. | ||
+ */ | ||
+ @NotNull | ||
+ CompletableFuture<PendingConnection.LoginPluginResponse> sendLoginPluginRequest(int transactionId, @NotNull NamespacedKey channel, byte @NotNull [] data); | ||
+ | ||
+ class LoginPluginResponse { | ||
+ final boolean acknowledged; | ||
+ final byte[] response; | ||
+ | ||
+ public LoginPluginResponse(boolean acknowledged, byte[] response) { | ||
+ this.acknowledged = acknowledged; | ||
+ this.response = response; | ||
+ } | ||
+ | ||
+ public boolean isAcknowledged() { | ||
+ return acknowledged; | ||
+ } | ||
+ | ||
+ public byte[] getResponse() { | ||
+ return response; | ||
+ } | ||
+ } | ||
+} | ||
diff --git a/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java b/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java | ||
index ff5cca4a7e75274b4b278a48ae1544ff42a9836a..2ace8261a836dbdf44b35cdedb53c4b5b2986f0f 100644 | ||
--- a/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java | ||
+++ b/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java | ||
@@ -27,6 +27,7 @@ public class AsyncPlayerPreLoginEvent extends Event { | ||
private final InetAddress rawAddress; // Paper | ||
private final String hostname; // Paper | ||
private final boolean transferred; | ||
+ private net.sparklypower.sparklypaper.PendingConnection pendingConnection; // SparklyPaper - Add support for login plugin requests | ||
|
||
@Deprecated(since = "1.7.5") | ||
public AsyncPlayerPreLoginEvent(@NotNull final String name, @NotNull final InetAddress ipAddress) { | ||
@@ -53,8 +54,15 @@ public class AsyncPlayerPreLoginEvent extends Event { | ||
this(name, ipAddress, rawAddress, uniqueId, transferred, profile, ""); | ||
} | ||
|
||
+ // SparklyPaper start - Add support for login plugin requests | ||
@org.jetbrains.annotations.ApiStatus.Internal | ||
public AsyncPlayerPreLoginEvent(@NotNull final String name, @NotNull final InetAddress ipAddress, @NotNull final InetAddress rawAddress, @NotNull final UUID uniqueId, boolean transferred, @NotNull com.destroystokyo.paper.profile.PlayerProfile profile, @NotNull String hostname) { | ||
+ this(name, ipAddress, rawAddress, uniqueId, transferred, profile, hostname, null); | ||
+ } | ||
+ | ||
+ @org.jetbrains.annotations.ApiStatus.Internal | ||
+ public AsyncPlayerPreLoginEvent(@NotNull final String name, @NotNull final InetAddress ipAddress, @NotNull final InetAddress rawAddress, @NotNull final UUID uniqueId, boolean transferred, @NotNull com.destroystokyo.paper.profile.PlayerProfile profile, @NotNull String hostname, @NotNull net.sparklypower.sparklypaper.PendingConnection pendingConnection) { | ||
+ // SparklyPaper end | ||
// Paper end | ||
super(true); | ||
this.result = Result.ALLOWED; | ||
@@ -64,6 +72,7 @@ public class AsyncPlayerPreLoginEvent extends Event { | ||
this.rawAddress = rawAddress; // Paper | ||
this.hostname = hostname; // Paper | ||
this.transferred = transferred; | ||
+ this.pendingConnection = pendingConnection; // SparklyPaper - Add support for login plugin requests | ||
} | ||
|
||
/** | ||
@@ -297,6 +306,18 @@ public class AsyncPlayerPreLoginEvent extends Event { | ||
return transferred; | ||
} | ||
|
||
+ // SparklyPaper start - Add support for login plugin requests | ||
+ | ||
+ /** | ||
+ * Gets the pending connection associated with this event. | ||
+ * | ||
+ * @return The pending connection | ||
+ */ | ||
+ public net.sparklypower.sparklypaper.PendingConnection getPendingConnection() { | ||
+ return this.pendingConnection; | ||
+ } | ||
+ // SparklyPaper end | ||
+ | ||
@NotNull | ||
@Override | ||
public HandlerList getHandlers() { |
115 changes: 115 additions & 0 deletions
115
patches/removed/server/0026-Extend-AsyncPlayerPreLoginEvent-to-allow-plugins-to-.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 | ||
From: MrPowerGamerBR <[email protected]> | ||
Date: Fri, 13 Dec 2024 16:35:12 -0300 | ||
Subject: [PATCH] Extend AsyncPlayerPreLoginEvent to allow plugins to send | ||
Login Plugin Requests to the client | ||
|
||
|
||
diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java | ||
index 033755682c61c889723c3669b5cff4de147f637e..8809a4ee30d0701dab85556c54e29a5c315790bc 100644 | ||
--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java | ||
+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java | ||
@@ -92,6 +92,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener, | ||
private ServerPlayer player; // CraftBukkit | ||
public boolean iKnowThisMayNotBeTheBestIdeaButPleaseDisableUsernameValidation = false; // Paper - username validation overriding | ||
private int velocityLoginMessageId = -1; // Paper - Add Velocity IP Forwarding Support | ||
+ private net.sparklypower.sparklypaper.CraftPendingConnection pendingConnection = new net.sparklypower.sparklypaper.CraftPendingConnection(this); | ||
|
||
public ServerLoginPacketListenerImpl(MinecraftServer server, Connection connection, boolean transferred) { | ||
this.state = ServerLoginPacketListenerImpl.State.HELLO; | ||
@@ -368,7 +369,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener, | ||
// Paper start - Add more fields to AsyncPlayerPreLoginEvent | ||
final InetAddress rawAddress = ((InetSocketAddress) this.connection.channel.remoteAddress()).getAddress(); | ||
com.destroystokyo.paper.profile.PlayerProfile profile = com.destroystokyo.paper.profile.CraftPlayerProfile.asBukkitMirror(gameprofile); // Paper - setPlayerProfileAPI | ||
- AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, rawAddress, uniqueId, this.transferred, profile, this.connection.hostname); | ||
+ AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, rawAddress, uniqueId, this.transferred, profile, this.connection.hostname, this.pendingConnection); // SparklyPaper - Add support for login plugin requests | ||
server.getPluginManager().callEvent(asyncEvent); | ||
profile = asyncEvent.getPlayerProfile(); | ||
profile.complete(true); // Paper - setPlayerProfileAPI | ||
@@ -450,6 +451,11 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener, | ||
return; | ||
} | ||
// Paper end - Add Velocity IP Forwarding Support | ||
+ // SparklyPaper - Add support for login plugin requests | ||
+ if (pendingConnection.handleLoginPluginResponse(packet)) { | ||
+ return; | ||
+ } | ||
+ // SparklyPaper end | ||
this.disconnect(ServerCommonPacketListenerImpl.DISCONNECT_UNEXPECTED_QUERY); | ||
} | ||
|
||
diff --git a/src/main/kotlin/net/sparklypower/sparklypaper/CraftPendingConnection.kt b/src/main/kotlin/net/sparklypower/sparklypaper/CraftPendingConnection.kt | ||
new file mode 100644 | ||
index 0000000000000000000000000000000000000000..59570030537f5ffedd199e2c74c11f9510bc4147 | ||
--- /dev/null | ||
+++ b/src/main/kotlin/net/sparklypower/sparklypaper/CraftPendingConnection.kt | ||
@@ -0,0 +1,68 @@ | ||
+package net.sparklypower.sparklypaper | ||
+ | ||
+import com.google.common.base.Preconditions | ||
+import io.netty.buffer.Unpooled | ||
+import net.minecraft.network.FriendlyByteBuf | ||
+import net.minecraft.network.protocol.login.ClientboundCustomQueryPacket | ||
+import net.minecraft.network.protocol.login.ServerboundCustomQueryAnswerPacket | ||
+import net.minecraft.server.network.ServerLoginPacketListenerImpl | ||
+import org.bukkit.NamespacedKey | ||
+import org.bukkit.craftbukkit.util.CraftNamespacedKey | ||
+import java.util.* | ||
+import java.util.concurrent.CompletableFuture | ||
+ | ||
+class CraftPendingConnection(val manager: ServerLoginPacketListenerImpl) : PendingConnection { | ||
+ private val requestedLoginData: Queue<LoginDataFuture> = LinkedList() | ||
+ | ||
+ override fun sendLoginPluginRequest( | ||
+ transactionId: Int, | ||
+ channel: NamespacedKey, | ||
+ data: ByteArray | ||
+ ): CompletableFuture<PendingConnection.LoginPluginResponse> { | ||
+ val future = CompletableFuture<PendingConnection.LoginPluginResponse>() | ||
+ | ||
+ this.requestedLoginData.add(LoginDataFuture(transactionId, future)) | ||
+ manager.sendPacket( | ||
+ ClientboundCustomQueryPacket( | ||
+ transactionId, | ||
+ ClientboundCustomQueryPacket.PlayerInfoChannelPayload( | ||
+ CraftNamespacedKey.toMinecraft(channel), | ||
+ FriendlyByteBuf(Unpooled.wrappedBuffer(data)) | ||
+ ) | ||
+ ) | ||
+ ) | ||
+ | ||
+ return future | ||
+ } | ||
+ | ||
+ fun handleLoginPluginResponse(response: ServerboundCustomQueryAnswerPacket): Boolean { | ||
+ val future = this.requestedLoginData.peek() | ||
+ if (future != null) { | ||
+ if (future.transactionId == response.transactionId) { | ||
+ Preconditions.checkState(future === this.requestedLoginData.poll(), "requestedLoginData queue mismatch") | ||
+ if (response.payload == null) { | ||
+ future.future.complete(PendingConnection.LoginPluginResponse(false, null)) | ||
+ return true | ||
+ } | ||
+ | ||
+ val payload = response.payload as ServerboundCustomQueryAnswerPacket.QueryAnswerPayload | ||
+ | ||
+ // Ensure the reader index and writer index are not modified | ||
+ val readableBytes: Int = payload.buffer.readableBytes() | ||
+ val byteArray = ByteArray(readableBytes) | ||
+ | ||
+ // Copy the readable bytes into the byte array | ||
+ payload.buffer.getBytes(payload.buffer.readerIndex(), byteArray) | ||
+ | ||
+ future.future.complete(PendingConnection.LoginPluginResponse(true, byteArray)) | ||
+ | ||
+ return true | ||
+ } | ||
+ } | ||
+ | ||
+ return false | ||
+ } | ||
+ | ||
+ @JvmRecord | ||
+ data class LoginDataFuture(val transactionId: Int, val future: CompletableFuture<PendingConnection.LoginPluginResponse>) | ||
+} | ||
\ No newline at end of file |
Oops, something went wrong.