From d52cc6d8b57058e515e2d669cd9f62c61db0fd1e Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Sun, 23 Mar 2025 05:06:04 +0800 Subject: [PATCH 1/6] =?UTF-8?q?feat(network):=20=E8=A1=A5=E5=85=85?= =?UTF-8?q?=E8=81=8A=E5=A4=A9=E5=91=BD=E4=BB=A4=E6=8B=A6=E6=88=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plugin/network/BukkitNetworkManager.java | 2 + .../plugin/network/PacketConsumers.java | 44 +++++++++++++ .../craftengine/bukkit/util/Reflections.java | 64 +++++++++++++++++++ 3 files changed, 110 insertions(+) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java index 606f31b5a..01a98be91 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java @@ -128,6 +128,8 @@ public class BukkitNetworkManager implements NetworkManager, Listener { registerNMSPacketConsumer(PacketConsumers.CHAT, Reflections.clazz$ServerboundChatPacket); registerNMSPacketConsumer(PacketConsumers.RENAME_ITEM, Reflections.clazz$ServerboundRenameItemPacket); registerNMSPacketConsumer(PacketConsumers.SIGN_UPDATE, Reflections.clazz$ServerboundSignUpdatePacket); + registerNMSPacketConsumer(PacketConsumers.COMMAND_SIGNED, Reflections.clazz$ServerboundChatCommandSignedPacket); + registerNMSPacketConsumer(PacketConsumers.COMMAND, Reflections.clazz$ServerboundChatCommandPacket); registerByteBufPacketConsumer(PacketConsumers.SECTION_BLOCK_UPDATE, this.packetIds.clientboundSectionBlocksUpdatePacket()); registerByteBufPacketConsumer(PacketConsumers.BLOCK_UPDATE, this.packetIds.clientboundBlockUpdatePacket()); registerByteBufPacketConsumer(PacketConsumers.LEVEL_PARTICLE, this.packetIds.clientboundLevelParticlesPacket()); 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 7d8048590..61033587e 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 @@ -732,6 +732,50 @@ public class PacketConsumers { } }; + public static final TriConsumer COMMAND_SIGNED = (user, event, packet) -> { + try { + String command = (String) Reflections.field$ServerboundChatCommandSignedPacket$command.get(packet); + ImageManager manager = CraftEngine.instance().imageManager(); + if (!manager.isDefaultFontInUse()) return; + runIfContainsIllegalCharacter(command, manager, (s) -> { + event.setCancelled(true); + try { + Object newPacket = Reflections.constructor$ServerboundChatCommandSignedPacket.newInstance( + s, + Reflections.field$ServerboundChatCommandSignedPacket$timeStamp.get(packet), + Reflections.field$ServerboundChatCommandSignedPacket$salt.get(packet), + Reflections.field$ServerboundChatCommandSignedPacket$argumentSignatures.get(packet), + Reflections.field$ServerboundChatCommandSignedPacket$lastSeenMessages.get(packet) + ); + user.receivePacket(newPacket); + } catch (Exception e) { + CraftEngine.instance().logger().warn("Failed to create replaced chat command signed packet", e); + } + }); + } catch (Exception e) { + CraftEngine.instance().logger().warn("Failed to handle ServerboundChatCommandSignedPacket", e); + } + }; + + public static final TriConsumer COMMAND = (user, event, packet) -> { + try { + String command = (String) Reflections.field$SServerboundChatCommandPacket$command.get(packet); + ImageManager manager = CraftEngine.instance().imageManager(); + if (!manager.isDefaultFontInUse()) return; + runIfContainsIllegalCharacter(command, manager, (s) -> { + event.setCancelled(true); + try { + Object newPacket = Reflections.constructor$ServerboundChatCommandPacket.newInstance(s); + user.receivePacket(newPacket); + } catch (Exception e) { + CraftEngine.instance().logger().warn("Failed to create replaced chat command packet", e); + } + }); + } catch (Exception e) { + CraftEngine.instance().logger().warn("Failed to handle ServerboundChatCommandPacket", e); + } + }; + private static void runIfContainsIllegalCharacter(String string, ImageManager manager, Consumer callback) { char[] chars = string.toCharArray(); int[] codepoints = CharacterUtils.charsToCodePoints(chars); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java index 4ed697c8e..fba5c7c3a 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java @@ -5201,4 +5201,68 @@ public class Reflections { clazz$ServerboundSignUpdatePacket, String[].class, 0 ) ); + + public static final Class clazz$ArgumentSignatures = requireNonNull( + ReflectionUtils.getClazz( + BukkitReflectionUtils.assembleMCClass("commands.arguments.ArgumentSignatures") + ) + ); + + public static final Class clazz$ServerboundChatCommandSignedPacket = requireNonNull( + ReflectionUtils.getClazz( + BukkitReflectionUtils.assembleMCClass("network.protocol.game.ServerboundChatCommandSignedPacket"), + BukkitReflectionUtils.assembleMCClass("network.protocol.game.ServerboundChatCommandPacket") + ) + ); + + public static final Field field$ServerboundChatCommandSignedPacket$command = requireNonNull( + ReflectionUtils.getDeclaredField( + clazz$ServerboundChatCommandSignedPacket, String.class, 0 + ) + ); + + public static final Field field$ServerboundChatCommandSignedPacket$timeStamp = requireNonNull( + ReflectionUtils.getDeclaredField( + clazz$ServerboundChatCommandSignedPacket, Instant.class, 0 + ) + ); + + public static final Field field$ServerboundChatCommandSignedPacket$salt = requireNonNull( + ReflectionUtils.getDeclaredField( + clazz$ServerboundChatCommandSignedPacket, long.class, 0 + ) + ); + + public static final Field field$ServerboundChatCommandSignedPacket$argumentSignatures = requireNonNull( + ReflectionUtils.getDeclaredField( + clazz$ServerboundChatCommandSignedPacket, clazz$ArgumentSignatures, 0 + ) + ); + + public static final Field field$ServerboundChatCommandSignedPacket$lastSeenMessages = requireNonNull( + ReflectionUtils.getDeclaredField( + clazz$ServerboundChatCommandSignedPacket, clazz$LastSeenMessages$Update, 0 + ) + ); + + public static final Constructor constructor$ServerboundChatCommandSignedPacket = requireNonNull( + ReflectionUtils.getConstructor( + clazz$ServerboundChatCommandSignedPacket, String.class, Instant.class, long.class, clazz$ArgumentSignatures, clazz$LastSeenMessages$Update + ) + ); + + // 1.20.5+ + public static final Class clazz$ServerboundChatCommandPacket = VersionHelper.isVersionNewerThan1_20_5() + ? ReflectionUtils.getClazz(BukkitReflectionUtils.assembleMCClass("network.protocol.game.ServerboundChatCommandPacket")) + : null; + + // 1.20.5+ + public static final Field field$SServerboundChatCommandPacket$command = Optional.ofNullable(clazz$ServerboundChatCommandPacket) + .map(it -> ReflectionUtils.getDeclaredField(it, String.class, 0)) + .orElse(null); + + // 1.20.5+ + public static final Constructor constructor$ServerboundChatCommandPacket = Optional.ofNullable(clazz$ServerboundChatCommandPacket) + .map(it -> ReflectionUtils.getConstructor(it, String.class)) + .orElse(null); } From 8024b3137d61093c7917ce879efd74f01d6eed2c Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Sun, 23 Mar 2025 07:50:23 +0800 Subject: [PATCH 2/6] =?UTF-8?q?feat(network):=20=E8=A1=A5=E5=85=85?= =?UTF-8?q?=E8=81=8A=E5=A4=A9=E5=91=BD=E4=BB=A4=E6=8B=A6=E6=88=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bukkit/font/BukkitImageManager.java | 94 +++++++++++++++++++ .../bukkit/plugin/BukkitCraftEngine.java | 2 + .../plugin/network/BukkitNetworkManager.java | 6 +- .../plugin/network/PacketConsumers.java | 1 + .../craftengine/bukkit/util/Reflections.java | 62 ++++++++++++ ...gerImpl.java => AbstractImageManager.java} | 4 +- .../craftengine/core/font/ImageManager.java | 2 + .../craftengine/core/plugin/CraftEngine.java | 4 +- .../core/util/AdventureHelper.java | 19 ++++ 9 files changed, 187 insertions(+), 7 deletions(-) create mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/font/BukkitImageManager.java rename core/src/main/java/net/momirealms/craftengine/core/font/{ImageManagerImpl.java => AbstractImageManager.java} (98%) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/font/BukkitImageManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/font/BukkitImageManager.java new file mode 100644 index 000000000..be5a5ebdf --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/font/BukkitImageManager.java @@ -0,0 +1,94 @@ +package net.momirealms.craftengine.bukkit.font; + +import com.google.gson.JsonElement; +import io.papermc.paper.event.player.AsyncChatCommandDecorateEvent; +import io.papermc.paper.event.player.AsyncChatDecorateEvent; +import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; +import net.momirealms.craftengine.bukkit.util.Reflections; +import net.momirealms.craftengine.core.font.AbstractImageManager; +import net.momirealms.craftengine.core.util.AdventureHelper; +import net.momirealms.craftengine.core.util.CharacterUtils; +import org.bukkit.Bukkit; +import org.bukkit.event.EventHandler; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; +import org.bukkit.event.server.ServerCommandEvent; + +import java.lang.reflect.InvocationTargetException; + +public class BukkitImageManager extends AbstractImageManager implements Listener { + private final BukkitCraftEngine plugin; + private final Object serializer; + + public BukkitImageManager(BukkitCraftEngine plugin) { + super(plugin); + this.plugin = plugin; + try { + Object builder = Reflections.method$GsonComponentSerializer$builder.invoke(null); + this.serializer = Reflections.method$GsonComponentSerializer$Builder$build.invoke(builder); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + } + + @Override + public void delayedInit() { + Bukkit.getPluginManager().registerEvents(this, plugin.bootstrap()); + } + + @Override + public void disable() { + super.disable(); + HandlerList.unregisterAll(this); + } + + @EventHandler + @SuppressWarnings("UnstableApiUsage") + public void onChat(AsyncChatDecorateEvent event) { + if (event.player() == null) return; + this.ProcessChatMessages(event); + } + + @EventHandler + @SuppressWarnings("UnstableApiUsage") + public void onChatCommand(AsyncChatCommandDecorateEvent event) { + if (event.player() == null) return; + this.ProcessChatMessages(event); + } + + @EventHandler + public void onCommand(PlayerCommandPreprocessEvent event) { + event.setMessage(processIllegalString(event.getMessage())); + } + + @SuppressWarnings("UnstableApiUsage") + private void ProcessChatMessages(AsyncChatDecorateEvent event) { + try { + Object originalMessage = Reflections.clazz$AdventureComponent.cast(Reflections.field$AsyncChatDecorateEvent$originalMessage.get(event)); + JsonElement json = (JsonElement) Reflections.method$GsonComponentSerializer$serializeToTree.invoke(serializer, originalMessage); + String jsonMessage = AdventureHelper.jsonElementToStringJson(json); + if (!this.isDefaultFontInUse()) return; + String str = processIllegalString(jsonMessage); + Object component = Reflections.method$ComponentSerializer$deserialize.invoke(serializer, str); + Reflections.method$AsyncChatDecorateEvent$result.invoke(event, component); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + } + + private String processIllegalString(String string) { + char[] chars = string.toCharArray(); + int[] codepoints = CharacterUtils.charsToCodePoints(chars); + int[] newCodepoints = new int[codepoints.length]; + for (int i = 0; i < codepoints.length; i++) { + int codepoint = codepoints[i]; + if (!this.isIllegalCharacter(codepoint)) { + newCodepoints[i] = codepoint; + } else { + newCodepoints[i] = '*'; + } + } + return new String(newCodepoints, 0, newCodepoints.length); + } +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/BukkitCraftEngine.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/BukkitCraftEngine.java index 6104cfcf5..28ab754da 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/BukkitCraftEngine.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/BukkitCraftEngine.java @@ -5,6 +5,7 @@ import net.momirealms.craftengine.bukkit.api.event.CraftEngineReloadEvent; import net.momirealms.craftengine.bukkit.block.BukkitBlockManager; import net.momirealms.craftengine.bukkit.block.behavior.BukkitBlockBehaviors; import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager; +import net.momirealms.craftengine.bukkit.font.BukkitImageManager; import net.momirealms.craftengine.bukkit.item.BukkitItemManager; import net.momirealms.craftengine.bukkit.item.behavior.BukkitItemBehaviors; import net.momirealms.craftengine.bukkit.item.recipe.BukkitRecipeManager; @@ -138,6 +139,7 @@ public class BukkitCraftEngine extends CraftEngine { super.worldManager = new BukkitWorldManager(this); super.soundManager = new BukkitSoundManager(this); super.vanillaLootManager = new BukkitVanillaLootManager(this); + this.imageManager = new BukkitImageManager(this); super.enable(); // tick task if (VersionHelper.isFolia()) { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java index 01a98be91..e47b3715b 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java @@ -125,11 +125,11 @@ public class BukkitNetworkManager implements NetworkManager, Listener { registerNMSPacketConsumer(PacketConsumers.MOVE_ENTITY, Reflections.clazz$ClientboundMoveEntityPacket$Pos); registerNMSPacketConsumer(PacketConsumers.PICK_ITEM_FROM_ENTITY, Reflections.clazz$ServerboundPickItemFromEntityPacket); registerNMSPacketConsumer(PacketConsumers.SOUND, Reflections.clazz$ClientboundSoundPacket); - registerNMSPacketConsumer(PacketConsumers.CHAT, Reflections.clazz$ServerboundChatPacket); + // registerNMSPacketConsumer(PacketConsumers.CHAT, Reflections.clazz$ServerboundChatPacket); registerNMSPacketConsumer(PacketConsumers.RENAME_ITEM, Reflections.clazz$ServerboundRenameItemPacket); registerNMSPacketConsumer(PacketConsumers.SIGN_UPDATE, Reflections.clazz$ServerboundSignUpdatePacket); - registerNMSPacketConsumer(PacketConsumers.COMMAND_SIGNED, Reflections.clazz$ServerboundChatCommandSignedPacket); - registerNMSPacketConsumer(PacketConsumers.COMMAND, Reflections.clazz$ServerboundChatCommandPacket); + // registerNMSPacketConsumer(PacketConsumers.COMMAND_SIGNED, Reflections.clazz$ServerboundChatCommandSignedPacket); + // registerNMSPacketConsumer(PacketConsumers.COMMAND, Reflections.clazz$ServerboundChatCommandPacket); registerByteBufPacketConsumer(PacketConsumers.SECTION_BLOCK_UPDATE, this.packetIds.clientboundSectionBlocksUpdatePacket()); registerByteBufPacketConsumer(PacketConsumers.BLOCK_UPDATE, this.packetIds.clientboundBlockUpdatePacket()); registerByteBufPacketConsumer(PacketConsumers.LEVEL_PARTICLE, this.packetIds.clientboundLevelParticlesPacket()); 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 61033587e..73e940c4c 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 @@ -777,6 +777,7 @@ public class PacketConsumers { }; private static void runIfContainsIllegalCharacter(String string, ImageManager manager, Consumer callback) { + //noinspection DuplicatedCode char[] chars = string.toCharArray(); int[] codepoints = CharacterUtils.charsToCodePoints(chars); int[] newCodepoints = new int[codepoints.length]; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java index fba5c7c3a..a859275ad 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java @@ -1,12 +1,14 @@ package net.momirealms.craftengine.bukkit.util; import com.google.common.collect.ImmutableList; +import com.google.gson.JsonElement; import io.netty.buffer.ByteBuf; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; import io.netty.handler.codec.MessageToByteEncoder; +import io.papermc.paper.event.player.AsyncChatDecorateEvent; import net.kyori.adventure.text.Component; import net.momirealms.craftengine.core.util.ReflectionUtils; import net.momirealms.craftengine.core.util.VersionHelper; @@ -5265,4 +5267,64 @@ public class Reflections { public static final Constructor constructor$ServerboundChatCommandPacket = Optional.ofNullable(clazz$ServerboundChatCommandPacket) .map(it -> ReflectionUtils.getConstructor(it, String.class)) .orElse(null); + + @SuppressWarnings("UnstableApiUsage") + public static final Field field$AsyncChatDecorateEvent$originalMessage = requireNonNull( + ReflectionUtils.getDeclaredField(AsyncChatDecorateEvent.class, "originalMessage") + ); + + public static final Class clazz$ComponentSerializer = requireNonNull( + ReflectionUtils.getClazz( + "net{}kyori{}adventure{}text{}serializer{}ComponentSerializer".replace("{}", ".") + ) + ); + + public static final Class clazz$GsonComponentSerializer = requireNonNull( + ReflectionUtils.getClazz( + "net{}kyori{}adventure{}text{}serializer{}gson{}GsonComponentSerializer".replace("{}", ".") + ) + ); + + public static final Class clazz$GsonComponentSerializer$Builder = requireNonNull( + ReflectionUtils.getClazz( + "net{}kyori{}adventure{}text{}serializer{}gson{}GsonComponentSerializer$Builder".replace("{}", ".") + ) + ); + + public static final Class clazz$AdventureComponent = requireNonNull( + ReflectionUtils.getClazz( + "net{}kyori{}adventure{}text{}Component".replace("{}", ".") + ) + ); + + public static final Method method$GsonComponentSerializer$builder = requireNonNull( + ReflectionUtils.getMethod( + clazz$GsonComponentSerializer, clazz$GsonComponentSerializer$Builder + ) + ); + + public static final Method method$GsonComponentSerializer$Builder$build = requireNonNull( + ReflectionUtils.getMethod( + clazz$GsonComponentSerializer$Builder, clazz$GsonComponentSerializer + ) + ); + + public static final Method method$GsonComponentSerializer$serializeToTree = requireNonNull( + ReflectionUtils.getMethod( + clazz$GsonComponentSerializer, JsonElement.class, clazz$AdventureComponent + ) + ); + + public static final Method method$ComponentSerializer$deserialize = requireNonNull( + ReflectionUtils.getMethod( + clazz$ComponentSerializer, Object.class, Object.class + ) + ); + + @SuppressWarnings("UnstableApiUsage") + public static final Method method$AsyncChatDecorateEvent$result = requireNonNull( + ReflectionUtils.getMethod( + AsyncChatDecorateEvent.class, void.class, clazz$AdventureComponent + ) + ); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/font/ImageManagerImpl.java b/core/src/main/java/net/momirealms/craftengine/core/font/AbstractImageManager.java similarity index 98% rename from core/src/main/java/net/momirealms/craftengine/core/font/ImageManagerImpl.java rename to core/src/main/java/net/momirealms/craftengine/core/font/AbstractImageManager.java index ace8f47e0..59c46871b 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/font/ImageManagerImpl.java +++ b/core/src/main/java/net/momirealms/craftengine/core/font/AbstractImageManager.java @@ -12,7 +12,7 @@ import java.nio.file.Path; import java.util.*; import java.util.function.BiFunction; -public class ImageManagerImpl implements ImageManager { +public abstract class AbstractImageManager implements ImageManager { private final CraftEngine plugin; // namespace:font font private final HashMap fonts = new HashMap<>(); @@ -22,7 +22,7 @@ public class ImageManagerImpl implements ImageManager { private OffsetFont offsetFont; - public ImageManagerImpl(CraftEngine plugin) { + public AbstractImageManager(CraftEngine plugin) { this.plugin = plugin; } diff --git a/core/src/main/java/net/momirealms/craftengine/core/font/ImageManager.java b/core/src/main/java/net/momirealms/craftengine/core/font/ImageManager.java index ac114d578..7c38e8643 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/font/ImageManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/font/ImageManager.java @@ -68,4 +68,6 @@ public interface ImageManager extends Reloadable, ConfigSectionParser { default int loadingSequence() { return LoadingSequence.FONT; } + + void delayedInit(); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/CraftEngine.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/CraftEngine.java index 931804201..62626b2c3 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/CraftEngine.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/CraftEngine.java @@ -3,7 +3,7 @@ package net.momirealms.craftengine.core.plugin; import net.momirealms.craftengine.core.block.BlockManager; import net.momirealms.craftengine.core.entity.furniture.FurnitureManager; import net.momirealms.craftengine.core.font.ImageManager; -import net.momirealms.craftengine.core.font.ImageManagerImpl; +import net.momirealms.craftengine.core.font.AbstractImageManager; import net.momirealms.craftengine.core.item.ItemManager; import net.momirealms.craftengine.core.item.recipe.RecipeManager; import net.momirealms.craftengine.core.loot.VanillaLootManager; @@ -120,7 +120,6 @@ public abstract class CraftEngine implements Plugin { @Override public void enable() { this.networkManager.enable(); - this.imageManager = new ImageManagerImpl(this); this.templateManager = new TemplateManagerImpl(this); this.itemBrowserManager = new ItemBrowserManagerImpl(this); this.commandManager.registerDefaultFeatures(); @@ -135,6 +134,7 @@ public abstract class CraftEngine implements Plugin { this.worldManager.delayedInit(); this.packManager.delayedInit(); this.furnitureManager.delayedInit(); + this.imageManager.delayedInit(); }); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/util/AdventureHelper.java b/core/src/main/java/net/momirealms/craftengine/core/util/AdventureHelper.java index d75919cbc..ef6d177ae 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/util/AdventureHelper.java +++ b/core/src/main/java/net/momirealms/craftengine/core/util/AdventureHelper.java @@ -2,6 +2,7 @@ package net.momirealms.craftengine.core.util; import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Caffeine; +import com.google.gson.JsonElement; import net.kyori.adventure.audience.Audience; import net.kyori.adventure.key.Key; import net.kyori.adventure.sound.Sound; @@ -182,6 +183,24 @@ public class AdventureHelper { return getGson().serialize(component); } + /** + * Converts a JsonElement to a Component. + * @param gson the JsonElement to convert + * @return the resulting Component + */ + public static Component jsonElementToComponent(JsonElement gson) { + return GsonComponentSerializer.gson().deserializeFromTree(gson); + } + + /** + * Converts a JsonElement to a JSON string. + * @param gson the JsonElement to convert + * @return the JSON string representation + */ + public static String jsonElementToStringJson(JsonElement gson) { + return componentToJson(jsonElementToComponent(gson)); + } + /** * Checks if a character is a legacy color code. * From 7a3c4fb61fe94cdee2fabf04336bd68ca5425987 Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Sun, 23 Mar 2025 07:53:05 +0800 Subject: [PATCH 3/6] =?UTF-8?q?refactor(network):=20=E6=B8=85=E7=90=86?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plugin/network/BukkitNetworkManager.java | 3 - .../plugin/network/PacketConsumers.java | 72 ------------------- .../craftengine/bukkit/util/Reflections.java | 64 ----------------- 3 files changed, 139 deletions(-) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java index e47b3715b..8bb11eb90 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java @@ -125,11 +125,8 @@ public class BukkitNetworkManager implements NetworkManager, Listener { registerNMSPacketConsumer(PacketConsumers.MOVE_ENTITY, Reflections.clazz$ClientboundMoveEntityPacket$Pos); registerNMSPacketConsumer(PacketConsumers.PICK_ITEM_FROM_ENTITY, Reflections.clazz$ServerboundPickItemFromEntityPacket); registerNMSPacketConsumer(PacketConsumers.SOUND, Reflections.clazz$ClientboundSoundPacket); - // registerNMSPacketConsumer(PacketConsumers.CHAT, Reflections.clazz$ServerboundChatPacket); registerNMSPacketConsumer(PacketConsumers.RENAME_ITEM, Reflections.clazz$ServerboundRenameItemPacket); registerNMSPacketConsumer(PacketConsumers.SIGN_UPDATE, Reflections.clazz$ServerboundSignUpdatePacket); - // registerNMSPacketConsumer(PacketConsumers.COMMAND_SIGNED, Reflections.clazz$ServerboundChatCommandSignedPacket); - // registerNMSPacketConsumer(PacketConsumers.COMMAND, Reflections.clazz$ServerboundChatCommandPacket); registerByteBufPacketConsumer(PacketConsumers.SECTION_BLOCK_UPDATE, this.packetIds.clientboundSectionBlocksUpdatePacket()); registerByteBufPacketConsumer(PacketConsumers.BLOCK_UPDATE, this.packetIds.clientboundBlockUpdatePacket()); registerByteBufPacketConsumer(PacketConsumers.LEVEL_PARTICLE, this.packetIds.clientboundLevelParticlesPacket()); 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 73e940c4c..0ac89fa5a 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 @@ -663,34 +663,6 @@ public class PacketConsumers { } }; - // we handle it on packet level to prevent it from being captured by plugins (most are chat plugins) - public static final TriConsumer CHAT = (user, event, packet) -> { - try { - String message = (String) Reflections.field$ServerboundChatPacket$message.get(packet); - if (message != null && !message.isEmpty()) { - ImageManager manager = CraftEngine.instance().imageManager(); - if (!manager.isDefaultFontInUse()) return; - runIfContainsIllegalCharacter(message, manager, (s) -> { - event.setCancelled(true); - try { - Object newPacket = Reflections.constructor$ServerboundChatPacket.newInstance( - s, - Reflections.field$ServerboundChatPacket$timeStamp.get(packet), - Reflections.field$ServerboundChatPacket$salt.get(packet), - Reflections.field$ServerboundChatPacket$signature.get(packet), - Reflections.field$ServerboundChatPacket$lastSeenMessages.get(packet) - ); - user.receivePacket(newPacket); - } catch (Exception e) { - CraftEngine.instance().logger().warn("Failed to create replaced chat packet", e); - } - }); - } - } catch (Exception e) { - CraftEngine.instance().logger().warn("Failed to handle ServerboundChatPacket", e); - } - }; - // we handle it on packet level to prevent it from being captured by plugins public static final TriConsumer RENAME_ITEM = (user, event, packet) -> { try { @@ -732,50 +704,6 @@ public class PacketConsumers { } }; - public static final TriConsumer COMMAND_SIGNED = (user, event, packet) -> { - try { - String command = (String) Reflections.field$ServerboundChatCommandSignedPacket$command.get(packet); - ImageManager manager = CraftEngine.instance().imageManager(); - if (!manager.isDefaultFontInUse()) return; - runIfContainsIllegalCharacter(command, manager, (s) -> { - event.setCancelled(true); - try { - Object newPacket = Reflections.constructor$ServerboundChatCommandSignedPacket.newInstance( - s, - Reflections.field$ServerboundChatCommandSignedPacket$timeStamp.get(packet), - Reflections.field$ServerboundChatCommandSignedPacket$salt.get(packet), - Reflections.field$ServerboundChatCommandSignedPacket$argumentSignatures.get(packet), - Reflections.field$ServerboundChatCommandSignedPacket$lastSeenMessages.get(packet) - ); - user.receivePacket(newPacket); - } catch (Exception e) { - CraftEngine.instance().logger().warn("Failed to create replaced chat command signed packet", e); - } - }); - } catch (Exception e) { - CraftEngine.instance().logger().warn("Failed to handle ServerboundChatCommandSignedPacket", e); - } - }; - - public static final TriConsumer COMMAND = (user, event, packet) -> { - try { - String command = (String) Reflections.field$SServerboundChatCommandPacket$command.get(packet); - ImageManager manager = CraftEngine.instance().imageManager(); - if (!manager.isDefaultFontInUse()) return; - runIfContainsIllegalCharacter(command, manager, (s) -> { - event.setCancelled(true); - try { - Object newPacket = Reflections.constructor$ServerboundChatCommandPacket.newInstance(s); - user.receivePacket(newPacket); - } catch (Exception e) { - CraftEngine.instance().logger().warn("Failed to create replaced chat command packet", e); - } - }); - } catch (Exception e) { - CraftEngine.instance().logger().warn("Failed to handle ServerboundChatCommandPacket", e); - } - }; - private static void runIfContainsIllegalCharacter(String string, ImageManager manager, Consumer callback) { //noinspection DuplicatedCode char[] chars = string.toCharArray(); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java index a859275ad..60566bdc6 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java @@ -5204,70 +5204,6 @@ public class Reflections { ) ); - public static final Class clazz$ArgumentSignatures = requireNonNull( - ReflectionUtils.getClazz( - BukkitReflectionUtils.assembleMCClass("commands.arguments.ArgumentSignatures") - ) - ); - - public static final Class clazz$ServerboundChatCommandSignedPacket = requireNonNull( - ReflectionUtils.getClazz( - BukkitReflectionUtils.assembleMCClass("network.protocol.game.ServerboundChatCommandSignedPacket"), - BukkitReflectionUtils.assembleMCClass("network.protocol.game.ServerboundChatCommandPacket") - ) - ); - - public static final Field field$ServerboundChatCommandSignedPacket$command = requireNonNull( - ReflectionUtils.getDeclaredField( - clazz$ServerboundChatCommandSignedPacket, String.class, 0 - ) - ); - - public static final Field field$ServerboundChatCommandSignedPacket$timeStamp = requireNonNull( - ReflectionUtils.getDeclaredField( - clazz$ServerboundChatCommandSignedPacket, Instant.class, 0 - ) - ); - - public static final Field field$ServerboundChatCommandSignedPacket$salt = requireNonNull( - ReflectionUtils.getDeclaredField( - clazz$ServerboundChatCommandSignedPacket, long.class, 0 - ) - ); - - public static final Field field$ServerboundChatCommandSignedPacket$argumentSignatures = requireNonNull( - ReflectionUtils.getDeclaredField( - clazz$ServerboundChatCommandSignedPacket, clazz$ArgumentSignatures, 0 - ) - ); - - public static final Field field$ServerboundChatCommandSignedPacket$lastSeenMessages = requireNonNull( - ReflectionUtils.getDeclaredField( - clazz$ServerboundChatCommandSignedPacket, clazz$LastSeenMessages$Update, 0 - ) - ); - - public static final Constructor constructor$ServerboundChatCommandSignedPacket = requireNonNull( - ReflectionUtils.getConstructor( - clazz$ServerboundChatCommandSignedPacket, String.class, Instant.class, long.class, clazz$ArgumentSignatures, clazz$LastSeenMessages$Update - ) - ); - - // 1.20.5+ - public static final Class clazz$ServerboundChatCommandPacket = VersionHelper.isVersionNewerThan1_20_5() - ? ReflectionUtils.getClazz(BukkitReflectionUtils.assembleMCClass("network.protocol.game.ServerboundChatCommandPacket")) - : null; - - // 1.20.5+ - public static final Field field$SServerboundChatCommandPacket$command = Optional.ofNullable(clazz$ServerboundChatCommandPacket) - .map(it -> ReflectionUtils.getDeclaredField(it, String.class, 0)) - .orElse(null); - - // 1.20.5+ - public static final Constructor constructor$ServerboundChatCommandPacket = Optional.ofNullable(clazz$ServerboundChatCommandPacket) - .map(it -> ReflectionUtils.getConstructor(it, String.class)) - .orElse(null); - @SuppressWarnings("UnstableApiUsage") public static final Field field$AsyncChatDecorateEvent$originalMessage = requireNonNull( ReflectionUtils.getDeclaredField(AsyncChatDecorateEvent.class, "originalMessage") From 0d7c877d86aa6290e5e60f0e229159271531992b Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Sun, 23 Mar 2025 07:59:59 +0800 Subject: [PATCH 4/6] =?UTF-8?q?feat(bukkit):=20=E5=A2=9E=E5=8A=A0=E9=98=BB?= =?UTF-8?q?=E6=AD=A2=E8=BF=90=E8=A1=8C=E6=97=B6=E5=90=AF=E7=94=A8/?= =?UTF-8?q?=E7=A6=81=E7=94=A8=E6=8F=92=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bukkit/plugin/BukkitCraftEngine.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/BukkitCraftEngine.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/BukkitCraftEngine.java index 28ab754da..37dc18dfd 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/BukkitCraftEngine.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/BukkitCraftEngine.java @@ -57,6 +57,7 @@ public class BukkitCraftEngine extends CraftEngine { private final JavaPlugin bootstrap; private SchedulerTask tickTask; private boolean successfullyLoaded = false; + private boolean successfullyEnabled = false; private boolean requiresRestart = false; private boolean hasMod = false; private AntiGriefLib antiGrief; @@ -104,6 +105,13 @@ public class BukkitCraftEngine extends CraftEngine { @Override public void enable() { + if (successfullyEnabled) { + logger().severe(" "); + logger().severe("Please do not reload/restart plugins at runtime"); + logger().severe(" "); + return; + } + this.successfullyEnabled = true; if (this.hasMod && this.requiresRestart) { logger().warn(" "); logger().warn(" "); @@ -175,6 +183,12 @@ public class BukkitCraftEngine extends CraftEngine { @Override public void disable() { + if (!Bukkit.getServer().isStopping()) { + logger().severe(" "); + logger().severe("Please do not disable plugins at runtime"); + logger().severe(" "); + return; + } super.disable(); if (this.tickTask != null) this.tickTask.cancel(); } From 720d9552a606cd482ec28caff90b5d4b78412f7f Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Sun, 23 Mar 2025 08:31:14 +0800 Subject: [PATCH 5/6] =?UTF-8?q?feat(bukkit):=20=E7=AE=80=E7=BA=A6=E7=9A=84?= =?UTF-8?q?=E6=93=8D=E4=BD=9C=E8=AE=A9=E7=94=A8=E6=88=B7=E7=9F=A5=E9=81=93?= =?UTF-8?q?=E4=B8=8D=E8=83=BD=E5=9C=A8=E8=BF=90=E8=A1=8C=E6=97=B6=E9=87=8D?= =?UTF-8?q?=E8=BD=BD=E6=8F=92=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bukkit/plugin/BukkitCraftEngine.java | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/BukkitCraftEngine.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/BukkitCraftEngine.java index 37dc18dfd..19571f6b8 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/BukkitCraftEngine.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/BukkitCraftEngine.java @@ -50,6 +50,7 @@ import java.lang.reflect.Field; import java.nio.file.Path; import java.util.List; import java.util.Optional; +import java.util.concurrent.TimeUnit; @SuppressWarnings("unchecked") public class BukkitCraftEngine extends CraftEngine { @@ -107,8 +108,13 @@ public class BukkitCraftEngine extends CraftEngine { public void enable() { if (successfullyEnabled) { logger().severe(" "); - logger().severe("Please do not reload/restart plugins at runtime"); logger().severe(" "); + logger().severe(" "); + logger().severe("Please do not restart plugins at runtime."); + logger().severe(" "); + logger().severe(" "); + logger().severe(" "); + Bukkit.getPluginManager().disablePlugin(this.bootstrap); return; } this.successfullyEnabled = true; @@ -183,14 +189,18 @@ public class BukkitCraftEngine extends CraftEngine { @Override public void disable() { - if (!Bukkit.getServer().isStopping()) { - logger().severe(" "); - logger().severe("Please do not disable plugins at runtime"); - logger().severe(" "); - return; - } super.disable(); if (this.tickTask != null) this.tickTask.cancel(); + if (!Bukkit.getServer().isStopping()) { + logger().severe(" "); + logger().severe(" "); + logger().severe(" "); + logger().severe("Please do not disable plugins at runtime."); + logger().severe(" "); + logger().severe(" "); + logger().severe(" "); + Bukkit.getServer().shutdown(); + } } @Override From 33a6dc982f9b2d83422be79199e7744ec54e1e8e Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Sun, 23 Mar 2025 16:02:08 +0800 Subject: [PATCH 6/6] =?UTF-8?q?refactor(core):=20=E4=BF=AE=E6=AD=A3?= =?UTF-8?q?=E4=B8=80=E4=BA=9B=E7=BB=86=E8=8A=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../craftengine/bukkit/font/BukkitImageManager.java | 7 +++---- .../momirealms/craftengine/core/util/AdventureHelper.java | 6 +++--- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/font/BukkitImageManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/font/BukkitImageManager.java index be5a5ebdf..d8570fd66 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/font/BukkitImageManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/font/BukkitImageManager.java @@ -13,7 +13,6 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerCommandPreprocessEvent; -import org.bukkit.event.server.ServerCommandEvent; import java.lang.reflect.InvocationTargetException; @@ -47,14 +46,14 @@ public class BukkitImageManager extends AbstractImageManager implements Listener @SuppressWarnings("UnstableApiUsage") public void onChat(AsyncChatDecorateEvent event) { if (event.player() == null) return; - this.ProcessChatMessages(event); + this.processChatMessages(event); } @EventHandler @SuppressWarnings("UnstableApiUsage") public void onChatCommand(AsyncChatCommandDecorateEvent event) { if (event.player() == null) return; - this.ProcessChatMessages(event); + this.processChatMessages(event); } @EventHandler @@ -63,7 +62,7 @@ public class BukkitImageManager extends AbstractImageManager implements Listener } @SuppressWarnings("UnstableApiUsage") - private void ProcessChatMessages(AsyncChatDecorateEvent event) { + private void processChatMessages(AsyncChatDecorateEvent event) { try { Object originalMessage = Reflections.clazz$AdventureComponent.cast(Reflections.field$AsyncChatDecorateEvent$originalMessage.get(event)); JsonElement json = (JsonElement) Reflections.method$GsonComponentSerializer$serializeToTree.invoke(serializer, originalMessage); diff --git a/core/src/main/java/net/momirealms/craftengine/core/util/AdventureHelper.java b/core/src/main/java/net/momirealms/craftengine/core/util/AdventureHelper.java index ef6d177ae..ea801883e 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/util/AdventureHelper.java +++ b/core/src/main/java/net/momirealms/craftengine/core/util/AdventureHelper.java @@ -194,11 +194,11 @@ public class AdventureHelper { /** * Converts a JsonElement to a JSON string. - * @param gson the JsonElement to convert + * @param jsonElement the JsonElement to convert * @return the JSON string representation */ - public static String jsonElementToStringJson(JsonElement gson) { - return componentToJson(jsonElementToComponent(gson)); + public static String jsonElementToStringJson(JsonElement jsonElement) { + return componentToJson(jsonElementToComponent(jsonElement)); } /**