diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java index 0767a1f3c..e94c20751 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java @@ -20,6 +20,9 @@ import net.momirealms.craftengine.bukkit.pack.BukkitPackManager; import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; import net.momirealms.craftengine.bukkit.plugin.injector.BukkitInjector; import net.momirealms.craftengine.bukkit.plugin.network.handler.*; +import net.momirealms.craftengine.bukkit.plugin.network.payload.DiscardedPayload; +import net.momirealms.craftengine.bukkit.plugin.network.payload.NetWorkDataTypes; +import net.momirealms.craftengine.bukkit.plugin.network.payload.Payload; import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer; import net.momirealms.craftengine.bukkit.util.*; import net.momirealms.craftengine.core.block.ImmutableBlockState; @@ -1970,36 +1973,20 @@ public class PacketConsumers { try { if (!VersionHelper.isOrAbove1_20_5()) return; Object payload = Reflections.field$ServerboundCustomPayloadPacket$payload.get(packet); - if (payload.getClass().equals(Reflections.clazz$DiscardedPayload)) { - Object type = Reflections.method$CustomPacketPayload$type.invoke(payload); - Object id = Reflections.method$CustomPacketPayload$Type$id.invoke(type); - String channel = id.toString(); - if (!channel.equals(NetworkManager.MOD_CHANNEL)) return; - byte[] data; - if (Reflections.method$DiscardedPayload$data != null) { - ByteBuf buf = (ByteBuf) Reflections.method$DiscardedPayload$data.invoke(payload); - data = new byte[buf.readableBytes()]; - buf.readBytes(data); - } else { - data = (byte[]) Reflections.method$DiscardedPayload$dataByteArray.invoke(payload); - } - FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.wrappedBuffer(data)); + if (Reflections.clazz$DiscardedPayload.isInstance(payload)) { + Payload discardedPayload = DiscardedPayload.from(payload); + if (discardedPayload == null || !discardedPayload.channel().equals(NetworkManager.MOD_CHANNEL_KEY)) return; + FriendlyByteBuf buf = discardedPayload.toBuffer(); NetWorkDataTypes dataType = NetWorkDataTypes.readType(buf); if (dataType == NetWorkDataTypes.CLIENT_CUSTOM_BLOCK) { int clientBlockRegistrySize = dataType.as(Integer.class).decode(buf); int serverBlockRegistrySize = RegistryUtils.currentBlockRegistrySize(); if (clientBlockRegistrySize != serverBlockRegistrySize) { - Object kickPacket = Reflections.constructor$ClientboundDisconnectPacket.newInstance( - ComponentUtils.adventureToMinecraft( - Component.translatable( - "disconnect.craftengine.block_registry_mismatch", - TranslationArgument.numeric(clientBlockRegistrySize), - TranslationArgument.numeric(serverBlockRegistrySize) - ) - ) - ); - user.nettyChannel().writeAndFlush(kickPacket); - user.nettyChannel().disconnect(); + user.kick(Component.translatable( + "disconnect.craftengine.block_registry_mismatch", + TranslationArgument.numeric(clientBlockRegistrySize), + TranslationArgument.numeric(serverBlockRegistrySize) + )); return; } user.setClientModState(true); @@ -2009,10 +1996,7 @@ public class PacketConsumers { FriendlyByteBuf bufPayload = new FriendlyByteBuf(Unpooled.buffer()); dataType.writeType(bufPayload); dataType.as(Boolean.class).encode(bufPayload, true); - Object channelKey = KeyUtils.toResourceLocation(Key.of(NetworkManager.MOD_CHANNEL)); - Object dataPayload = Reflections.constructor$DiscardedPayload.newInstance(channelKey, bufPayload.array()); - Object responsePacket = Reflections.constructor$ClientboundCustomPayloadPacket.newInstance(dataPayload); - user.nettyChannel().writeAndFlush(responsePacket); + user.sendCustomPayload(NetworkManager.MOD_CHANNEL_KEY, bufPayload.array()); } } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/payload/DiscardedPayload.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/payload/DiscardedPayload.java new file mode 100644 index 000000000..d0319220a --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/payload/DiscardedPayload.java @@ -0,0 +1,44 @@ +package net.momirealms.craftengine.bukkit.plugin.network.payload; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import net.momirealms.craftengine.bukkit.util.Reflections; +import net.momirealms.craftengine.core.plugin.CraftEngine; +import net.momirealms.craftengine.core.util.FriendlyByteBuf; +import net.momirealms.craftengine.core.util.Key; + +public record DiscardedPayload(Key channel, Object rawPayload) implements Payload { + public static final boolean useNewMethod = Reflections.method$DiscardedPayload$data == null; + + public static DiscardedPayload from(Object payload) { + try { + Object type = Reflections.method$CustomPacketPayload$type.invoke(payload); + Object id = Reflections.method$CustomPacketPayload$Type$id.invoke(type); + Key channel = Key.of(id.toString()); + return new DiscardedPayload(channel, payload); + } catch (Exception e) { + CraftEngine.instance().logger().warn("Failed to create DiscardedPayload", e); + return null; + } + } + + public byte[] getData() { + try { + if (useNewMethod) { + return (byte[]) Reflections.method$DiscardedPayload$dataByteArray.invoke(this.rawPayload()); + } else { + ByteBuf buf = (ByteBuf) Reflections.method$DiscardedPayload$data.invoke(this.rawPayload()); + byte[] data = new byte[buf.readableBytes()]; + buf.readBytes(data); + return data; + } + } catch (Exception e) { + CraftEngine.instance().logger().warn("Failed to get data from DiscardedPayload", e); + return new byte[0]; + } + } + + public FriendlyByteBuf toBuffer() { + return new FriendlyByteBuf(Unpooled.wrappedBuffer(this.getData())); + } +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/NetWorkDataTypes.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/payload/NetWorkDataTypes.java similarity index 96% rename from bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/NetWorkDataTypes.java rename to bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/payload/NetWorkDataTypes.java index 50b8e57bf..281d0db70 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/NetWorkDataTypes.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/payload/NetWorkDataTypes.java @@ -1,4 +1,4 @@ -package net.momirealms.craftengine.bukkit.plugin.network; +package net.momirealms.craftengine.bukkit.plugin.network.payload; import net.momirealms.craftengine.core.util.FriendlyByteBuf; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/payload/Payload.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/payload/Payload.java new file mode 100644 index 000000000..2c82d9463 --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/payload/Payload.java @@ -0,0 +1,10 @@ +package net.momirealms.craftengine.bukkit.plugin.network.payload; + +import net.momirealms.craftengine.core.util.FriendlyByteBuf; +import net.momirealms.craftengine.core.util.Key; + +public interface Payload { + FriendlyByteBuf toBuffer(); + + Key channel(); +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java index c84f97b9f..9c6b7b5ef 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java @@ -287,6 +287,30 @@ public class BukkitServerPlayer extends Player { this.plugin.networkManager().sendPacket(this, packet, immediately); } + @Override + public void sendCustomPayload(Key channel, byte[] data) { + try { + Object channelKey = KeyUtils.toResourceLocation(channel); + Object dataPayload = Reflections.constructor$DiscardedPayload.newInstance(channelKey, data); + Object responsePacket = Reflections.constructor$ClientboundCustomPayloadPacket.newInstance(dataPayload); + this.nettyChannel().writeAndFlush(responsePacket); + } catch (Exception e) { + CraftEngine.instance().logger().warn("Failed to send custom payload to " + name(), e); + } + } + + @Override + public void kick(Component message) { + try { + Object reason = ComponentUtils.adventureToMinecraft(message); + Object kickPacket = Reflections.constructor$ClientboundDisconnectPacket.newInstance(reason); + this.nettyChannel().writeAndFlush(kickPacket); + this.nettyChannel().disconnect(); + } catch (Exception e) { + CraftEngine.instance().logger().warn("Failed to kick " + name(), e); + } + } + @Override public void sendPackets(List packet, boolean immediately) { this.plugin.networkManager().sendPackets(this, packet, immediately); diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/network/NetWorkUser.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/network/NetWorkUser.java index cf9442fee..d8fe6ec0c 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/network/NetWorkUser.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/network/NetWorkUser.java @@ -1,6 +1,7 @@ package net.momirealms.craftengine.core.plugin.network; import io.netty.channel.Channel; +import net.kyori.adventure.text.Component; import net.momirealms.craftengine.core.plugin.Plugin; import net.momirealms.craftengine.core.util.Key; import org.jetbrains.annotations.ApiStatus; @@ -25,6 +26,10 @@ public interface NetWorkUser { void sendPacket(Object packet, boolean immediately); + void sendCustomPayload(Key channel, byte[] data); + + void kick(Component message); + void simulatePacket(Object packet); @ApiStatus.Internal diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/network/NetworkManager.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/network/NetworkManager.java index 8d2b0c0ba..e24a4ba29 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/network/NetworkManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/network/NetworkManager.java @@ -3,6 +3,7 @@ package net.momirealms.craftengine.core.plugin.network; import io.netty.channel.Channel; import net.momirealms.craftengine.core.entity.player.Player; import net.momirealms.craftengine.core.plugin.Manageable; +import net.momirealms.craftengine.core.util.Key; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -10,6 +11,8 @@ import java.util.List; public interface NetworkManager extends Manageable { String MOD_CHANNEL = "craftengine:payload"; String VIA_CHANNEL = "vv:proxy_details"; + Key MOD_CHANNEL_KEY = Key.of(MOD_CHANNEL); + Key VIA_CHANNEL_KEY = Key.of(VIA_CHANNEL); void setUser(Channel channel, NetWorkUser user);