From f160ea6dc46a2788dcfc27be15ef2afa5706256b Mon Sep 17 00:00:00 2001 From: APairOfMoons Date: Tue, 30 Jun 2026 23:06:42 +0800 Subject: [PATCH 1/8] Rebuild Logic & RGB Color Supported The text format is now composed by the mod itself, rather than the game. --- build.gradle | 4 +- gradle.properties | 6 +- gradle/wrapper/gradle-wrapper.properties | 2 +- properties/26.2.properties | 24 ++ .../revaria/chatplus/format/ChatFormat.java | 7 + .../chatplus/format/ChatFormatType.java | 8 + .../format/formats/ChatColorFormat.java | 78 +++++ .../format/formats/ChatFontFormat.java | 51 +++ .../format/formats/ChatInsertItemFormat.java | 36 +++ .../format/formats/ChatResetFormat.java | 27 ++ ...apMixin.java => DynmapMixin.java.disabled} | 0 .../chatplus/util/TextStyleFormatter.java | 305 +++++++++++++++--- src/main/resources/chat-plus.mixins.json | 1 - 13 files changed, 500 insertions(+), 49 deletions(-) create mode 100644 properties/26.2.properties create mode 100644 src/main/java/cn/revaria/chatplus/format/ChatFormat.java create mode 100644 src/main/java/cn/revaria/chatplus/format/ChatFormatType.java create mode 100644 src/main/java/cn/revaria/chatplus/format/formats/ChatColorFormat.java create mode 100644 src/main/java/cn/revaria/chatplus/format/formats/ChatFontFormat.java create mode 100644 src/main/java/cn/revaria/chatplus/format/formats/ChatInsertItemFormat.java create mode 100644 src/main/java/cn/revaria/chatplus/format/formats/ChatResetFormat.java rename src/main/java/cn/revaria/chatplus/mixin/compat/{DynmapMixin.java => DynmapMixin.java.disabled} (100%) diff --git a/build.gradle b/build.gradle index 5808c1f..979a894 100644 --- a/build.gradle +++ b/build.gradle @@ -2,8 +2,8 @@ import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform import java.nio.file.Paths plugins { - id "net.fabricmc.fabric-loom-remap" version "1.16-SNAPSHOT" apply false - id "net.fabricmc.fabric-loom" version "1.16-SNAPSHOT" apply false + id "net.fabricmc.fabric-loom-remap" version "1.17-SNAPSHOT" apply false + id "net.fabricmc.fabric-loom" version "1.17-SNAPSHOT" apply false id "maven-publish" // Manifold preprocessor diff --git a/gradle.properties b/gradle.properties index 1021c87..0cba7db 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,15 +6,15 @@ org.gradle.parallel=true version_properties_path=./properties # Mod Properties -mod_version=1.1.0 +mod_version=1.2.0 maven_group=cn.revaria.chatplus archives_base_name=chat-plus # Minecraft -minecraft_version=26.1 +minecraft_version=26.2 # Override Fabric API version for local testing (runClient/runServer) #test_fabric_api_version= # Dependencies -manifold_version=2025.1.9 +manifold_version=2025.1.25 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index c61a118..7e7d24f 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.0-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/properties/26.2.properties b/properties/26.2.properties new file mode 100644 index 0000000..cbfb2c3 --- /dev/null +++ b/properties/26.2.properties @@ -0,0 +1,24 @@ +java_version=25 + +# Fabric Loom +# - For Minecraft versions <26.1: enable remap +# - For Minecraft versions >=26.1: disable remap +fabric_loom_remap=false + +# Fabric Properties +# check these on https://fabricmc.net/develop +fabric_loader_version=0.19.3 +min_fabric_loader_version= +fabric_api_version=0.152.2 +# Fabric API mod ID conventions: +# - For Minecraft versions <1.19.2: use "fabric" +# - For Minecraft versions >=1.19.2: use "fabric-api" +# Ref: https://wiki.fabricmc.net/tutorial:setup +fabric_api_mod_id=fabric-api + +# Mod Compatibility +! Dynmap 3.8 +mod_dynmap_version=4UHHD4t6 +! Styled Chat 2.13.0+26.2 +mod_styled_chat_version=2.13.0+26.2 +mod_styled_chat_placeholder_api_version=3.1.0-beta.1+26.2 diff --git a/src/main/java/cn/revaria/chatplus/format/ChatFormat.java b/src/main/java/cn/revaria/chatplus/format/ChatFormat.java new file mode 100644 index 0000000..6fdc7d2 --- /dev/null +++ b/src/main/java/cn/revaria/chatplus/format/ChatFormat.java @@ -0,0 +1,7 @@ +package cn.revaria.chatplus.format; + +public interface ChatFormat { + int startingIndex(); + ChatFormatType formatType(); + ChatFormat copy(); +} diff --git a/src/main/java/cn/revaria/chatplus/format/ChatFormatType.java b/src/main/java/cn/revaria/chatplus/format/ChatFormatType.java new file mode 100644 index 0000000..be2b14b --- /dev/null +++ b/src/main/java/cn/revaria/chatplus/format/ChatFormatType.java @@ -0,0 +1,8 @@ +package cn.revaria.chatplus.format; + +public enum ChatFormatType { + COLOR, + FONT, + INSERT, + RESET +} diff --git a/src/main/java/cn/revaria/chatplus/format/formats/ChatColorFormat.java b/src/main/java/cn/revaria/chatplus/format/formats/ChatColorFormat.java new file mode 100644 index 0000000..35f0a83 --- /dev/null +++ b/src/main/java/cn/revaria/chatplus/format/formats/ChatColorFormat.java @@ -0,0 +1,78 @@ +package cn.revaria.chatplus.format.formats; + +import cn.revaria.chatplus.format.ChatFormat; +import cn.revaria.chatplus.format.ChatFormatType; + +import java.util.Map; + +public class ChatColorFormat implements ChatFormat { + + private final int R, G, B; + + private final int startingIndex; + private final ChatFormatType formatType = ChatFormatType.COLOR; + + public ChatColorFormat(int startingIndex, int R, int G, int B) { + this.startingIndex = startingIndex; + + this.R = R; + this.G = G; + this.B = B; + } + public ChatColorFormat(int startingIndex, char colorCode) { + this.startingIndex = startingIndex; + + if (VANILLA_COLOR_FORMATS.containsKey(colorCode)) { + this.R = VANILLA_COLOR_FORMATS.get(colorCode).getR(); + this.G = VANILLA_COLOR_FORMATS.get(colorCode).getG(); + this.B = VANILLA_COLOR_FORMATS.get(colorCode).getB(); + } + else { + this.R = 0; + this.G = 0; + this.B = 0; + } + } + + public int getR() { + return R; + } + public int getG() { + return G; + } + public int getB() { + return B; + } + + @Override + public int startingIndex() { + return this.startingIndex; + } + @Override + public ChatFormatType formatType() { + return this.formatType; + } + @Override + public ChatColorFormat copy() { + return new ChatColorFormat(this.startingIndex, this.R, this.G, this.B); + } + + public static final Map VANILLA_COLOR_FORMATS = Map.ofEntries( + Map.entry('0', new ChatColorFormat(0, 0, 0, 0)), + Map.entry('1', new ChatColorFormat(0, 0, 0, 170)), + Map.entry('2', new ChatColorFormat(0, 0, 170, 0)), + Map.entry('3', new ChatColorFormat(0, 0, 170, 170)), + Map.entry('4', new ChatColorFormat(0, 170, 0, 0)), + Map.entry('5', new ChatColorFormat(0, 170, 0, 170)), + Map.entry('6', new ChatColorFormat(0, 255, 170, 0)), + Map.entry('7', new ChatColorFormat(0, 170, 170, 170)), + Map.entry('8', new ChatColorFormat(0, 85, 85, 85)), + Map.entry('9', new ChatColorFormat(0, 85, 85, 255)), + Map.entry('a', new ChatColorFormat(0, 85, 255, 85)), + Map.entry('b', new ChatColorFormat(0, 85, 255, 255)), + Map.entry('c', new ChatColorFormat(0, 255, 85, 85)), + Map.entry('d', new ChatColorFormat(0, 255, 85, 255)), + Map.entry('e', new ChatColorFormat(0, 255, 255, 85)), + Map.entry('f', new ChatColorFormat(0, 255, 255, 255)) + ); +} diff --git a/src/main/java/cn/revaria/chatplus/format/formats/ChatFontFormat.java b/src/main/java/cn/revaria/chatplus/format/formats/ChatFontFormat.java new file mode 100644 index 0000000..05ae252 --- /dev/null +++ b/src/main/java/cn/revaria/chatplus/format/formats/ChatFontFormat.java @@ -0,0 +1,51 @@ +package cn.revaria.chatplus.format.formats; + +import cn.revaria.chatplus.format.ChatFormat; +import cn.revaria.chatplus.format.ChatFormatType; +import net.minecraft.ChatFormatting; + +import java.util.Map; + +public class ChatFontFormat implements ChatFormat { + + private final ChatFormatting fontFormat; + + private final int startingIndex; + private final ChatFormatType formatType = ChatFormatType.FONT; + + public ChatFontFormat(int startingIndex, ChatFormatting fontFormat) { + this.startingIndex = startingIndex; + + this.fontFormat = fontFormat; + } + public ChatFontFormat(int startingIndex, char fontCode) { + this.startingIndex = startingIndex; + + this.fontFormat = VANILLA_FONT_FORMATS.getOrDefault(fontCode, ChatFormatting.ITALIC); + } + + public ChatFormatting getFont() { + return fontFormat; + } + + @Override + public int startingIndex() { + return startingIndex; + } + @Override + public ChatFormatType formatType() { + return formatType; + } + @Override + public ChatFontFormat copy() { + return new ChatFontFormat(this.startingIndex, this.fontFormat); + } + + public static final Map VANILLA_FONT_FORMATS = Map.ofEntries( + Map.entry('k', ChatFormatting.OBFUSCATED), + Map.entry('l', ChatFormatting.BOLD), + Map.entry('m', ChatFormatting.STRIKETHROUGH), + Map.entry('n', ChatFormatting.UNDERLINE), + Map.entry('o', ChatFormatting.ITALIC) + ); +} diff --git a/src/main/java/cn/revaria/chatplus/format/formats/ChatInsertItemFormat.java b/src/main/java/cn/revaria/chatplus/format/formats/ChatInsertItemFormat.java new file mode 100644 index 0000000..86c2323 --- /dev/null +++ b/src/main/java/cn/revaria/chatplus/format/formats/ChatInsertItemFormat.java @@ -0,0 +1,36 @@ +package cn.revaria.chatplus.format.formats; + +import cn.revaria.chatplus.format.ChatFormat; +import cn.revaria.chatplus.format.ChatFormatType; +import net.minecraft.world.item.ItemStack; + +public class ChatInsertItemFormat implements ChatFormat { + + private final ItemStack item; + + private final int startingIndex; + private final ChatFormatType formatType = ChatFormatType.INSERT; + + public ChatInsertItemFormat(int startingIndex, ItemStack item) { + this.startingIndex = startingIndex; + + this.item = item; + } + + public ItemStack getItem() { + return item; + } + + @Override + public int startingIndex() { + return startingIndex; + } + @Override + public ChatFormatType formatType() { + return formatType; + } + @Override + public ChatInsertItemFormat copy() { + return new ChatInsertItemFormat(this.startingIndex, this.item); + } +} diff --git a/src/main/java/cn/revaria/chatplus/format/formats/ChatResetFormat.java b/src/main/java/cn/revaria/chatplus/format/formats/ChatResetFormat.java new file mode 100644 index 0000000..8d40574 --- /dev/null +++ b/src/main/java/cn/revaria/chatplus/format/formats/ChatResetFormat.java @@ -0,0 +1,27 @@ +package cn.revaria.chatplus.format.formats; + +import cn.revaria.chatplus.format.ChatFormat; +import cn.revaria.chatplus.format.ChatFormatType; + +public class ChatResetFormat implements ChatFormat { + + private final int startingIndex; + private final ChatFormatType formatType = ChatFormatType.RESET; + + public ChatResetFormat(int startingIndex) { + this.startingIndex = startingIndex; + } + + @Override + public int startingIndex() { + return startingIndex; + } + @Override + public ChatFormatType formatType() { + return formatType; + } + @Override + public ChatResetFormat copy() { + return new ChatResetFormat(this.startingIndex); + } +} diff --git a/src/main/java/cn/revaria/chatplus/mixin/compat/DynmapMixin.java b/src/main/java/cn/revaria/chatplus/mixin/compat/DynmapMixin.java.disabled similarity index 100% rename from src/main/java/cn/revaria/chatplus/mixin/compat/DynmapMixin.java rename to src/main/java/cn/revaria/chatplus/mixin/compat/DynmapMixin.java.disabled diff --git a/src/main/java/cn/revaria/chatplus/util/TextStyleFormatter.java b/src/main/java/cn/revaria/chatplus/util/TextStyleFormatter.java index 465b47d..f791d50 100644 --- a/src/main/java/cn/revaria/chatplus/util/TextStyleFormatter.java +++ b/src/main/java/cn/revaria/chatplus/util/TextStyleFormatter.java @@ -3,30 +3,26 @@ #if MC_VER <= MC_1_20 import net.minecraft.network.chat.contents.LiteralContents; #else -import net.minecraft.network.chat.contents.PlainTextContents; +import cn.revaria.chatplus.format.ChatFormat; +import cn.revaria.chatplus.format.ChatFormatType; +import cn.revaria.chatplus.format.formats.ChatColorFormat; +import cn.revaria.chatplus.format.formats.ChatFontFormat; +import cn.revaria.chatplus.format.formats.ChatInsertItemFormat; +import cn.revaria.chatplus.format.formats.ChatResetFormat; #endif import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.item.ItemStack; -import java.util.ArrayDeque; -import java.util.Deque; -import java.util.List; +import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; public class TextStyleFormatter { - public static int MAIN_HAND = -1; // Must be smaller than or equal to 0 /** - * Processes text styling with two key functions: - *

- * 1. Replaces {@code &} with {@code §}, using {@code &&} to escape literal {@code &}
- * 2. Substitutes {@code [item]} with main-hand item hover text and {@code [item=N]} with Nth slot's hover text - *

- * Recursively processes nested text components. + * * * @param sourceText Original text to process (supports nested text components) * @param sourcePlayer Player used for item stack references @@ -35,46 +31,271 @@ public class TextStyleFormatter { public static MutableComponent applyStyle(Component sourceText, ServerPlayer sourcePlayer) { MutableComponent sourceMutableText = sourceText.copy(); + String sourceRawText = sourceMutableText.toString().substring(8, sourceMutableText.toString().length() - 1); + + // These will be motified in translateInput() + TreeMap> formatsTable = new TreeMap<>(); + + String sourceLiteralText = translateInput(sourceRawText, sourcePlayer, formatsTable); + + /* Debug + sourcePlayer.sendSystemMessage(Component.literal(sourceLiteralText)); + for (int i : formatsTable.keySet()) { + ArrayList formatsList = formatsTable.get(i); + sourcePlayer.sendSystemMessage(Component.literal(i + ".")); + for (ChatFormat format : formatsList) { + if (format instanceof ChatInsertItemFormat) { + sourcePlayer.sendSystemMessage(Component.literal(" 物品插入数据")); + } + if (format instanceof ChatResetFormat) { + sourcePlayer.sendSystemMessage(Component.literal(" 清除")); + } + if (format instanceof ChatColorFormat colorFormat) { + sourcePlayer.sendSystemMessage(Component.literal(" 颜色:" + colorFormat.getR() + " " + colorFormat.getG() + " " + colorFormat.getB())); + } + if (format instanceof ChatFontFormat fontFormat) { + sourcePlayer.sendSystemMessage(Component.literal(" 字体").withStyle(fontFormat.getFont())); + } + } + }*/ + MutableComponent finalText = Component.empty().setStyle(sourceMutableText.getStyle()); + ChatColorFormat currentColor = new ChatColorFormat(0, 'f'); + HashSet currentFonts = new HashSet<>(); + int startIndex = 0; + + for (int i : formatsTable.keySet()) { + + ArrayList formatsList = formatsTable.get(i); + + if (formatsList.getFirst() instanceof ChatInsertItemFormat insertItem) { - if (sourceText.getContents() instanceof #if MC_VER <= MC_1_20 LiteralContents #else PlainTextContents #endif plainTextContent) { - String changedMessage = plainTextContent.text() - .replace('&', '§') - .replace("§§", "&"); - String regex = "\\[item(?:=([1-9]))?\\]"; - String[] messages = changedMessage.split(regex, -1); - Deque itemDeque = new ArrayDeque<>(); - - Matcher matcher = Pattern.compile(regex).matcher(changedMessage); - while (matcher.find()) { - String digit = matcher.group(1); - if (digit == null) { - itemDeque.addLast(MAIN_HAND); - } else { - itemDeque.addLast(Integer.parseInt(digit)); + if (i > 0) { + finalText.append(composeChatComponent( + sourceLiteralText.substring(startIndex, i), + currentColor, + currentFonts + )); } + + finalText.append(insertItem.getItem().getDisplayName()); + + startIndex = i; + continue; } + if (formatsList.getFirst() instanceof ChatResetFormat) { - for (String message : messages) { - finalText.append(Component.literal(message)); - if (!itemDeque.isEmpty()) { - ItemStack itemStack; - if (itemDeque.getFirst() == MAIN_HAND) { - itemStack = sourcePlayer.getMainHandItem(); - } else { - itemStack = sourcePlayer.getInventory().getItem(itemDeque.getFirst() - 1); - } - finalText.append(itemStack.getDisplayName()); - itemDeque.removeFirst(); + if (i > 0) { + finalText.append(composeChatComponent( + sourceLiteralText.substring(startIndex, i), + currentColor, + currentFonts + )); } + + currentColor = new ChatColorFormat(0, 'f'); + currentFonts.clear(); + + startIndex = i; + continue; } - } - List sourceTexts = sourceMutableText.getSiblings(); - for (Component text : sourceTexts) { - finalText.append(applyStyle(text, sourcePlayer)); + if (i > 0) { + finalText.append(composeChatComponent( + sourceLiteralText.substring(startIndex, i), + currentColor, + currentFonts + )); + } + + for (ChatFormat format : formatsList) { + + if (format instanceof ChatColorFormat colorFormat) { + currentColor = colorFormat; + } + else if (format instanceof ChatFontFormat fontFormat) { + currentFonts.add(fontFormat); + } + } + + startIndex = i; + } + if (startIndex < sourceLiteralText.length() - 1) { + finalText.append(composeChatComponent( + sourceLiteralText.substring(startIndex, sourceLiteralText.length()), + currentColor, + currentFonts + )); } return finalText; } + + private static MutableComponent composeChatComponent(String chatText, ChatColorFormat currentColor, HashSet currentFonts) { + + if (currentColor == null) { + currentColor = new ChatColorFormat(0, 'f'); + } + + MutableComponent finalChatComponent = Component.literal(chatText); + + finalChatComponent.withColor(currentColor.getR() << 16 | currentColor.getG() << 8 | currentColor.getB()); + for (ChatFontFormat fontFormat : currentFonts) { + finalChatComponent.withStyle(fontFormat.getFont()); + } + + return finalChatComponent; + } + + private static String translateInput(String sourceRawText, ServerPlayer sourcePlayer, TreeMap> formatsTableOutput) { + + StringBuilder textBuilder = new StringBuilder(); + + String itemRegex = "\\[item(?:=([1-9]))?\\]"; + Pattern itemPattern = Pattern.compile(itemRegex); + Matcher matcher = itemPattern.matcher(sourceRawText); + + for (int i = 0; i < sourceRawText.length(); ++i) { + + char character = sourceRawText.charAt(i); + int currentIndex = textBuilder.length(); + + if (character == '&' && i < sourceRawText.length() - 1) { + + char colorCode = sourceRawText.charAt(i + 1); + if (ChatColorFormat.VANILLA_COLOR_FORMATS.containsKey(colorCode)) { + + if (!formatsTableOutput.containsKey(currentIndex)) { + formatsTableOutput.put(currentIndex, new ArrayList<>()); + } + formatsTableOutput.get(currentIndex).add(new ChatColorFormat(currentIndex, colorCode)); + + ++i; + continue; + } + } + + if (character == '#' && i < sourceRawText.length() - 6) { + + boolean legalColorCode = true; + for (int j = i + 1; j <= i + 6 && j < sourceRawText.length(); ++j) { + char c = sourceRawText.charAt(j); + + if (!((c >= '0' && c <= '9') || + (c >= 'a' && c <= 'f') || + (c >= 'A' && c <= 'F'))) { + legalColorCode = false; + break; + } + } + + if (legalColorCode) { + + if (!formatsTableOutput.containsKey(currentIndex)) { + formatsTableOutput.put(currentIndex, new ArrayList<>()); + } + + int color = Integer.parseInt(sourceRawText.substring(i + 1, i + 7), 16); + formatsTableOutput.get(currentIndex).add(new ChatColorFormat( + currentIndex, + (color >> 16) & 0xFF, + (color >> 8) & 0xFF, + color & 0xFF) + ); + + i += 6; + continue; + } + } + + if (character == '&' && i < sourceRawText.length() - 1) { + + char fontCode = sourceRawText.charAt(i + 1); + if (ChatFontFormat.VANILLA_FONT_FORMATS.containsKey(fontCode)) { + + if (!formatsTableOutput.containsKey(currentIndex)) { + formatsTableOutput.put(currentIndex, new ArrayList<>()); + } + formatsTableOutput.get(currentIndex).add(new ChatFontFormat(currentIndex, fontCode)); + + ++i; + continue; + } + } + + if (character == '[' && i < sourceRawText.length() - 5) { + + matcher.region(i, Math.min(i + 8, sourceRawText.length())); + if (matcher.lookingAt()) { + + if (!formatsTableOutput.containsKey(currentIndex)) { + formatsTableOutput.put(currentIndex, new ArrayList<>()); + } + + String digit = matcher.group(1); + if (digit == null) { + formatsTableOutput.get(currentIndex).add(new ChatInsertItemFormat( + currentIndex, + sourcePlayer.getMainHandItem() + )); + } + else { + formatsTableOutput.get(currentIndex).add(new ChatInsertItemFormat( + currentIndex, + sourcePlayer.getInventory().getItem(Integer.parseInt(digit) - 1) + )); + } + + while (sourceRawText.charAt(i) != ']' && i < sourceRawText.length()) { + ++i; + } + continue; + } + } + + if (character == '&' && i < sourceRawText.length() - 1) { + + if (sourceRawText.charAt(i + 1) == 'r') { + + if (!formatsTableOutput.containsKey(currentIndex)) { + formatsTableOutput.put(currentIndex, new ArrayList<>()); + } + formatsTableOutput.get(currentIndex).add(new ChatResetFormat(currentIndex)); + + ++i; + continue; + } + } + + textBuilder.append(character); + } + + formatsTableOutput.forEach((i, formatsList) -> { + + boolean containsResetFormat = false; + ChatInsertItemFormat containedInsertItemFormat = null; + for (ChatFormat format : formatsList) { + + if (format.formatType() == ChatFormatType.RESET) { + containsResetFormat = true; + break; + } + if (format instanceof ChatInsertItemFormat insertItemFormat && format.formatType() == ChatFormatType.INSERT) { + containedInsertItemFormat = insertItemFormat.copy(); + break; + } + } + + if (containsResetFormat) { + formatsList.clear(); + formatsList.add(new ChatResetFormat(i)); + } + if (containedInsertItemFormat != null) { + formatsList.clear(); + formatsList.add(containedInsertItemFormat); + } + }); + + return textBuilder.toString(); + } } diff --git a/src/main/resources/chat-plus.mixins.json b/src/main/resources/chat-plus.mixins.json index bbb0e0e..9b06cbd 100644 --- a/src/main/resources/chat-plus.mixins.json +++ b/src/main/resources/chat-plus.mixins.json @@ -4,7 +4,6 @@ "plugin": "cn.revaria.chatplus.plugin.MixinConfigPlugin", "mixins": [ "ChatMixin", - "compat.DynmapMixin", "compat.StyledChatMixin" ], "injectors": { From 02e3914d0459a9cd97c48af4b1a38e610de554e5 Mon Sep 17 00:00:00 2001 From: APairOfMoons Date: Thu, 2 Jul 2026 11:50:01 +0800 Subject: [PATCH 2/8] Fix: Single character chat text issue fixed. --- src/main/java/cn/revaria/chatplus/util/TextStyleFormatter.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/cn/revaria/chatplus/util/TextStyleFormatter.java b/src/main/java/cn/revaria/chatplus/util/TextStyleFormatter.java index f791d50..5cce8e0 100644 --- a/src/main/java/cn/revaria/chatplus/util/TextStyleFormatter.java +++ b/src/main/java/cn/revaria/chatplus/util/TextStyleFormatter.java @@ -39,6 +39,7 @@ public static MutableComponent applyStyle(Component sourceText, ServerPlayer sou String sourceLiteralText = translateInput(sourceRawText, sourcePlayer, formatsTable); /* Debug + sourcePlayer.sendSystemMessage(Component.literal(sourceRawText)); sourcePlayer.sendSystemMessage(Component.literal(sourceLiteralText)); for (int i : formatsTable.keySet()) { ArrayList formatsList = formatsTable.get(i); @@ -120,7 +121,7 @@ else if (format instanceof ChatFontFormat fontFormat) { startIndex = i; } - if (startIndex < sourceLiteralText.length() - 1) { + if (startIndex < sourceLiteralText.length()) { finalText.append(composeChatComponent( sourceLiteralText.substring(startIndex, sourceLiteralText.length()), currentColor, From 35b829c3db6b3bb43e132c8ff9a7ad52c7ced9b9 Mon Sep 17 00:00:00 2001 From: APairOfMoons <84629346+APairOfMoons@users.noreply.github.com> Date: Mon, 6 Jul 2026 01:06:30 +0800 Subject: [PATCH 3/8] Feat & Rebuild: Add @PlayerName Reminder in chat. --- .../java/cn/revaria/chatplus/ChatPlus.java | 10 +++ .../format/formats/ChatInsertFormat.java | 9 +++ .../ChatInsertItemFormat.java | 11 +++- .../ChatInsertReminderFormat.java | 53 +++++++++++++++ .../chatplus/util/TextStyleFormatter.java | 66 +++++++++++++++---- 5 files changed, 135 insertions(+), 14 deletions(-) create mode 100644 src/main/java/cn/revaria/chatplus/format/formats/ChatInsertFormat.java rename src/main/java/cn/revaria/chatplus/format/formats/{ => insertformats}/ChatInsertItemFormat.java (66%) create mode 100644 src/main/java/cn/revaria/chatplus/format/formats/insertformats/ChatInsertReminderFormat.java diff --git a/src/main/java/cn/revaria/chatplus/ChatPlus.java b/src/main/java/cn/revaria/chatplus/ChatPlus.java index e18f3f2..bad1b5e 100644 --- a/src/main/java/cn/revaria/chatplus/ChatPlus.java +++ b/src/main/java/cn/revaria/chatplus/ChatPlus.java @@ -1,6 +1,8 @@ package cn.revaria.chatplus; import net.fabricmc.api.ModInitializer; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; +import net.minecraft.server.MinecraftServer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -12,12 +14,20 @@ public class ChatPlus implements ModInitializer { // That way, it's clear which mod wrote info, warnings, and errors. public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID); + private static MinecraftServer server; + + public static MinecraftServer getServer() { + return server; + } + @Override public void onInitialize() { // This code runs as soon as Minecraft is in a mod-load-ready state. // However, some things (like resources) may still be uninitialized. // Proceed with mild caution. + ServerLifecycleEvents.SERVER_STARTING.register(server -> ChatPlus.server = server); + LOGGER.info("Chat Plus loaded"); } } diff --git a/src/main/java/cn/revaria/chatplus/format/formats/ChatInsertFormat.java b/src/main/java/cn/revaria/chatplus/format/formats/ChatInsertFormat.java new file mode 100644 index 0000000..877dd39 --- /dev/null +++ b/src/main/java/cn/revaria/chatplus/format/formats/ChatInsertFormat.java @@ -0,0 +1,9 @@ +package cn.revaria.chatplus.format.formats; + +import cn.revaria.chatplus.format.ChatFormat; +import net.minecraft.network.chat.MutableComponent; + +public interface ChatInsertFormat extends ChatFormat { + MutableComponent getInsertComponent(); + ChatInsertFormat copy(); +} diff --git a/src/main/java/cn/revaria/chatplus/format/formats/ChatInsertItemFormat.java b/src/main/java/cn/revaria/chatplus/format/formats/insertformats/ChatInsertItemFormat.java similarity index 66% rename from src/main/java/cn/revaria/chatplus/format/formats/ChatInsertItemFormat.java rename to src/main/java/cn/revaria/chatplus/format/formats/insertformats/ChatInsertItemFormat.java index 86c2323..26720eb 100644 --- a/src/main/java/cn/revaria/chatplus/format/formats/ChatInsertItemFormat.java +++ b/src/main/java/cn/revaria/chatplus/format/formats/insertformats/ChatInsertItemFormat.java @@ -1,10 +1,11 @@ -package cn.revaria.chatplus.format.formats; +package cn.revaria.chatplus.format.formats.insertformats; -import cn.revaria.chatplus.format.ChatFormat; import cn.revaria.chatplus.format.ChatFormatType; +import cn.revaria.chatplus.format.formats.ChatInsertFormat; +import net.minecraft.network.chat.MutableComponent; import net.minecraft.world.item.ItemStack; -public class ChatInsertItemFormat implements ChatFormat { +public class ChatInsertItemFormat implements ChatInsertFormat { private final ItemStack item; @@ -21,6 +22,10 @@ public ItemStack getItem() { return item; } + @Override + public MutableComponent getInsertComponent() { + return item.getDisplayName().copy(); + } @Override public int startingIndex() { return startingIndex; diff --git a/src/main/java/cn/revaria/chatplus/format/formats/insertformats/ChatInsertReminderFormat.java b/src/main/java/cn/revaria/chatplus/format/formats/insertformats/ChatInsertReminderFormat.java new file mode 100644 index 0000000..a7aaa31 --- /dev/null +++ b/src/main/java/cn/revaria/chatplus/format/formats/insertformats/ChatInsertReminderFormat.java @@ -0,0 +1,53 @@ +package cn.revaria.chatplus.format.formats.insertformats; + +import cn.revaria.chatplus.format.ChatFormatType; +import cn.revaria.chatplus.format.formats.ChatInsertFormat; +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.network.chat.TextColor; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; + +public class ChatInsertReminderFormat implements ChatInsertFormat { + + private final ServerPlayer aimPlayer; + private boolean soundPlayed = false; + + private final int startingIndex; + private final ChatFormatType formatType = ChatFormatType.INSERT; + + public ChatInsertReminderFormat(int startingIndex, ServerPlayer aim) { + this.startingIndex = startingIndex; + + this.aimPlayer = aim; + } + + public ServerPlayer getAimPlayer() { + return aimPlayer; + } + + @Override + public MutableComponent getInsertComponent() { + if (!soundPlayed) { + soundPlayed = true; + aimPlayer.playSound(SoundEvents.EXPERIENCE_ORB_PICKUP, 3, 1); + } + return Component.literal("@").append(aimPlayer.getDisplayName()) + .withColor(TextColor.GREEN) + .withStyle(ChatFormatting.BOLD); + } + @Override + public int startingIndex() { + return startingIndex; + } + @Override + public ChatFormatType formatType() { + return formatType; + } + @Override + public ChatInsertFormat copy() { + return new ChatInsertReminderFormat(startingIndex, aimPlayer); + } +} diff --git a/src/main/java/cn/revaria/chatplus/util/TextStyleFormatter.java b/src/main/java/cn/revaria/chatplus/util/TextStyleFormatter.java index 5cce8e0..1c75dd7 100644 --- a/src/main/java/cn/revaria/chatplus/util/TextStyleFormatter.java +++ b/src/main/java/cn/revaria/chatplus/util/TextStyleFormatter.java @@ -2,17 +2,20 @@ #if MC_VER <= MC_1_20 import net.minecraft.network.chat.contents.LiteralContents; -#else +#endif + +import cn.revaria.chatplus.ChatPlus; +import cn.revaria.chatplus.format.formats.ChatInsertFormat; +import cn.revaria.chatplus.format.formats.insertformats.ChatInsertReminderFormat; import cn.revaria.chatplus.format.ChatFormat; import cn.revaria.chatplus.format.ChatFormatType; import cn.revaria.chatplus.format.formats.ChatColorFormat; import cn.revaria.chatplus.format.formats.ChatFontFormat; -import cn.revaria.chatplus.format.formats.ChatInsertItemFormat; +import cn.revaria.chatplus.format.formats.insertformats.ChatInsertItemFormat; import cn.revaria.chatplus.format.formats.ChatResetFormat; -#endif - import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; +import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; import java.util.*; @@ -69,7 +72,7 @@ public static MutableComponent applyStyle(Component sourceText, ServerPlayer sou ArrayList formatsList = formatsTable.get(i); - if (formatsList.getFirst() instanceof ChatInsertItemFormat insertItem) { + if (formatsList.getFirst() instanceof ChatInsertFormat insertFormat) { if (i > 0) { finalText.append(composeChatComponent( @@ -79,7 +82,7 @@ public static MutableComponent applyStyle(Component sourceText, ServerPlayer sou )); } - finalText.append(insertItem.getItem().getDisplayName()); + finalText.append(insertFormat.getInsertComponent()); startIndex = i; continue; @@ -152,6 +155,9 @@ private static String translateInput(String sourceRawText, ServerPlayer sourcePl StringBuilder textBuilder = new StringBuilder(); + MinecraftServer server = ChatPlus.getServer(); + String[] playerNames = server.getPlayerList().getPlayerNamesArray(); + String itemRegex = "\\[item(?:=([1-9]))?\\]"; Pattern itemPattern = Pattern.compile(itemRegex); Matcher matcher = itemPattern.matcher(sourceRawText); @@ -268,21 +274,42 @@ private static String translateInput(String sourceRawText, ServerPlayer sourcePl } } + if ((character >= '0' && character <= '9') + || (character >= 'a' && character <= 'z') + || (character >= 'A' && character <= 'Z') + || character == '_') { + + String insertName = matchPlayerName(sourceRawText, playerNames, i); + if (insertName != null) { + + if (!formatsTableOutput.containsKey(currentIndex)) { + formatsTableOutput.put(currentIndex, new ArrayList<>()); + } + formatsTableOutput.get(currentIndex).add(new ChatInsertReminderFormat( + currentIndex, + server.getPlayerList().getPlayer(insertName) + )); + + i += insertName.length() - 1; + continue; + } + } + textBuilder.append(character); } formatsTableOutput.forEach((i, formatsList) -> { boolean containsResetFormat = false; - ChatInsertItemFormat containedInsertItemFormat = null; + ChatInsertFormat containedInsertFormat = null; for (ChatFormat format : formatsList) { if (format.formatType() == ChatFormatType.RESET) { containsResetFormat = true; break; } - if (format instanceof ChatInsertItemFormat insertItemFormat && format.formatType() == ChatFormatType.INSERT) { - containedInsertItemFormat = insertItemFormat.copy(); + if (format instanceof ChatInsertFormat insertFormat && format.formatType() == ChatFormatType.INSERT) { + containedInsertFormat = insertFormat.copy(); break; } } @@ -291,12 +318,29 @@ private static String translateInput(String sourceRawText, ServerPlayer sourcePl formatsList.clear(); formatsList.add(new ChatResetFormat(i)); } - if (containedInsertItemFormat != null) { + if (containedInsertFormat != null) { formatsList.clear(); - formatsList.add(containedInsertItemFormat); + formatsList.add(containedInsertFormat); } }); return textBuilder.toString(); } + + private static String matchPlayerName(String chatText, String[] playerNames, int startingIndex) { + + String aimName = null; + + for (String name : playerNames) { + + if (chatText.startsWith(name, startingIndex)) { + + if (aimName == null || aimName.length() < name.length()) { + aimName = name; + } + } + } + + return aimName; + } } From 9fb66dc69a7cbc4a7d21e6bb3217c839c401301b Mon Sep 17 00:00:00 2001 From: APairOfMoons <84629346+APairOfMoons@users.noreply.github.com> Date: Mon, 6 Jul 2026 11:56:03 +0800 Subject: [PATCH 4/8] Feat: Add sound reminder for @Player. --- .../insertformats/ChatInsertReminderFormat.java | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/main/java/cn/revaria/chatplus/format/formats/insertformats/ChatInsertReminderFormat.java b/src/main/java/cn/revaria/chatplus/format/formats/insertformats/ChatInsertReminderFormat.java index a7aaa31..96542be 100644 --- a/src/main/java/cn/revaria/chatplus/format/formats/insertformats/ChatInsertReminderFormat.java +++ b/src/main/java/cn/revaria/chatplus/format/formats/insertformats/ChatInsertReminderFormat.java @@ -3,11 +3,14 @@ import cn.revaria.chatplus.format.ChatFormatType; import cn.revaria.chatplus.format.formats.ChatInsertFormat; import net.minecraft.ChatFormatting; +import net.minecraft.core.Holder; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.network.chat.TextColor; +import net.minecraft.network.protocol.game.ClientboundSoundPacket; +import net.minecraft.resources.Identifier; import net.minecraft.server.level.ServerPlayer; -import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundSource; public class ChatInsertReminderFormat implements ChatInsertFormat { @@ -32,7 +35,17 @@ public ServerPlayer getAimPlayer() { public MutableComponent getInsertComponent() { if (!soundPlayed) { soundPlayed = true; - aimPlayer.playSound(SoundEvents.EXPERIENCE_ORB_PICKUP, 3, 1); + + aimPlayer.connection.send(new ClientboundSoundPacket( + Holder.direct(SoundEvent.createVariableRangeEvent(Identifier.fromNamespaceAndPath("minecraft", "entity.experience_orb.pickup"))), + SoundSource.MASTER, + aimPlayer.position().x, + aimPlayer.position().y, + aimPlayer.position().z, + 3, + 1, + aimPlayer.level().getRandom().nextLong() + )); } return Component.literal("@").append(aimPlayer.getDisplayName()) .withColor(TextColor.GREEN) From 5961e16cf91b892947104b7dc3b98fd86907faf4 Mon Sep 17 00:00:00 2001 From: APairOfMoons <84629346+APairOfMoons@users.noreply.github.com> Date: Mon, 6 Jul 2026 15:00:49 +0800 Subject: [PATCH 5/8] Feat: Add @All reminder. --- .../ChatInsertRemindAllFormat.java | 66 +++++++++++++++++++ .../chatplus/util/TextStyleFormatter.java | 33 ++++++++++ 2 files changed, 99 insertions(+) create mode 100644 src/main/java/cn/revaria/chatplus/format/formats/insertformats/ChatInsertRemindAllFormat.java diff --git a/src/main/java/cn/revaria/chatplus/format/formats/insertformats/ChatInsertRemindAllFormat.java b/src/main/java/cn/revaria/chatplus/format/formats/insertformats/ChatInsertRemindAllFormat.java new file mode 100644 index 0000000..097d926 --- /dev/null +++ b/src/main/java/cn/revaria/chatplus/format/formats/insertformats/ChatInsertRemindAllFormat.java @@ -0,0 +1,66 @@ +package cn.revaria.chatplus.format.formats.insertformats; + +import cn.revaria.chatplus.ChatPlus; +import cn.revaria.chatplus.format.ChatFormatType; +import cn.revaria.chatplus.format.formats.ChatInsertFormat; +import net.minecraft.ChatFormatting; +import net.minecraft.core.Holder; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.network.chat.TextColor; +import net.minecraft.network.protocol.game.ClientboundSoundPacket; +import net.minecraft.resources.Identifier; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.sounds.SoundSource; + +public class ChatInsertRemindAllFormat implements ChatInsertFormat { + + private final String reminderText; + private boolean soundPlayed = false; + + private final int startingIndex; + private final ChatFormatType formatType = ChatFormatType.INSERT; + + public ChatInsertRemindAllFormat(int startingIndex, String reminderText) { + this.startingIndex = startingIndex; + + this.reminderText = reminderText; + } + + @Override + public MutableComponent getInsertComponent() { + if (!soundPlayed) { + soundPlayed = true; + + for (ServerPlayer player : ChatPlus.getServer().getPlayerList().getPlayers()) { + player.connection.send(new ClientboundSoundPacket( + Holder.direct(SoundEvent.createVariableRangeEvent(Identifier.fromNamespaceAndPath("minecraft", "entity.experience_orb.pickup"))), + SoundSource.MASTER, + player.position().x, + player.position().y, + player.position().z, + 3, + 1, + player.level().getRandom().nextLong() + )); + } + } + + return Component.literal("@").append(reminderText) + .withColor(TextColor.GREEN) + .withStyle(ChatFormatting.BOLD); + } + @Override + public int startingIndex() { + return startingIndex; + } + @Override + public ChatFormatType formatType() { + return formatType; + } + @Override + public ChatInsertFormat copy() { + return new ChatInsertRemindAllFormat(startingIndex, reminderText); + } +} diff --git a/src/main/java/cn/revaria/chatplus/util/TextStyleFormatter.java b/src/main/java/cn/revaria/chatplus/util/TextStyleFormatter.java index 1c75dd7..f9378b6 100644 --- a/src/main/java/cn/revaria/chatplus/util/TextStyleFormatter.java +++ b/src/main/java/cn/revaria/chatplus/util/TextStyleFormatter.java @@ -7,6 +7,7 @@ import cn.revaria.chatplus.ChatPlus; import cn.revaria.chatplus.format.formats.ChatInsertFormat; import cn.revaria.chatplus.format.formats.insertformats.ChatInsertReminderFormat; +import cn.revaria.chatplus.format.formats.insertformats.ChatInsertRemindAllFormat; import cn.revaria.chatplus.format.ChatFormat; import cn.revaria.chatplus.format.ChatFormatType; import cn.revaria.chatplus.format.formats.ChatColorFormat; @@ -274,6 +275,38 @@ private static String translateInput(String sourceRawText, ServerPlayer sourcePl } } + if (character == '@') { + + if (sourceRawText.startsWith("All", i + 1) + || sourceRawText.startsWith("ALL", i + 1) + || sourceRawText.startsWith("all", i + 1)) { + + if (!formatsTableOutput.containsKey(currentIndex)) { + formatsTableOutput.put(currentIndex, new ArrayList<>()); + } + formatsTableOutput.get(currentIndex).add(new ChatInsertRemindAllFormat( + currentIndex, + "All" + )); + + i += 3; + continue; + } + if (sourceRawText.startsWith("所有人", i + 1)) { + + if (!formatsTableOutput.containsKey(currentIndex)) { + formatsTableOutput.put(currentIndex, new ArrayList<>()); + } + formatsTableOutput.get(currentIndex).add(new ChatInsertRemindAllFormat( + currentIndex, + "所有人" + )); + + i += 3; + continue; + } + } + if ((character >= '0' && character <= '9') || (character >= 'a' && character <= 'z') || (character >= 'A' && character <= 'Z') From a38637058f50ed4d4c1567dfc87781b30fa70674 Mon Sep 17 00:00:00 2001 From: APairOfMoons <84629346+APairOfMoons@users.noreply.github.com> Date: Tue, 21 Jul 2026 11:25:12 +0800 Subject: [PATCH 6/8] Update debug output. --- src/main/java/cn/revaria/chatplus/util/TextStyleFormatter.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/cn/revaria/chatplus/util/TextStyleFormatter.java b/src/main/java/cn/revaria/chatplus/util/TextStyleFormatter.java index f9378b6..39780c3 100644 --- a/src/main/java/cn/revaria/chatplus/util/TextStyleFormatter.java +++ b/src/main/java/cn/revaria/chatplus/util/TextStyleFormatter.java @@ -43,8 +43,11 @@ public static MutableComponent applyStyle(Component sourceText, ServerPlayer sou String sourceLiteralText = translateInput(sourceRawText, sourcePlayer, formatsTable); /* Debug + sourcePlayer.sendSystemMessage(Component.literal("原始聊天文本:")); sourcePlayer.sendSystemMessage(Component.literal(sourceRawText)); + sourcePlayer.sendSystemMessage(Component.literal("提取到的聊天内容:")); sourcePlayer.sendSystemMessage(Component.literal(sourceLiteralText)); + sourcePlayer.sendSystemMessage(Component.literal("修饰列表:")); for (int i : formatsTable.keySet()) { ArrayList formatsList = formatsTable.get(i); sourcePlayer.sendSystemMessage(Component.literal(i + ".")); From 80b0dc5f21156ea6846d77de7c0200fe6a177e4a Mon Sep 17 00:00:00 2001 From: APairOfMoons <84629346+APairOfMoons@users.noreply.github.com> Date: Tue, 21 Jul 2026 11:36:05 +0800 Subject: [PATCH 7/8] Update gradle to 9.6.1 --- gradle/wrapper/gradle-wrapper.properties | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index eb84db6..87c980e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,9 +1,6 @@ +#Tue Jul 21 11:35:40 CST 2026 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.0-bin.zip -networkTimeout=10000 -retries=0 -retryBackOffMs=500 -validateDistributionUrl=true +distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 02ab858b4fa371c8e0c261b65ad425b382945019 Mon Sep 17 00:00:00 2001 From: APairOfMoons <84629346+APairOfMoons@users.noreply.github.com> Date: Tue, 21 Jul 2026 15:05:57 +0800 Subject: [PATCH 8/8] Disabled the markdown formats inheritance. --- .../java/cn/revaria/chatplus/util/TextStyleFormatter.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/cn/revaria/chatplus/util/TextStyleFormatter.java b/src/main/java/cn/revaria/chatplus/util/TextStyleFormatter.java index 39780c3..c39a4b0 100644 --- a/src/main/java/cn/revaria/chatplus/util/TextStyleFormatter.java +++ b/src/main/java/cn/revaria/chatplus/util/TextStyleFormatter.java @@ -43,6 +43,8 @@ public static MutableComponent applyStyle(Component sourceText, ServerPlayer sou String sourceLiteralText = translateInput(sourceRawText, sourcePlayer, formatsTable); /* Debug + sourcePlayer.sendSystemMessage(Component.literal("原始聊天代码:")); + sourcePlayer.sendSystemMessage(Component.literal(sourceMutableText.toString())); sourcePlayer.sendSystemMessage(Component.literal("原始聊天文本:")); sourcePlayer.sendSystemMessage(Component.literal(sourceRawText)); sourcePlayer.sendSystemMessage(Component.literal("提取到的聊天内容:")); @@ -67,7 +69,7 @@ public static MutableComponent applyStyle(Component sourceText, ServerPlayer sou } }*/ - MutableComponent finalText = Component.empty().setStyle(sourceMutableText.getStyle()); + MutableComponent finalText = Component.literal(""); ChatColorFormat currentColor = new ChatColorFormat(0, 'f'); HashSet currentFonts = new HashSet<>(); int startIndex = 0;