From 4d947fe6b828932b7e53476c9f36f86d4d2f1969 Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Thu, 10 Apr 2025 15:07:48 +0800 Subject: [PATCH 1/4] =?UTF-8?q?feat(emoji):=20=E5=A2=9E=E5=8A=A0=20emoji?= =?UTF-8?q?=20=E8=A7=A3=E6=9E=90=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bukkit/loader/src/main/resources/config.yml | 2 + .../bukkit/font/BukkitFontManager.java | 122 ++++++++++++++---- .../bukkit/util/ComponentUtils.java | 22 ++-- .../craftengine/bukkit/util/Reflections.java | 37 ++++++ .../core/plugin/config/Config.java | 6 + gradle.properties | 2 +- 6 files changed, 156 insertions(+), 35 deletions(-) diff --git a/bukkit/loader/src/main/resources/config.yml b/bukkit/loader/src/main/resources/config.yml index 242aba376..5efdfb664 100644 --- a/bukkit/loader/src/main/resources/config.yml +++ b/bukkit/loader/src/main/resources/config.yml @@ -237,6 +237,8 @@ gui: performance: # Maximum chain update depth when fixing client visuals max-block-chain-update-limit: 64 + # Maximum emoji parsed each time + max-emoji-parsed-limit: 100 light-system: enable: true diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/font/BukkitFontManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/font/BukkitFontManager.java index 26d33fc0b..8ba4f59fd 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/font/BukkitFontManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/font/BukkitFontManager.java @@ -1,5 +1,7 @@ package net.momirealms.craftengine.bukkit.font; +import com.google.gson.JsonElement; +import com.google.gson.JsonPrimitive; import io.papermc.paper.event.player.AsyncChatCommandDecorateEvent; import io.papermc.paper.event.player.AsyncChatDecorateEvent; import net.kyori.adventure.text.Component; @@ -25,14 +27,17 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; +import org.bukkit.event.block.SignChangeEvent; import org.bukkit.event.inventory.PrepareAnvilEvent; import org.bukkit.event.player.PlayerCommandPreprocessEvent; +import org.bukkit.event.player.PlayerEditBookEvent; import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.BookMeta; import org.bukkit.inventory.view.AnvilView; import java.lang.reflect.InvocationTargetException; -import java.util.Map; -import java.util.Objects; +import java.util.*; +import java.util.function.Consumer; public class BukkitFontManager extends AbstractFontManager implements Listener { private final BukkitCraftEngine plugin; @@ -105,31 +110,104 @@ public class BukkitFontManager extends AbstractFontManager implements Listener { if (renameText == null || renameText.isEmpty()) return; Component itemName = Component.text(renameText); - boolean replaced = false; - for (Token token : super.emojiKeywordTrie.tokenize(renameText)) { + final int[] parsedCount = {0}; + processComponent(itemName, player, parsedCount[0], (text) -> { + if (parsedCount[0]++ >= Config.maxEmojiParsed()) return; + Item wrapped = this.plugin.itemManager().wrap(result); + wrapped.customName(AdventureHelper.componentToJson(text)); + event.setResult(wrapped.loadCopy()); + }, (count) -> parsedCount[0]++); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onPlayerEditBook(PlayerEditBookEvent event) { + if (!event.isSigning()) return; + Player player = event.getPlayer(); + BookMeta newBookMeta = event.getNewBookMeta(); + List pages = newBookMeta.pages(); + final boolean[] replacedBookMeta = {false}; + final int[] parsedCount = {0}; + for (int i = 0; i < pages.size(); i++) { + int finalIndex = i; + JsonElement json = ComponentUtils.paperAdventureToJsonElement(pages.get(i)); + if (json instanceof JsonPrimitive primitive) { + if (primitive.isString() && primitive.getAsString().isEmpty()) continue; + } + Component page = AdventureHelper.jsonElementToComponent(json); + processComponent(page, player, parsedCount[0], (text) -> { + try { + replacedBookMeta[0] = true; + Reflections.method$BookMeta$page.invoke( + newBookMeta, finalIndex + 1, + ComponentUtils.jsonElementToPaperAdventure(AdventureHelper.componentToJsonElement(text)) + ); + } catch (IllegalAccessException | InvocationTargetException e) { + this.plugin.logger().warn("Failed to set book page", e); + } + }, (count) -> parsedCount[0]++); + if (parsedCount[0] > Config.maxEmojiParsed()) break; + } + if (replacedBookMeta[0]) { + event.setNewBookMeta(newBookMeta); + } + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onSignChange(SignChangeEvent event) { + Player player = event.getPlayer(); + List lines = event.lines(); + final int[] parsedCount = {0}; + for (int i = 0; i < lines.size(); i++) { + int finalIndex = i; + JsonElement json = ComponentUtils.paperAdventureToJsonElement(lines.get(i)); + if (json.toString().isEmpty()) continue; + Component line = AdventureHelper.jsonElementToComponent(json); + processComponent(line, player, parsedCount[0], (text) -> { + try { + Reflections.method$SignChangeEvent$line.invoke( + event, finalIndex, + ComponentUtils.jsonElementToPaperAdventure(AdventureHelper.componentToJsonElement(text)) + ); + } catch (IllegalAccessException | InvocationTargetException e) { + plugin.logger().warn("Failed to set sign line", e); + } + }, (count) -> parsedCount[0]++); + if (parsedCount[0] > Config.maxEmojiParsed()) break; + } + } + + private void processComponent(Component text, Player player, int parsedCount, Consumer consumer, Consumer parsedCountConsumer) { + if (parsedCount > Config.maxEmojiParsed()) return; + Component textReplaced = text; + Set processedKeywords = new HashSet<>(); + for (Token token : super.emojiKeywordTrie.tokenize(AdventureHelper.componentToJson(text))) { if (!token.isMatch()) continue; - Emoji emoji = super.emojiMapper.get(token.getFragment()); - if (emoji == null) continue; - if (emoji.permission() != null && !player.hasPermission(Objects.requireNonNull(emoji.permission()))) { + String keyword = token.getFragment(); + parsedCountConsumer.accept(parsedCount++); + if (parsedCount > Config.maxEmojiParsed()) return; + if (processedKeywords.contains(keyword)) continue; + Emoji emoji = super.emojiMapper.get(keyword); + if (emoji == null) { + parsedCountConsumer.accept(parsedCount--); continue; } - itemName = itemName.replaceText(builder -> { - builder.matchLiteral(token.getFragment()) - .replacement(AdventureHelper.miniMessage().deserialize( - emoji.content(), - PlayerContext.of(plugin.adapt(player), ContextHolder.builder() - .withOptionalParameter(EmojiParameters.EMOJI, emoji.emojiImage()) - .withParameter(EmojiParameters.KEYWORD, emoji.keywords().get(0)) - .build()).tagResolvers() - )) ; + if (emoji.permission() != null && !player.hasPermission(Objects.requireNonNull(emoji.permission()))) { + parsedCountConsumer.accept(parsedCount--); + continue; + } + textReplaced = textReplaced.replaceText(builder -> { + builder.matchLiteral(keyword) + .replacement(AdventureHelper.miniMessage().deserialize( + emoji.content(), + PlayerContext.of(plugin.adapt(player), ContextHolder.builder() + .withOptionalParameter(EmojiParameters.EMOJI, emoji.emojiImage()) + .withParameter(EmojiParameters.KEYWORD, emoji.keywords().get(0)) + .build()).tagResolvers() + )); }); - replaced = true; + consumer.accept(textReplaced); + processedKeywords.add(keyword); } - - if (!replaced) return; - Item wrapped = this.plugin.itemManager().wrap(result); - wrapped.customName(AdventureHelper.componentToJson(itemName)); - event.setResult(wrapped.loadCopy()); } @SuppressWarnings("UnstableApiUsage") diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/ComponentUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/ComponentUtils.java index 426e456ff..b9622ed40 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/ComponentUtils.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/ComponentUtils.java @@ -3,7 +3,6 @@ package net.momirealms.craftengine.bukkit.util; import com.google.gson.JsonElement; import net.kyori.adventure.text.Component; import net.momirealms.craftengine.bukkit.nms.FastNMS; -import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.util.AdventureHelper; public class ComponentUtils { @@ -27,19 +26,18 @@ public class ComponentUtils { } public static String paperAdventureToJson(Object component) { - try { - return (String) Reflections.method$ComponentSerializer$serialize.invoke(Reflections.instance$GsonComponentSerializer, component); - } catch (ReflectiveOperationException e) { - CraftEngine.instance().logger().warn("Failed to serialize paper adventure component " + component, e); - return AdventureHelper.EMPTY_COMPONENT; - } + return Reflections.instance$GsonComponentSerializer$Gson.toJson(component); } public static Object jsonToPaperAdventure(String json) { - try { - return Reflections.method$ComponentSerializer$deserialize.invoke(Reflections.instance$GsonComponentSerializer, json); - } catch (ReflectiveOperationException e) { - throw new RuntimeException("Failed to deserialize paper component from json", e); - } + return Reflections.instance$GsonComponentSerializer$Gson.fromJson(json, Reflections.clazz$AdventureComponent); + } + + public static JsonElement paperAdventureToJsonElement(Object component) { + return Reflections.instance$GsonComponentSerializer$Gson.toJsonTree(component); + } + + public static Object jsonElementToPaperAdventure(JsonElement json) { + return Reflections.instance$GsonComponentSerializer$Gson.fromJson(json, Reflections.clazz$AdventureComponent); } } 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 869b18b27..a98610732 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,6 +1,7 @@ package net.momirealms.craftengine.bukkit.util; import com.google.common.collect.ImmutableList; +import com.google.gson.Gson; import com.google.gson.JsonElement; import io.netty.buffer.ByteBuf; import io.netty.channel.Channel; @@ -6314,4 +6315,40 @@ public class Reflections { BukkitReflectionUtils.assembleMCClass("network.protocol.game.PacketPlayOutScoreboardObjective") ) ); + + public static final Class clazz$SignChangeEvent = requireNonNull( + ReflectionUtils.getClazz( + "org.bukkit.event.block.SignChangeEvent" + ) + ); + + public static final Method method$SignChangeEvent$line = requireNonNull( + ReflectionUtils.getMethod(clazz$SignChangeEvent, void.class, int.class, clazz$AdventureComponent) + ); + + public static final Class clazz$BookMeta = requireNonNull( + ReflectionUtils.getClazz( + "org.bukkit.inventory.meta.BookMeta" + ) + ); + + public static final Method method$BookMeta$page = requireNonNull( + ReflectionUtils.getMethod(clazz$BookMeta, void.class, int.class, clazz$AdventureComponent) + ); + + public static final Method method$GsonComponentSerializer$serializer = requireNonNull( + ReflectionUtils.getMethod( + clazz$GsonComponentSerializer, Gson.class + ) + ); + + public static final Gson instance$GsonComponentSerializer$Gson; + + static { + try { + instance$GsonComponentSerializer$Gson = (Gson) Reflections.method$GsonComponentSerializer$serializer.invoke(instance$GsonComponentSerializer); + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/config/Config.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/config/Config.java index fd197c315..f94baf16f 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/config/Config.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/config/Config.java @@ -96,6 +96,7 @@ public class Config { protected UUID resource_pack$external_host$uuid; protected int performance$max_block_chain_update_limit; + protected int performance$max_emoji_parsed_limit; protected boolean light_system$force_update_light; protected boolean light_system$enable; @@ -259,6 +260,7 @@ public class Config { // performance performance$max_block_chain_update_limit = config.getInt("performance.max-block-chain-update-limit", 64); + performance$max_emoji_parsed_limit = config.getInt("performance.max-emoji-parsed-limit", 100); // light light_system$force_update_light = config.getBoolean("light-system.force-update-light", false); @@ -352,6 +354,10 @@ public class Config { return instance.performance$max_block_chain_update_limit; } + public static int maxEmojiParsed() { + return instance.performance$max_emoji_parsed_limit; + } + public static boolean removeInvalidFurniture() { return instance.furniture$remove_invalid_furniture_on_chunk_load$enable; } diff --git a/gradle.properties b/gradle.properties index 57c38701c..b90dd8cd5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,7 +3,7 @@ org.gradle.jvmargs=-Xmx1G # Project settings # Rule: [major update].[feature update].[bug fix] project_version=0.0.46.3 -config_version=23 +config_version=24 lang_version=4 project_group=net.momirealms latest_supported_version=1.21.5 From a904b63c402870a0104d23b366987d3b5a3cafbc Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Thu, 10 Apr 2025 19:13:00 +0800 Subject: [PATCH 2/4] =?UTF-8?q?feat(core):=20=E6=B7=BB=E5=8A=A0=E8=A1=A8?= =?UTF-8?q?=E6=83=85=E7=AC=A6=E5=8F=B7=E8=A1=A5=E5=85=A8=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bukkit/font/BukkitFontManager.java | 19 +++++++++++++++++++ .../core/font/AbstractFontManager.java | 19 +++++++++++++++++++ .../craftengine/core/font/FontManager.java | 5 +++++ gradle.properties | 4 ++-- 4 files changed, 45 insertions(+), 2 deletions(-) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/font/BukkitFontManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/font/BukkitFontManager.java index 8ba4f59fd..0151e87e6 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/font/BukkitFontManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/font/BukkitFontManager.java @@ -5,6 +5,7 @@ import com.google.gson.JsonPrimitive; import io.papermc.paper.event.player.AsyncChatCommandDecorateEvent; import io.papermc.paper.event.player.AsyncChatDecorateEvent; import net.kyori.adventure.text.Component; +import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; import net.momirealms.craftengine.bukkit.util.ComponentUtils; import net.momirealms.craftengine.bukkit.util.LegacyInventoryUtils; @@ -31,6 +32,7 @@ import org.bukkit.event.block.SignChangeEvent; import org.bukkit.event.inventory.PrepareAnvilEvent; import org.bukkit.event.player.PlayerCommandPreprocessEvent; import org.bukkit.event.player.PlayerEditBookEvent; +import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.BookMeta; import org.bukkit.inventory.view.AnvilView; @@ -58,6 +60,23 @@ public class BukkitFontManager extends AbstractFontManager implements Listener { HandlerList.unregisterAll(this); } + @Override + public void delayedLoad() { + Map oldCachedEmojiSuggestions = this.oldCachedEmojiSuggestions(); + super.delayedLoad(); + this.oldCachedEmojiSuggestions.putAll(this.cachedEmojiSuggestions()); + Bukkit.getOnlinePlayers().forEach(player -> { + FastNMS.INSTANCE.method$ChatSuggestions$remove(oldCachedEmojiSuggestions.keySet(), player); + FastNMS.INSTANCE.method$ChatSuggestions$add(this.cachedEmojiSuggestions(), player); + }); + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onPlayerJoin(PlayerJoinEvent event) { + Player player = event.getPlayer(); + FastNMS.INSTANCE.method$ChatSuggestions$add(this.cachedEmojiSuggestions(), player); + } + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) @SuppressWarnings("UnstableApiUsage") public void onChat(AsyncChatDecorateEvent event) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/font/AbstractFontManager.java b/core/src/main/java/net/momirealms/craftengine/core/font/AbstractFontManager.java index 767058d65..3bdc5c77d 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/font/AbstractFontManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/font/AbstractFontManager.java @@ -1,5 +1,6 @@ package net.momirealms.craftengine.core.font; +import com.google.common.collect.ImmutableMap; import net.kyori.adventure.text.Component; import net.momirealms.craftengine.core.entity.player.Player; import net.momirealms.craftengine.core.pack.LoadingSequence; @@ -35,6 +36,9 @@ public abstract class AbstractFontManager implements FontManager { protected Trie emojiKeywordTrie; private Map tagMapper; protected Map emojiMapper; + // tab补全 + protected final Map cachedEmojiSuggestions = new HashMap<>(); + protected final Map oldCachedEmojiSuggestions = new HashMap<>(); public AbstractFontManager(CraftEngine plugin) { this.plugin = plugin; @@ -55,6 +59,17 @@ public abstract class AbstractFontManager implements FontManager { this.images.clear(); this.illegalChars.clear(); this.emojis.clear(); + this.cachedEmojiSuggestions.clear(); + } + + @Override + public Map cachedEmojiSuggestions() { + return ImmutableMap.copyOf(this.cachedEmojiSuggestions); + } + + @Override + public Map oldCachedEmojiSuggestions() { + return ImmutableMap.copyOf(this.oldCachedEmojiSuggestions); } @Override @@ -146,6 +161,7 @@ public abstract class AbstractFontManager implements FontManager { @Override public void delayedLoad() { + this.oldCachedEmojiSuggestions.clear(); Optional.ofNullable(this.fonts.get(DEFAULT_FONT)).ifPresent(font -> this.illegalChars.addAll(font.codepointsInUse())); this.buildImageTagTrie(); this.buildEmojiKeywordsTrie(); @@ -263,6 +279,9 @@ public abstract class AbstractFontManager implements FontManager { return; } List keywords = MiscUtils.getAsStringList(keywordsRaw); + UUID uuid = UUID.randomUUID(); + String keyword = keywords.get(0); + cachedEmojiSuggestions.put(uuid, keyword); String content = section.getOrDefault("content", "").toString(); String image = null; if (section.containsKey("image")) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/font/FontManager.java b/core/src/main/java/net/momirealms/craftengine/core/font/FontManager.java index 7fd53b4d1..ca001f040 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/font/FontManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/font/FontManager.java @@ -11,6 +11,7 @@ import net.momirealms.craftengine.core.util.Key; import java.util.Collection; import java.util.Map; import java.util.Optional; +import java.util.UUID; public interface FontManager extends Manageable { Key DEFAULT_FONT = Key.of("minecraft:default"); @@ -73,4 +74,8 @@ public interface FontManager extends Manageable { } Map matchTags(String json); + + Map cachedEmojiSuggestions(); + + Map oldCachedEmojiSuggestions(); } diff --git a/gradle.properties b/gradle.properties index b90dd8cd5..c2f32fe2c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -41,7 +41,7 @@ geantyref_version=1.3.16 zstd_version=1.5.7-2 commons_io_version=2.18.0 sparrow_nbt_version=0.6.2 -sparrow_util_version=0.37 +sparrow_util_version=0.38 fastutil_version=8.5.15 netty_version=4.1.119.Final joml_version=1.10.8 @@ -51,7 +51,7 @@ byte_buddy_version=1.17.5 ahocorasick_version=0.6.3 snake_yaml_version=2.4 anti_grief_version=0.13 -nms_helper_version=0.53 +nms_helper_version=0.54 # Ignite Dependencies mixinextras_version=0.4.1 mixin_version=0.15.2+mixin.0.8.7 From 7963288c1d710c27e90ec126e9e081ddf7c183b1 Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Thu, 10 Apr 2025 22:00:53 +0800 Subject: [PATCH 3/4] =?UTF-8?q?refactor(bukkit):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E5=AD=97=E4=BD=93=E7=AE=A1=E7=90=86=E5=99=A8=E4=B8=AD=E8=A1=A8?= =?UTF-8?q?=E6=83=85=E8=A7=A3=E6=9E=90=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bukkit/font/BukkitFontManager.java | 55 ++++++++++--------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/font/BukkitFontManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/font/BukkitFontManager.java index 0151e87e6..b433afe87 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/font/BukkitFontManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/font/BukkitFontManager.java @@ -129,13 +129,13 @@ public class BukkitFontManager extends AbstractFontManager implements Listener { if (renameText == null || renameText.isEmpty()) return; Component itemName = Component.text(renameText); - final int[] parsedCount = {0}; - processComponent(itemName, player, parsedCount[0], (text) -> { - if (parsedCount[0]++ >= Config.maxEmojiParsed()) return; + MutableInt parsedCount = new MutableInt(0); + processComponent(itemName, player, parsedCount, (text) -> { + if (parsedCount.value >= Config.maxEmojiParsed()) return; Item wrapped = this.plugin.itemManager().wrap(result); wrapped.customName(AdventureHelper.componentToJson(text)); event.setResult(wrapped.loadCopy()); - }, (count) -> parsedCount[0]++); + }); } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) @@ -144,8 +144,8 @@ public class BukkitFontManager extends AbstractFontManager implements Listener { Player player = event.getPlayer(); BookMeta newBookMeta = event.getNewBookMeta(); List pages = newBookMeta.pages(); - final boolean[] replacedBookMeta = {false}; - final int[] parsedCount = {0}; + MutableBoolean replacedBookMeta = new MutableBoolean(false); + MutableInt parsedCount = new MutableInt(0); for (int i = 0; i < pages.size(); i++) { int finalIndex = i; JsonElement json = ComponentUtils.paperAdventureToJsonElement(pages.get(i)); @@ -153,9 +153,9 @@ public class BukkitFontManager extends AbstractFontManager implements Listener { if (primitive.isString() && primitive.getAsString().isEmpty()) continue; } Component page = AdventureHelper.jsonElementToComponent(json); - processComponent(page, player, parsedCount[0], (text) -> { + processComponent(page, player, parsedCount, (text) -> { try { - replacedBookMeta[0] = true; + replacedBookMeta.value = true; Reflections.method$BookMeta$page.invoke( newBookMeta, finalIndex + 1, ComponentUtils.jsonElementToPaperAdventure(AdventureHelper.componentToJsonElement(text)) @@ -163,10 +163,10 @@ public class BukkitFontManager extends AbstractFontManager implements Listener { } catch (IllegalAccessException | InvocationTargetException e) { this.plugin.logger().warn("Failed to set book page", e); } - }, (count) -> parsedCount[0]++); - if (parsedCount[0] > Config.maxEmojiParsed()) break; + }); + if (parsedCount.value > Config.maxEmojiParsed()) break; } - if (replacedBookMeta[0]) { + if (replacedBookMeta.value) { event.setNewBookMeta(newBookMeta); } } @@ -175,13 +175,13 @@ public class BukkitFontManager extends AbstractFontManager implements Listener { public void onSignChange(SignChangeEvent event) { Player player = event.getPlayer(); List lines = event.lines(); - final int[] parsedCount = {0}; + MutableInt parsedCount = new MutableInt(0); for (int i = 0; i < lines.size(); i++) { int finalIndex = i; JsonElement json = ComponentUtils.paperAdventureToJsonElement(lines.get(i)); if (json.toString().isEmpty()) continue; Component line = AdventureHelper.jsonElementToComponent(json); - processComponent(line, player, parsedCount[0], (text) -> { + processComponent(line, player, parsedCount, (text) -> { try { Reflections.method$SignChangeEvent$line.invoke( event, finalIndex, @@ -190,28 +190,22 @@ public class BukkitFontManager extends AbstractFontManager implements Listener { } catch (IllegalAccessException | InvocationTargetException e) { plugin.logger().warn("Failed to set sign line", e); } - }, (count) -> parsedCount[0]++); - if (parsedCount[0] > Config.maxEmojiParsed()) break; + }); + if (parsedCount.value > Config.maxEmojiParsed()) break; } } - private void processComponent(Component text, Player player, int parsedCount, Consumer consumer, Consumer parsedCountConsumer) { - if (parsedCount > Config.maxEmojiParsed()) return; + private void processComponent(Component text, Player player, MutableInt parsedCount, Consumer consumer) { + if (parsedCount.value > Config.maxEmojiParsed()) return; Component textReplaced = text; Set processedKeywords = new HashSet<>(); for (Token token : super.emojiKeywordTrie.tokenize(AdventureHelper.componentToJson(text))) { - if (!token.isMatch()) continue; + if (!token.isMatch() || parsedCount.value > Config.maxEmojiParsed()) continue; String keyword = token.getFragment(); - parsedCountConsumer.accept(parsedCount++); - if (parsedCount > Config.maxEmojiParsed()) return; if (processedKeywords.contains(keyword)) continue; Emoji emoji = super.emojiMapper.get(keyword); - if (emoji == null) { - parsedCountConsumer.accept(parsedCount--); - continue; - } + if (emoji == null) continue; if (emoji.permission() != null && !player.hasPermission(Objects.requireNonNull(emoji.permission()))) { - parsedCountConsumer.accept(parsedCount--); continue; } textReplaced = textReplaced.replaceText(builder -> { @@ -226,9 +220,20 @@ public class BukkitFontManager extends AbstractFontManager implements Listener { }); consumer.accept(textReplaced); processedKeywords.add(keyword); + parsedCount.value++; } } + private static final class MutableInt { + int value; + MutableInt(int value) { this.value = value; } + } + + private static final class MutableBoolean { + boolean value; + MutableBoolean(boolean value) { this.value = value; } + } + @SuppressWarnings("UnstableApiUsage") private void processChatEvent(AsyncChatDecorateEvent event) { Player player = event.player(); From 5d2698a8343267da8415f5ee08609cdc0c4cc13b Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Thu, 10 Apr 2025 22:03:31 +0800 Subject: [PATCH 4/4] =?UTF-8?q?refactor(bukkit):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E5=AD=97=E4=BD=93=E7=AE=A1=E7=90=86=E5=99=A8=E4=B8=AD=E8=A1=A8?= =?UTF-8?q?=E6=83=85=E8=A7=A3=E6=9E=90=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../momirealms/craftengine/bukkit/font/BukkitFontManager.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/font/BukkitFontManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/font/BukkitFontManager.java index b433afe87..6b3a6a440 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/font/BukkitFontManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/font/BukkitFontManager.java @@ -200,7 +200,8 @@ public class BukkitFontManager extends AbstractFontManager implements Listener { Component textReplaced = text; Set processedKeywords = new HashSet<>(); for (Token token : super.emojiKeywordTrie.tokenize(AdventureHelper.componentToJson(text))) { - if (!token.isMatch() || parsedCount.value > Config.maxEmojiParsed()) continue; + if (!token.isMatch()) continue; + if (parsedCount.value++ > Config.maxEmojiParsed()) return; String keyword = token.getFragment(); if (processedKeywords.contains(keyword)) continue; Emoji emoji = super.emojiMapper.get(keyword); @@ -220,7 +221,6 @@ public class BukkitFontManager extends AbstractFontManager implements Listener { }); consumer.accept(textReplaced); processedKeywords.add(keyword); - parsedCount.value++; } }