From b216438a477fdf0d7d1dea96e67d6f14d393f144 Mon Sep 17 00:00:00 2001 From: YoyoNow Date: Sat, 16 May 2026 11:52:06 +0200 Subject: [PATCH] Add SteamWar adaption for TinyProtocol --- .../comphenix/tinyprotocol/TinyProtocol.java | 81 ++++++++++--------- .../de/steamwar/core/CheckpointUtilsJ9.java | 10 ++- 2 files changed, 48 insertions(+), 43 deletions(-) diff --git a/SpigotCore/SpigotCore_Main/src/com/comphenix/tinyprotocol/TinyProtocol.java b/SpigotCore/SpigotCore_Main/src/com/comphenix/tinyprotocol/TinyProtocol.java index 08732ee3..5f8c02c3 100644 --- a/SpigotCore/SpigotCore_Main/src/com/comphenix/tinyprotocol/TinyProtocol.java +++ b/SpigotCore/SpigotCore_Main/src/com/comphenix/tinyprotocol/TinyProtocol.java @@ -24,6 +24,7 @@ import de.steamwar.Reflection; import de.steamwar.core.Core; import io.netty.channel.*; import net.minecraft.network.Connection; +import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.login.ServerboundHelloPacket; import net.minecraft.server.MinecraftServer; import net.minecraft.server.network.ServerConnectionListener; @@ -39,6 +40,8 @@ import org.bukkit.plugin.Plugin; import org.bukkit.scheduler.BukkitRunnable; import java.util.*; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.function.BiFunction; import java.util.logging.Level; /** @@ -57,7 +60,7 @@ public class TinyProtocol { private Set uninjectedChannels = Collections.newSetFromMap(new MapMaker().weakKeys().makeMap()); // List of network markers - private List networkManagers; + public List networkManagers; // Injected channel handlers private List serverChannels = new ArrayList<>(); @@ -72,6 +75,11 @@ public class TinyProtocol { protected Plugin plugin; public static final TinyProtocol instance = new TinyProtocol(Core.getInstance()); + private final Map, List>> packetFilters = new HashMap<>(); + + public static void init() { + // enforce init + } /** * Construct a new instance of TinyProtocol, and start intercepting packets for all connected clients and future clients. @@ -235,79 +243,63 @@ public class TinyProtocol { } } - /** - * Invoked when the server is starting to send a packet to a player. - *

- * Note that this is not executed on the main thread. - * - * @param receiver - the receiving player, NULL for early login/status packets. - * @param channel - the channel that received the packet. Never NULL. - * @param packet - the packet being sent. - * @return The packet to send instead, or NULL to cancel the transmission. - */ - public Object onPacketOutAsync(Player receiver, Channel channel, Object packet) { - return packet; + public void addTypedFilter(Class packetType, BiFunction filter) { + packetFilters.computeIfAbsent(packetType, c -> new CopyOnWriteArrayList<>()).add((BiFunction) filter); } - /** - * Invoked when the server has received a packet from a given player. - *

- * Use {@link Channel#remoteAddress()} to get the remote address of the client. - * - * @param sender - the player that sent the packet, NULL for early login/status packets. - * @param channel - channel that received the packet. Never NULL. - * @param packet - the packet being received. - * @return The packet to recieve instead, or NULL to cancel. - */ - public Object onPacketInAsync(Player sender, Channel channel, Object packet) { - return packet; + @Deprecated + public void addFilter(Class packetType, BiFunction filter) { + packetFilters.computeIfAbsent(packetType, c -> new CopyOnWriteArrayList<>()).add(filter); + } + + public void removeFilter(Class packetType, BiFunction filter) { + packetFilters.getOrDefault(packetType, Collections.emptyList()).remove(filter); } /** * Send a packet to a particular player. - *

- * Note that {@link #onPacketOutAsync(Player, Channel, Object)} will be invoked with this packet. * * @param player - the destination player. * @param packet - the packet to send. */ - public void sendPacket(Player player, Object packet) { + public void sendPacket(Player player, Packet packet) { sendPacket(getChannel(player), packet); } + @Deprecated + public void sendPacket(Player player, Object object) { + if (object instanceof Packet packet) { + sendPacket(getChannel(player), packet); + } + } + /** * Send a packet to a particular client. - *

- * Note that {@link #onPacketOutAsync(Player, Channel, Object)} will be invoked with this packet. * * @param channel - client identified by a channel. * @param packet - the packet to send. */ - public void sendPacket(Channel channel, Object packet) { + public void sendPacket(Channel channel, Packet packet) { channel.pipeline().writeAndFlush(packet); } /** * Pretend that a given packet has been received from a player. - *

- * Note that {@link #onPacketInAsync(Player, Channel, Object)} will be invoked with this packet. * * @param player - the player that sent the packet. * @param packet - the packet that will be received by the server. */ - public void receivePacket(Player player, Object packet) { + public void receivePacket(Player player, Packet packet) { receivePacket(getChannel(player), packet); } /** * Pretend that a given packet has been received from a given client. - *

- * Note that {@link #onPacketInAsync(Player, Channel, Object)} will be invoked with this packet. * * @param channel - client identified by a channel. * @param packet - the packet that will be received by the server. */ - public void receivePacket(Channel channel, Object packet) { + public void receivePacket(Channel channel, Packet packet) { channel.pipeline().context("encoder").fireChannelRead(packet); } @@ -461,7 +453,7 @@ public class TinyProtocol { handleLoginStart(channel, msg); try { - msg = onPacketInAsync(player, channel, msg); + msg = filterPacket(player, msg); } catch (Exception e) { plugin.getLogger().log(Level.SEVERE, "Error in onPacketInAsync().", e); } @@ -474,7 +466,7 @@ public class TinyProtocol { @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { try { - msg = onPacketOutAsync(player, ctx.channel(), msg); + msg = filterPacket(player, msg); } catch (Exception e) { plugin.getLogger().log(Level.SEVERE, "Error in onPacketOutAsync().", e); } @@ -489,5 +481,16 @@ public class TinyProtocol { channelLookup.put(name, channel); } } + + private Object filterPacket(Player player, Object packet) { + List> filters = packetFilters.getOrDefault(packet.getClass(), Collections.emptyList()); + + for(BiFunction filter : filters) { + packet = filter.apply(player, packet); + if(packet == null) break; + } + + return packet; + } } } \ No newline at end of file diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/core/CheckpointUtilsJ9.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/core/CheckpointUtilsJ9.java index 8f34ae6a..31577e6e 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/core/CheckpointUtilsJ9.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/core/CheckpointUtilsJ9.java @@ -23,6 +23,8 @@ import com.comphenix.tinyprotocol.TinyProtocol; import de.steamwar.Reflection; import de.steamwar.sql.internal.Statement; import io.netty.channel.ChannelFuture; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.network.ServerConnectionListener; import org.bukkit.Bukkit; import org.eclipse.openj9.criu.CRIUSupport; import org.eclipse.openj9.criu.JVMCRIUException; @@ -56,7 +58,7 @@ class CheckpointUtilsJ9 { Bukkit.getOnlinePlayers().forEach(player -> player.kickPlayer(null)); - List networkManagers = TinyProtocol.networkManagers.get(TinyProtocol.getServerConnection(Core.getInstance())); + List networkManagers = TinyProtocol.instance.networkManagers; if(!Bukkit.getOnlinePlayers().isEmpty() || !networkManagers.isEmpty()) { Core.getInstance().getLogger().log(Level.INFO, "Waiting for players to disconnect for checkpointing"); Bukkit.getScheduler().runTaskLater(Core.getInstance(), CheckpointUtils::freeze, 1); @@ -90,8 +92,8 @@ class CheckpointUtilsJ9 { } - private static final Reflection.Field channelFutures = Reflection.getField(TinyProtocol.serverConnection, List.class, 0, ChannelFuture.class); - private static final Reflection.Method bind = Reflection.getMethod(TinyProtocol.serverConnection, null, InetAddress.class, int.class); + private static final Reflection.Field channelFutures = Reflection.getField(ServerConnectionListener.class, List.class, 0, ChannelFuture.class); + private static final Reflection.Method bind = Reflection.getMethod(ServerConnectionListener.class, null, InetAddress.class, int.class); private static void freezeInternal(Path path) throws Exception { Bukkit.getPluginManager().callEvent(new CRIUSleepEvent()); @@ -99,7 +101,7 @@ class CheckpointUtilsJ9 { Statement.closeAll(); // Close socket - Object serverConnection = TinyProtocol.getServerConnection(Core.getInstance()); + ServerConnectionListener serverConnection = MinecraftServer.getServer().getConnection(); List channels = channelFutures.get(serverConnection); for(Object future : channels) { ((ChannelFuture) future).channel().close().syncUninterruptibly();