From 53c85298b231527ca551598b3be440bdaad07fe8 Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Mon, 24 Mar 2025 22:30:20 +0800 Subject: [PATCH] add options for filters --- bukkit/loader/src/main/resources/config.yml | 15 ++++++--- .../bukkit/font/BukkitImageManager.java | 25 ++++++++++---- .../plugin/network/PacketConsumers.java | 15 +++++++++ .../craftengine/core/font/ImageManager.java | 5 +++ .../core/plugin/config/ConfigManager.java | 33 +++++++++++++++++++ 5 files changed, 82 insertions(+), 11 deletions(-) diff --git a/bukkit/loader/src/main/resources/config.yml b/bukkit/loader/src/main/resources/config.yml index 0546ca672..e4aa5638c 100644 --- a/bukkit/loader/src/main/resources/config.yml +++ b/bukkit/loader/src/main/resources/config.yml @@ -13,12 +13,10 @@ resource-pack: # Should those images in minecraft:default font also work in minecraft:uniform override-uniform-font: true # Generate assets for CraftEngine fabric mod - # Note: CraftEngine fabric mod is used for Axiom mod, most users do not need to install it + # Note: fabric mod is used for clientside Axiom/WorldEdit mod generate-mod-assets: false # Resource pack protection protection: - # Warning: Do not attempt to unzip the resource pack with crash tools enabled. - # Warning: Do not attempt to unzip the resource pack with crash tools enabled. # Warning: Do not attempt to unzip the resource pack with crash tools enabled. # You can enable all the methods at the same time. crash-tools: @@ -55,7 +53,6 @@ resource-pack: bypass-models: [] bypass-sounds: [] bypass-equipments: [] - supported-version: min: "1.20" max: LATEST @@ -140,6 +137,16 @@ furniture: list: - "xxx:invalid_furniture" +image: + # Prevent players from using images set in minecraft:default font + # Players with `craftengine.filter.bypass.xxx` would ignore the limitation + illegal-characters-filter: + anvil: true + book: true + chat: true + command: true + sign: true + recipe: enable: true 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 b636ef95c..6dcd6e430 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 @@ -5,8 +5,11 @@ 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.font.ImageManager; +import net.momirealms.craftengine.core.plugin.config.ConfigManager; import net.momirealms.craftengine.core.util.CharacterUtils; import org.bukkit.Bukkit; +import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.HandlerList; @@ -45,27 +48,35 @@ public class BukkitImageManager extends AbstractImageManager implements Listener @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) @SuppressWarnings("UnstableApiUsage") public void onChat(AsyncChatDecorateEvent event) { - if (event.player() == null) return; - if (!this.isDefaultFontInUse()) return; - this.processChatMessages(event); + if (!ConfigManager.filterChat()) return; + this.processChatEvent(event); } @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) @SuppressWarnings("UnstableApiUsage") public void onChatCommand(AsyncChatCommandDecorateEvent event) { - if (event.player() == null) return; - if (!this.isDefaultFontInUse()) return; - this.processChatMessages(event); + if (!ConfigManager.filterChat()) return; + this.processChatEvent(event); } @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) public void onCommand(PlayerCommandPreprocessEvent event) { + if (!ConfigManager.filterCommand()) return; if (!this.isDefaultFontInUse()) return; + if (event.getPlayer().hasPermission(ImageManager.BYPASS_COMMAND)) { + return; + } runIfContainsIllegalCharacter(event.getMessage(), event::setMessage); } @SuppressWarnings("UnstableApiUsage") - private void processChatMessages(AsyncChatDecorateEvent event) { + private void processChatEvent(AsyncChatDecorateEvent event) { + Player player = event.player(); + if (player == null) return; + if (!this.isDefaultFontInUse()) return; + if (player.hasPermission(ImageManager.BYPASS_CHAT)) { + return; + } try { Object originalMessage = Reflections.field$AsyncChatDecorateEvent$originalMessage.get(event); String jsonMessage = (String) Reflections.method$ComponentSerializer$serialize.invoke(serializer, originalMessage); 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 51dc3732e..8e315fc3a 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 @@ -730,10 +730,15 @@ public class PacketConsumers { // we handle it on packet level to prevent it from being captured by plugins public static final TriConsumer RENAME_ITEM = (user, event, packet) -> { try { + if (!ConfigManager.filterAnvil()) return; String message = (String) Reflections.field$ServerboundRenameItemPacket$name.get(packet); if (message != null && !message.isEmpty()) { ImageManager manager = CraftEngine.instance().imageManager(); if (!manager.isDefaultFontInUse()) return; + // check bypass + if (((BukkitServerPlayer) user).hasPermission(ImageManager.BYPASS_ANVIL)) { + return; + } runIfContainsIllegalCharacter(message, manager, (s) -> { try { Reflections.field$ServerboundRenameItemPacket$name.set(packet, s); @@ -750,9 +755,14 @@ public class PacketConsumers { // we handle it on packet level to prevent it from being captured by plugins public static final TriConsumer SIGN_UPDATE = (user, event, packet) -> { try { + if (!ConfigManager.filterSign()) return; String[] lines = (String[]) Reflections.field$ServerboundSignUpdatePacket$lines.get(packet); ImageManager manager = CraftEngine.instance().imageManager(); if (!manager.isDefaultFontInUse()) return; + // check bypass + if (((BukkitServerPlayer) user).hasPermission(ImageManager.BYPASS_SIGN)) { + return; + } for (int i = 0; i < lines.length; i++) { String line = lines[i]; if (line != null && !line.isEmpty()) { @@ -772,8 +782,13 @@ public class PacketConsumers { @SuppressWarnings("unchecked") public static final TriConsumer EDIT_BOOK = (user, event, packet) -> { try { + if (!ConfigManager.filterBook()) return; ImageManager manager = CraftEngine.instance().imageManager(); if (!manager.isDefaultFontInUse()) return; + // check bypass + if (((BukkitServerPlayer) user).hasPermission(ImageManager.BYPASS_BOOK)) { + return; + } boolean changed = false; 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 7c38e8643..eb2b5ab6d 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 @@ -14,6 +14,11 @@ import java.util.function.BiFunction; public interface ImageManager extends Reloadable, ConfigSectionParser { String CONFIG_SECTION_NAME = "images"; Key DEFAULT_FONT = Key.of("minecraft:default"); + String BYPASS_BOOK = "craftengine.filter.bypass.book"; + String BYPASS_SIGN = "craftengine.filter.bypass.sign"; + String BYPASS_CHAT = "craftengine.filter.bypass.chat"; + String BYPASS_COMMAND = "craftengine.filter.bypass.command"; + String BYPASS_ANVIL = "craftengine.filter.bypass.anvil"; default String sectionId() { return CONFIG_SECTION_NAME; diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/config/ConfigManager.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/config/ConfigManager.java index 64d50a78a..746769d83 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/config/ConfigManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/config/ConfigManager.java @@ -105,6 +105,12 @@ public class ConfigManager implements Reloadable { protected boolean item$non_italic_tag; + protected boolean image$illegal_characters_filter$command; + protected boolean image$illegal_characters_filter$chat; + protected boolean image$illegal_characters_filter$anvil; + protected boolean image$illegal_characters_filter$sign; + protected boolean image$illegal_characters_filter$book; + public ConfigManager(CraftEngine plugin) { this.plugin = plugin; this.configVersion = PluginProperties.getValue("config"); @@ -249,6 +255,13 @@ public class ConfigManager implements Reloadable { // recipe recipe$enable = config.getBoolean("recipe.enable", true); + // image + image$illegal_characters_filter$anvil = config.getBoolean("image.illegal-characters-filter.anvil", true); + image$illegal_characters_filter$book = config.getBoolean("image.illegal-characters-filter.book", true); + image$illegal_characters_filter$chat = config.getBoolean("image.illegal-characters-filter.chat", true); + image$illegal_characters_filter$command = config.getBoolean("image.illegal-characters-filter.command", true); + image$illegal_characters_filter$sign = config.getBoolean("image.illegal-characters-filter.sign", true); + Class modClazz = ReflectionUtils.getClazz(CraftEngine.MOD_CLASS); if (modClazz != null) { Method setMaxChainMethod = ReflectionUtils.getStaticMethod(modClazz, void.class, new String[] {"setMaxChainUpdate"}, int.class); @@ -500,6 +513,26 @@ public class ConfigManager implements Reloadable { return instance.resource_pack$generate_mod_assets; } + public static boolean filterChat() { + return instance().image$illegal_characters_filter$chat; + } + + public static boolean filterAnvil() { + return instance().image$illegal_characters_filter$anvil; + } + + public static boolean filterCommand() { + return instance().image$illegal_characters_filter$command; + } + + public static boolean filterBook() { + return instance().image$illegal_characters_filter$book; + } + + public static boolean filterSign() { + return instance().image$illegal_characters_filter$sign; + } + public YamlDocument loadOrCreateYamlData(String fileName) { File file = new File(this.plugin.dataFolderFile(), fileName); if (!file.exists()) {