From 90f2a5156173200e9d46b898a560ea25f08685a9 Mon Sep 17 00:00:00 2001 From: Aya <31237389+tal5@users.noreply.github.com> Date: Thu, 31 Jul 2025 09:54:36 +0100 Subject: [PATCH 01/24] Initial copy-paste over --- .../paper/utilities/FormattedTextHelper.java | 895 ++++++++++++++++++ 1 file changed, 895 insertions(+) create mode 100644 paper/src/main/java/com/denizenscript/denizen/paper/utilities/FormattedTextHelper.java diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/FormattedTextHelper.java b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/FormattedTextHelper.java new file mode 100644 index 0000000000..d00fa1219a --- /dev/null +++ b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/FormattedTextHelper.java @@ -0,0 +1,895 @@ +package com.denizenscript.denizen.paper.utilities; + +import com.denizenscript.denizen.nms.NMSHandler; +import com.denizenscript.denizen.nms.NMSVersion; +import com.denizenscript.denizen.objects.properties.bukkit.BukkitElementExtensions; +import com.denizenscript.denizen.utilities.HoverFormatHelper; +import com.denizenscript.denizen.utilities.Utilities; +import com.denizenscript.denizencore.objects.core.ColorTag; +import com.denizenscript.denizencore.objects.core.ElementTag; +import com.denizenscript.denizencore.objects.core.ListTag; +import com.denizenscript.denizencore.objects.core.MapTag; +import com.denizenscript.denizencore.utilities.AsciiMatcher; +import com.denizenscript.denizencore.utilities.CoreConfiguration; +import com.denizenscript.denizencore.utilities.CoreUtilities; +import com.denizenscript.denizencore.utilities.ReflectionHelper; +import com.denizenscript.denizencore.utilities.debugging.Debug; +import com.google.gson.Gson; +import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.chat.*; +import net.md_5.bungee.chat.ChatVersion; +import net.md_5.bungee.chat.ComponentSerializer; +import net.md_5.bungee.chat.VersionedComponentSerializer; + +import java.util.List; + +public class FormattedTextHelper { + + // <--[language] + // @name Denizen Text Formatting + // @group Denizen Magic + // @description + // Denizen provides a variety of special chat format options like "on_hover" and "on_click". + // These options exist within Denizen and do not appear in the historical Minecraft legacy chat format that most plugins and systems read. + // That legacy system has 16 colors (0-9, A-F) and a few toggleable formats (bold, italic, etc). It does not contain anything that needs more than just an on/off. + // + // Modern Minecraft, however, supports a JSON based "raw" message format that can do click events, hover events, full RGB colors, etc. + // + // Denizen therefore has its own internal system that works like the legacy format system, but also supports the new options normally only available as 'raw JSON'. + // + // Because it is entirely processed within Denizen, these options only work within Denizen, when performing actions that support raw JSON input. + // This magic tool exists to let you write messages without having to write the messy JSON. + // + // Be aware that many inputs do not support raw JSON, and as such are limited only the historical Minecraft legacy format. + // Also be aware that click events, hover events, etc. are exclusively limited to the chat bar and the pages of books, as you cannot mouse over anything else. + // + // Also note that RGB colors use a format that Spigot invented, meaning they will work in places that use Spigot's parser OR Denizen's version, but nowhere that uses the vanilla format still. + // + // Thanks to Paper's implementation of component APIs where Spigot was too lazy to, Paper servers have advanced text formatting available in more areas. + // --> + + public static AsciiMatcher needsEscapeMatcher = new AsciiMatcher("&;[]"); + + public static String escape(String input) { + if (needsEscapeMatcher.containsAnyMatch(input)) { + input = input.replace("&", "&").replace(";", "&sc").replace("[", "&lb").replace("]", "&rb").replace("\n", "&nl"); + } + return input.replace(String.valueOf(ChatColor.COLOR_CHAR), "&ss"); + } + + public static String unescape(String input) { + if (input.indexOf('&') != -1) { + return input.replace("&sc", ";").replace("&lb", "[").replace("&rb", "]").replace("&nl", "\n").replace("&ss", String.valueOf(ChatColor.COLOR_CHAR)).replace("&", "&"); + } + return input; + } + + public static boolean hasRootFormat(BaseComponent component) { + if (component == null) { + return false; + } + if (component.hasFormatting()) { + return true; + } + if (!(component instanceof TextComponent)) { + return false; + } + if (!((TextComponent) component).getText().isEmpty()) { + return false; + } + List extra = component.getExtra(); + if (extra == null || extra.isEmpty()) { + return false; + } + return hasRootFormat(extra.get(0)); + } + + public static String stringify(BaseComponent[] components) { + if (components == null) { + return null; + } + if (components.length == 0) { + return ""; + } + StringBuilder builder = new StringBuilder(128 * components.length); + if (hasRootFormat(components[0])) { + builder.append(RESET); + } + for (BaseComponent component : components) { + if (component != null) { + builder.append(stringify(component)); + } + } + String output = builder.toString(); + while (output.endsWith(RESET)) { + output = output.substring(0, output.length() - RESET.length()); + } + while (output.startsWith(POSSIBLE_RESET_PREFIX) && output.length() > 4 && colorCodeInvalidator.isMatch(output.charAt(3))) { + output = output.substring(2); + } + return cleanRedundantCodes(output); + } + + public static String stringifyRGBSpigot(String hex) { + StringBuilder hexBuilder = new StringBuilder(7); + hexBuilder.append('x'); + for (int i = hex.length(); i < 6; i++) { + hexBuilder.append('0'); + } + hexBuilder.append(hex); + hex = hexBuilder.toString(); + StringBuilder outColor = new StringBuilder(); + for (char c : hex.toCharArray()) { + outColor.append(org.bukkit.ChatColor.COLOR_CHAR).append(c); + } + return outColor.toString(); + } + + public static String stringify(BaseComponent component) { + return stringifySub(component, null); + } + + public static String stringifySub(BaseComponent component, ChatColor parentColor) { + if (component == null) { + return null; + } + StringBuilder builder = new StringBuilder(128); + ChatColor color = component.getColorRaw(); + if (color == null) { + color = parentColor; + } + if (color != null) { + builder.append(color); + } + if (component.isBold()) { + builder.append(ChatColor.BOLD); + } + if (component.isItalic()) { + builder.append(ChatColor.ITALIC); + } + if (component.isStrikethrough()) { + builder.append(ChatColor.STRIKETHROUGH); + } + if (component.isUnderlined()) { + builder.append(ChatColor.UNDERLINE); + } + if (component.isObfuscated()) { + builder.append(ChatColor.MAGIC); + } + boolean hasFont = component.getFontRaw() != null; + if (hasFont) { + builder.append(ChatColor.COLOR_CHAR).append("[font=").append(component.getFont()).append("]"); + } + boolean hasInsertion = component.getInsertion() != null; + if (hasInsertion) { + builder.append(ChatColor.COLOR_CHAR).append("[insertion=").append(escape(component.getInsertion())).append("]"); + } + boolean hasHover = component.getHoverEvent() != null; + if (hasHover) { + HoverEvent hover = component.getHoverEvent(); + builder.append(ChatColor.COLOR_CHAR).append("[hover=").append(hover.getAction().name()).append(";").append(escape(HoverFormatHelper.stringForHover(hover))).append("]"); + } + boolean hasClick = component.getClickEvent() != null; + if (hasClick) { + ClickEvent click = component.getClickEvent(); + builder.append(ChatColor.COLOR_CHAR).append("[click=").append(click.getAction().name()).append(";").append(escape(click.getValue())).append("]"); + } + if (component instanceof TextComponent) { + builder.append(((TextComponent) component).getText()); + } + else if (component instanceof TranslatableComponent translatableComponent) { + MapTag map = new MapTag(); + map.putObject("key", new ElementTag(translatableComponent.getTranslate(), true)); + if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20) && translatableComponent.getFallback() != null) { + map.putObject("fallback", new ElementTag(translatableComponent.getFallback(), true)); + } + if (translatableComponent.getWith() != null) { + map.putObject("with", new ListTag(translatableComponent.getWith(), baseComponent -> new ElementTag(stringify(baseComponent), true))); + } + builder.append(ChatColor.COLOR_CHAR).append("[translate=").append(escape(map.savable())).append(']'); + } + else if (component instanceof SelectorComponent) { + builder.append(ChatColor.COLOR_CHAR).append("[selector=").append(escape(((SelectorComponent) component).getSelector())).append("]"); + } + else if (component instanceof KeybindComponent) { + builder.append(ChatColor.COLOR_CHAR).append("[keybind=").append(escape(((KeybindComponent) component).getKeybind())).append("]"); + } + else if (component instanceof ScoreComponent) { + builder.append(ChatColor.COLOR_CHAR).append("[score=").append(escape(((ScoreComponent) component).getName())) + .append(";").append(escape(((ScoreComponent) component).getObjective())) + .append(";").append(escape(((ScoreComponent) component).getValue())).append("]"); + } + List after = component.getExtra(); + if (after != null) { + for (BaseComponent afterComponent : after) { + builder.append(stringifySub(afterComponent, color)); + } + } + if (hasClick) { + builder.append(ChatColor.COLOR_CHAR + "[/click]"); + } + if (hasHover) { + builder.append(ChatColor.COLOR_CHAR + "[/hover]"); + } + if (hasInsertion) { + builder.append(ChatColor.COLOR_CHAR + "[/insertion]"); + } + if (hasFont) { + builder.append(ChatColor.COLOR_CHAR + "[reset=font]"); + } + builder.append(RESET); + String output = builder.toString(); + return cleanRedundantCodes(output); + } + + public static final String RESET = ChatColor.RESET.toString(), POSSIBLE_RESET_PREFIX = RESET + ChatColor.COLOR_CHAR; + + private static Boolean procBool(Boolean input, boolean optimize) { + if (input == null) { + return null; + } + if (optimize) { + return input ? true : null; + } + return input; + } + + public static TextComponent copyFormatToNewText(TextComponent last, boolean optimize) { + TextComponent toRet = new TextComponent(); + toRet.setObfuscated(procBool(last.isObfuscatedRaw(), optimize)); + toRet.setBold(procBool(last.isBoldRaw(), optimize)); + toRet.setStrikethrough(procBool(last.isStrikethroughRaw(), optimize)); + toRet.setUnderlined(procBool(last.isUnderlinedRaw(), optimize)); + toRet.setItalic(procBool(last.isItalicRaw(), optimize)); + toRet.setColor(last.getColorRaw()); + return toRet; + } + + public static BaseComponent[] parse(String str, ChatColor baseColor) { + if (str == null) { + return null; + } + return parse(str, baseColor, true); + } + + public static int findNextNormalColorSymbol(String base, int startAt) { + while (true) { + int next = base.indexOf(ChatColor.COLOR_CHAR, startAt); + if (next == -1 || next + 1 >= base.length()) { + return -1; + } + char after = base.charAt(next + 1); + if (colorCodeInvalidator.isMatch(after)) { + return next; + } + startAt = next + 1; + } + } + + public static int findEndIndexFor(String base, String startSymbol, String endSymbol, int startAt) { + int layers = 1; + while (true) { + int next = base.indexOf(ChatColor.COLOR_CHAR, startAt); + if (next == -1) { + return -1; + } + if (next + endSymbol.length() >= base.length()) { + return -1; + } + if (base.startsWith(startSymbol, next + 1)) { + layers++; + } + else if (base.startsWith(endSymbol, next + 1)) { + layers--; + if (layers == 0) { + return next; + } + } + startAt = next + 1; + } + } + + public static int findEndIndexFor(String base, String type, int startAt) { + return findEndIndexFor(base, "[" + type + "=", "[/" + type + "]", startAt); + } + + public static String HEX = "0123456789abcdefABCDEF"; + + public static AsciiMatcher allowedCharCodes = new AsciiMatcher(HEX + "klmnorxKLMNORX["); + + public static AsciiMatcher hexMatcher = new AsciiMatcher(HEX); + + public static AsciiMatcher colorCodesOrReset = new AsciiMatcher(HEX + "rR"); // Any color code that can be invalidated + + public static AsciiMatcher colorCodeInvalidator = new AsciiMatcher(HEX + "rRxX"); // Any code that can invalidate the colors above + + public static String cleanRedundantCodes(String str) { + int index = str.indexOf(ChatColor.COLOR_CHAR); + if (index == -1) { + return str; + } + int start = 0; + StringBuilder output = new StringBuilder(str.length()); + while (index != -1) { + output.append(str, start, index); + start = index; + if (index + 1 >= str.length()) { + break; + } + char symbol = str.charAt(index + 1); + if (allowedCharCodes.isMatch(symbol)) { + if (symbol == 'x' || symbol == 'X') { // Skip entire hex block + index = str.indexOf(ChatColor.COLOR_CHAR, index + 14); + continue; + } + int nextIndex = str.indexOf(ChatColor.COLOR_CHAR, index + 1); + if (colorCodesOrReset.isMatch(symbol) && nextIndex == index + 2 && nextIndex + 1 < str.length()) { + char nextSymbol = str.charAt(nextIndex + 1); + if (colorCodeInvalidator.isMatch(nextSymbol)) { + start = index + 2; // Exclude from output the initial (redundant) color code + index = nextIndex; + continue; + } + } + } + index = str.indexOf(ChatColor.COLOR_CHAR, index + 1); + } + output.append(str, start, str.length()); + return output.toString(); + } + + public static TextComponent getCleanRef() { + TextComponent reference = new TextComponent(); + reference.setBold(false); + reference.setItalic(false); + reference.setStrikethrough(false); + reference.setUnderlined(false); + reference.setObfuscated(false); + return reference; + } + + public static BaseComponent[] parseSimpleColorsOnly(String str) { + TextComponent root = new TextComponent(); + int firstChar = str.indexOf(ChatColor.COLOR_CHAR); + int lastStart = 0; + if (firstChar > 0) { + root.addExtra(new TextComponent(str.substring(0, firstChar))); + lastStart = firstChar; + } + TextComponent nextText = new TextComponent(); + while (firstChar != -1 && firstChar + 1 < str.length()) { + char c = str.charAt(firstChar + 1); + if (allowedCharCodes.isMatch(c)) { + if (c == 'r' || c == 'R') { + nextText.setText(str.substring(lastStart, firstChar)); + if (!nextText.getText().isEmpty()) { + root.addExtra(nextText); + } + nextText = getCleanRef(); + lastStart = firstChar + 2; + } + else if (c == 'X' || c == 'x' && firstChar + 13 < str.length()) { + StringBuilder color = new StringBuilder(12); + color.append("#"); + for (int i = 1; i <= 6; i++) { + if (str.charAt(firstChar + i * 2) != ChatColor.COLOR_CHAR) { + color = null; + break; + } + char hexChar = str.charAt(firstChar + 1 + i * 2); + if (!hexMatcher.isMatch(hexChar)) { + color = null; + break; + } + color.append(hexChar); + } + if (color != null) { + nextText.setText(str.substring(lastStart, firstChar)); + if (!nextText.getText().isEmpty()) { + root.addExtra(nextText); + } + nextText = getCleanRef(); + nextText.setColor(ChatColor.of(CoreUtilities.toUpperCase(color.toString()))); + firstChar += 12; + lastStart = firstChar + 2; + } + } + else if (colorCodesOrReset.isMatch(c)) { + nextText.setText(str.substring(lastStart, firstChar)); + if (!nextText.getText().isEmpty()) { + root.addExtra(nextText); + } + nextText = getCleanRef(); + nextText.setColor(ChatColor.getByChar(c)); + lastStart = firstChar + 2; + } + else { // format code + nextText.setText(str.substring(lastStart, firstChar)); + if (!nextText.getText().isEmpty()) { + root.addExtra(nextText); + } + nextText = copyFormatToNewText(nextText, false); + if (c == 'k' || c == 'K') { + nextText.setObfuscated(true); + } + else if (c == 'l' || c == 'L') { + nextText.setBold(true); + } + else if (c == 'm' || c == 'M') { + nextText.setStrikethrough(true); + } + else if (c == 'n' || c == 'N') { + nextText.setUnderlined(true); + } + else if (c == 'o' || c == 'O') { + nextText.setItalic(true); + } + lastStart = firstChar + 2; + } + } + firstChar = str.indexOf(ChatColor.COLOR_CHAR, firstChar + 1); + } + if (lastStart < str.length()) { + nextText.setText(str.substring(lastStart)); + root.addExtra(nextText); + } + return new BaseComponent[] { root }; + } + + public static BaseComponent[] parse(String str, ChatColor baseColor, boolean cleanBase) { + if (str == null) { + return null; + } + try { + return parseInternal(str, baseColor, cleanBase, false); + } + catch (Throwable ex) { + Debug.echoError(ex); + } + return new BaseComponent[]{new TextComponent(str)}; + } + + private static BaseComponent parseTranslatable(String str, ChatColor baseColor, boolean optimize) { + if (!str.startsWith("map@")) { + List innardParts = CoreUtilities.split(str, ';'); + TranslatableComponent component = new TranslatableComponent(unescape(innardParts.get(0))); + for (int i = 1; i < innardParts.size(); i++) { + for (BaseComponent subComponent : parseInternal(unescape(innardParts.get(i)), baseColor, false, optimize)) { + component.addWith(subComponent); + } + } + return component; + } + MapTag map = MapTag.valueOf(unescape(str), CoreUtilities.noDebugContext); + if (map == null) { + return new TextComponent(str); + } + ElementTag translationKey = map.getElement("key"); + if (translationKey == null) { + return new TextComponent(str); + } + TranslatableComponent component = new TranslatableComponent(translationKey.asString()); + ElementTag fallback = map.getElement("fallback"); + if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20) && fallback != null) { + component.setFallback(fallback.asString()); + } + ListTag withList = map.getObjectAs("with", ListTag.class, CoreUtilities.noDebugContext); + if (withList != null) { + for (String with : withList) { + for (BaseComponent withComponent : parseInternal(with, baseColor, false, optimize)) { + component.addWith(withComponent); + } + } + } + return component; + } + + public static BaseComponent[] parseInternal(String str, ChatColor baseColor, boolean cleanBase, boolean optimize) { + str = CoreUtilities.clearNBSPs(str); + int firstChar = str.indexOf(ChatColor.COLOR_CHAR); + if (firstChar == -1) { + if (str.contains("://")) { + firstChar = 0; + } + else { + TextComponent base = new TextComponent(); + base.addExtra(new TextComponent(str)); // This is for compat with how Spigot does parsing of plaintext. + return new BaseComponent[]{base}; + } + } + str = cleanRedundantCodes(str); + if (cleanBase && str.length() < 512) { + if (!str.contains(ChatColor.COLOR_CHAR + "[") && !str.contains("://")) { + return parseSimpleColorsOnly(str); + } + // Ensure compat with certain weird vanilla translate strings. + if (str.startsWith(ChatColor.COLOR_CHAR + "[translate=") && str.indexOf(']') == str.length() - 1) { + return new BaseComponent[] {parseTranslatable(str.substring("&[translate=".length(), str.length() - 1), baseColor, optimize)}; + } + if (str.length() > 3 && str.startsWith((ChatColor.COLOR_CHAR + "")) && hexMatcher.isMatch(str.charAt(1)) + && str.startsWith(ChatColor.COLOR_CHAR + "[translate=", 2) && str.indexOf(']') == str.length() - 1) { // eg "&6&[translate=block.minecraft.ominous_banner]" + BaseComponent component = parseTranslatable(str.substring("&[translate=".length() + 2, str.length() - 1), baseColor, optimize); + component.setColor(ChatColor.getByChar(str.charAt(1))); + return new BaseComponent[] {component}; + } + } + if (!optimize) { + optimize = str.contains(ChatColor.COLOR_CHAR + "[optimize=true]"); + } + TextComponent root = new TextComponent(); + TextComponent base = new TextComponent(); + if (cleanBase && !optimize) { + base.setBold(false); + base.setItalic(false); + base.setStrikethrough(false); + base.setUnderlined(false); + base.setObfuscated(false); + base.setColor(baseColor); + if (firstChar > 0) { + root.addExtra(new TextComponent(str.substring(0, firstChar))); + } + } + else { + base.setText(str.substring(0, firstChar)); + } + root.addExtra(base); + str = str.substring(firstChar); + char[] chars = str.toCharArray(); + int started = 0; + TextComponent nextText = new TextComponent(); + TextComponent lastText; + for (int i = 0; i < chars.length; i++) { + if (chars[i] == ChatColor.COLOR_CHAR && i + 1 < chars.length) { + char code = chars[i + 1]; + if (!allowedCharCodes.isMatch(code)) { + continue; + } + if (code == '[') { + int endBracket = str.indexOf(']', i + 2); + if (endBracket == -1) { + continue; + } + String innards = str.substring(i + 2, endBracket); + List innardParts = CoreUtilities.split(innards, ';'); + List innardBase = CoreUtilities.split(innardParts.get(0), '=', 2); + innardParts.remove(0); + String innardType = CoreUtilities.toLowerCase(innardBase.get(0)); + if (innardBase.size() == 2) { + nextText.setText(nextText.getText() + str.substring(started, i)); + base.addExtra(nextText); + lastText = nextText; + nextText = copyFormatToNewText(lastText, optimize); + nextText.setText(""); + if (innardType.equals("score") && innardParts.size() == 2) { + ScoreComponent component = new ScoreComponent(unescape(innardBase.get(1)), unescape(innardParts.get(0)), unescape(innardParts.get(1))); + lastText.addExtra(component); + } + else if (innardType.equals("keybind") && Utilities.matchesNamespacedKeyButCaseInsensitive(innardBase.get(1))) { + KeybindComponent component = new KeybindComponent(); + component.setKeybind(unescape(innardBase.get(1))); + lastText.addExtra(component); + } + else if (innardType.equals("selector")) { + SelectorComponent component = new SelectorComponent(unescape(innardBase.get(1))); + lastText.addExtra(component); + } + else if (innardType.equals("translate")) { + lastText.addExtra(parseTranslatable(innards.substring("translate=".length()), baseColor, optimize)); + } + else if (innardType.equals("click") && innardParts.size() == 1) { + int endIndex = findEndIndexFor(str, "click", endBracket); + if (endIndex == -1) { + continue; + } + TextComponent clickableText = new TextComponent(); + ClickEvent.Action action = ElementTag.asEnum(ClickEvent.Action.class, innardBase.get(1)); + clickableText.setClickEvent(new ClickEvent(action == null ? ClickEvent.Action.SUGGEST_COMMAND : action, unescape(innardParts.get(0)))); + for (BaseComponent subComponent : parseInternal(str.substring(endBracket + 1, endIndex), baseColor, false, optimize)) { + clickableText.addExtra(subComponent); + } + lastText.addExtra(clickableText); + endBracket = endIndex + "&[/click".length(); + } + else if (innardType.equals("hover")) { + int endIndex = findEndIndexFor(str, "hover", endBracket); + if (endIndex == -1) { + continue; + } + TextComponent hoverableText = new TextComponent(); + HoverEvent.Action action = ElementTag.asEnum(HoverEvent.Action.class, innardBase.get(1)); + if (HoverFormatHelper.processHoverInput(action == null ? HoverEvent.Action.SHOW_TEXT : action, hoverableText, innardParts.get(0))) { + continue; + } + for (BaseComponent subComponent : parseInternal(str.substring(endBracket + 1, endIndex), baseColor, false, optimize)) { + hoverableText.addExtra(subComponent); + } + lastText.addExtra(hoverableText); + endBracket = endIndex + "&[/hover".length(); + } + else if (innardType.equals("insertion")) { + int endIndex = str.indexOf(ChatColor.COLOR_CHAR + "[/insertion]", i); + int backupEndIndex = str.indexOf(ChatColor.COLOR_CHAR + "[insertion=", i + 5); + if (backupEndIndex > 0 && backupEndIndex < endIndex) { + endIndex = backupEndIndex; + } + if (endIndex == -1) { + continue; + } + TextComponent insertableText = new TextComponent(); + insertableText.setInsertion(unescape(innardBase.get(1))); + for (BaseComponent subComponent : parseInternal(str.substring(endBracket + 1, endIndex), baseColor, false, optimize)) { + insertableText.addExtra(subComponent); + } + lastText.addExtra(insertableText); + endBracket = endIndex + "&[/insertion".length(); + } + else if (innardType.equals("reset")) { + if (innardBase.get(1).length() == 1) { + char subCode = innardBase.get(1).charAt(0); + if (subCode == 'k' || subCode == 'K') { + nextText.setObfuscated(false); + } + else if (subCode == 'l' || subCode == 'L') { + nextText.setBold(false); + } + else if (subCode == 'm' || subCode == 'M') { + nextText.setStrikethrough(false); + } + else if (subCode == 'n' || subCode == 'N') { + nextText.setUnderlined(false); + } + else if (subCode == 'o' || subCode == 'O') { + nextText.setItalic(false); + } + } + else if (innardBase.get(1).equals("font")) { + nextText.setFont(base.getFont()); + } + else { + nextText.setColor(base.getColor()); + } + } + else if (innardType.equals("color")) { + String colorChar = innardBase.get(1); + ChatColor color = null; + if (colorChar.length() == 1) { + color = ChatColor.getByChar(colorChar.charAt(0)); + } + else if (colorChar.length() == 7) { + color = ChatColor.of(CoreUtilities.toUpperCase(colorChar)); + } + else if (CoreConfiguration.debugVerbose) { + Debug.echoError("Text parse issue: cannot interpret color '" + innardBase.get(1) + "'."); + } + if (color != null) { + int endIndex = findEndIndexFor(str, "[color=", "[reset=color]", endBracket); + if (endIndex == -1) { + nextText.setColor(color); + } + else { + TextComponent colorText = new TextComponent(); + colorText.setColor(color); + for (BaseComponent subComponent : parseInternal(str.substring(endBracket + 1, endIndex), color, false, optimize)) { + colorText.addExtra(subComponent); + } + lastText.addExtra(colorText); + endBracket = endIndex + "&[reset=color".length(); + } + } + } + else if (innardType.equals("gradient") && innardParts.size() == 2) { + String from = innardBase.get(1), to = innardParts.get(0), style = innardParts.get(1); + ColorTag fromColor = ColorTag.valueOf(from, CoreUtilities.noDebugContext); + ColorTag toColor = ColorTag.valueOf(to, CoreUtilities.noDebugContext); + BukkitElementExtensions.GradientStyle styleEnum = new ElementTag(style).asEnum(BukkitElementExtensions.GradientStyle.class); + if (fromColor == null || toColor == null || styleEnum == null) { + if (CoreConfiguration.debugVerbose) { + Debug.echoError("Text parse issue: cannot interpret gradient input '" + innards + "'."); + } + } + else { + int endIndex = findNextNormalColorSymbol(str, i + 1); + if (endIndex == -1) { + endIndex = str.length(); + } + String gradientText = BukkitElementExtensions.doGradient(str.substring(endBracket + 1, endIndex), fromColor, toColor, styleEnum); + for (BaseComponent subComponent : parseInternal(gradientText, baseColor, false, optimize)) { + lastText.addExtra(subComponent); + } + endBracket = endIndex - 1; + } + } + else if (innardType.equals("font") && Utilities.matchesNamespacedKey(innardBase.get(1))) { + int endIndex = findEndIndexFor(str, "[font=", "[reset=font]", endBracket); + if (endIndex == -1) { + nextText.setFont(innardBase.get(1)); + } + else { + TextComponent fontText = new TextComponent(); + fontText.setFont(innardBase.get(1)); + for (BaseComponent subComponent : parseInternal(str.substring(endBracket + 1, endIndex), baseColor, false, optimize)) { + fontText.addExtra(subComponent); + } + lastText.addExtra(fontText); + endBracket = endIndex + "&[reset=font".length(); + } + } + else if (innardType.equals("optimize")) { + // Ignore + } + else { + if (CoreConfiguration.debugVerbose) { + Debug.echoError("Text parse issue: cannot interpret type '" + innardType + "' with " + innardParts.size() + " parts."); + } + } + } + i = endBracket; + started = endBracket + 1; + continue; + } + else if (code == 'r' || code == 'R') { + nextText.setText(nextText.getText() + str.substring(started, i)); + if (!nextText.getText().isEmpty()) { + base.addExtra(nextText); + } + nextText = new TextComponent(); + nextText.setColor(baseColor); + } + else if (colorCodesOrReset.isMatch(code)) { + nextText.setText(nextText.getText() + str.substring(started, i)); + if (!nextText.getText().isEmpty()) { + base.addExtra(nextText); + } + nextText = new TextComponent(); + nextText.setColor(ChatColor.getByChar(code)); + } + else if (code == 'x') { + if (i + 13 >= chars.length) { + continue; + } + StringBuilder color = new StringBuilder(12); + color.append("#"); + for (int c = 1; c <= 6; c++) { + if (chars[i + c * 2] != ChatColor.COLOR_CHAR) { + color = null; + break; + } + char hexPart = chars[i + 1 + c * 2]; + if (!hexMatcher.isMatch(hexPart)) { + color = null; + break; + } + color.append(hexPart); + } + if (color == null) { + continue; + } + nextText.setText(nextText.getText() + str.substring(started, i)); + if (!nextText.getText().isEmpty()) { + base.addExtra(nextText); + } + nextText = new TextComponent(); + nextText.setColor(ChatColor.of(CoreUtilities.toUpperCase(color.toString()))); + i += 13; + started = i + 1; + continue; + } + else { + nextText.setText(nextText.getText() + str.substring(started, i)); + if (!nextText.getText().isEmpty()) { + base.addExtra(nextText); + } + nextText = copyFormatToNewText(nextText, optimize); + if (code == 'k' || code == 'K') { + nextText.setObfuscated(true); + } + else if (code == 'l' || code == 'L') { + nextText.setBold(true); + } + else if (code == 'm' || code == 'M') { + nextText.setStrikethrough(true); + } + else if (code == 'n' || code == 'N') { + nextText.setUnderlined(true); + } + else if (code == 'o' || code == 'O') { + nextText.setItalic(true); + } + } + i++; + started = i + 1; + } + else if (i + "https://a.".length() < chars.length && chars[i] == 'h' && chars[i + 1] == 't' && chars[i + 2] == 't' && chars[i + 3] == 'p') { + String subStr = str.substring(i, i + "https://a.".length()); + if (subStr.startsWith("https://") || subStr.startsWith("http://")) { + int nextSpace = CoreUtilities.indexOfAny(str, i, ' ', '\t', '\n', ChatColor.COLOR_CHAR); + if (nextSpace == -1) { + nextSpace = str.length(); + } + String url = str.substring(i, nextSpace); + nextText.setText(nextText.getText() + str.substring(started, i)); + base.addExtra(nextText); + lastText = nextText; + nextText = new TextComponent(lastText); + nextText.setText(""); + TextComponent clickableText = new TextComponent(url); + clickableText.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, url)); + lastText.addExtra(clickableText); + i = nextSpace - 1; + started = nextSpace; + continue; + } + } + } + nextText.setText(nextText.getText() + str.substring(started)); + if (!nextText.getText().isEmpty()) { + base.addExtra(nextText); + } + return new BaseComponent[] { cleanBase && !optimize ? root : base }; + } + + public static int indexOfLastColorBlockStart(String text) { + int result = text.lastIndexOf(ChatColor.COLOR_CHAR + "["); + if (result == -1 || text.indexOf(']', result + 2) != -1) { + return -1; + } + return result; + } + + /** + * Equivalent to DebugInternals.trimMessage, with a special check: + * If a message is cut in the middle of a format block like "&[font=x:y]", cut that block entirely out. + * (This is needed because a snip in the middle of this will explode with parsing errors). + */ + public static String bukkitSafeDebugTrimming(String message) { + int trimSize = CoreConfiguration.debugTrimLength; + if (message.length() > trimSize) { + int firstCut = (trimSize / 2) - 10, secondCut = message.length() - ((trimSize / 2) - 10); + String prePart = message.substring(0, firstCut); + String cutPart = message.substring(firstCut, secondCut); + String postPart = message.substring(secondCut); + int preEarlyCut = indexOfLastColorBlockStart(prePart); + if (preEarlyCut != -1) { + prePart = message.substring(0, preEarlyCut); + } + if (indexOfLastColorBlockStart(cutPart) != -1 || (preEarlyCut != -1 && cutPart.indexOf(']') == -1)) { + int lateCut = postPart.indexOf(']'); + if (lateCut != -1) { + postPart = postPart.substring(lateCut + 1); + } + } + message = prePart + "... *snip!*..." + postPart; + } + return message; + } + + public static Gson getBungeeGson() { + if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21)) { + return VersionedComponentSerializer.forVersion(ChatVersion.V1_21_5).getGson(); + } + else { + return ReflectionHelper.getFieldValue(ComponentSerializer.class, "gson", null); + } + } + + static { + // Explicitly before initializing vanillaStyleSpigotComponentGSON + HoverFormatHelper.tryInitializeItemHoverFix(); + } + + public static final Gson vanillaStyleSpigotComponentGSON = getBungeeGson().newBuilder().disableHtmlEscaping().create(); + + public static String componentToJson(BaseComponent[] components) { + if (components.length == 1) { + return vanillaStyleSpigotComponentGSON.toJson(components[0]); + } + return vanillaStyleSpigotComponentGSON.toJson(new TextComponent(components)); + } + + public static BaseComponent[] parseJson(String json) { + if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21)) { + return VersionedComponentSerializer.forVersion(ChatVersion.V1_21_5).parse(json); + } + return ComponentSerializer.parse(json); + } +} From d9f1d7bc3ae528f7f2af1bc89725252350c174f4 Mon Sep 17 00:00:00 2001 From: Aya <31237389+tal5@users.noreply.github.com> Date: Thu, 4 Sep 2025 13:36:35 +0100 Subject: [PATCH 02/24] Copy-paste `HoverFormatHelper` --- .../paper/utilities/HoverFormatHelper.java | 241 ++++++++++++++++++ 1 file changed, 241 insertions(+) create mode 100644 paper/src/main/java/com/denizenscript/denizen/paper/utilities/HoverFormatHelper.java diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/HoverFormatHelper.java b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/HoverFormatHelper.java new file mode 100644 index 0000000000..fc8a52e3ca --- /dev/null +++ b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/HoverFormatHelper.java @@ -0,0 +1,241 @@ +package com.denizenscript.denizen.paper.utilities; + +import com.denizenscript.denizen.nms.NMSHandler; +import com.denizenscript.denizen.nms.NMSVersion; +import com.denizenscript.denizen.objects.EntityTag; +import com.denizenscript.denizen.objects.ItemTag; +import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.PaperAPITools; +import com.denizenscript.denizen.utilities.Utilities; +import com.denizenscript.denizencore.objects.ObjectTag; +import com.denizenscript.denizencore.objects.core.ElementTag; +import com.denizenscript.denizencore.objects.core.MapTag; +import com.denizenscript.denizencore.tags.Attribute; +import com.denizenscript.denizencore.utilities.CoreUtilities; +import com.denizenscript.denizencore.utilities.ReflectionHelper; +import com.denizenscript.denizencore.utilities.debugging.Debug; +import com.google.gson.*; +import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.api.chat.HoverEvent; +import net.md_5.bungee.api.chat.TextComponent; +import net.md_5.bungee.api.chat.hover.content.*; +import net.md_5.bungee.chat.ChatVersion; +import net.md_5.bungee.chat.ComponentSerializer; +import net.md_5.bungee.chat.VersionedComponentSerializer; +import org.bukkit.Bukkit; +import org.bukkit.Registry; +import org.bukkit.inventory.ItemStack; + +import java.lang.reflect.Type; +import java.util.UUID; + +public class HoverFormatHelper { + + public static boolean processHoverInput(HoverEvent.Action action, TextComponent hoverableText, String input) { + Content content; + if (action == HoverEvent.Action.SHOW_ITEM) { + ItemTag item = ItemTag.valueOf(com.denizenscript.denizen.utilities.FormattedTextHelper.unescape(input), CoreUtilities.noDebugContext); + if (item == null) { + return true; + } + if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20)) { + content = new com.denizenscript.denizen.utilities.HoverFormatHelper.FixedItemHover(item.getBukkitMaterial().getKey().toString(), item.getAmount(), NMSHandler.itemHelper.getRawHoverComponentsJson(item.getItemStack())); + } + else { + content = new Item(item.getBukkitMaterial().getKey().toString(), item.getAmount(), net.md_5.bungee.api.chat.ItemTag.ofNbt(NMSHandler.itemHelper.getLegacyHoverNbt(item))); + } + } + else if (action == HoverEvent.Action.SHOW_ENTITY) { + String rawInput = com.denizenscript.denizen.utilities.FormattedTextHelper.unescape(input); + if (!rawInput.startsWith("map@")) { + content = parseLegacyEntityHover(rawInput); + if (content == null) { + return true; + } + } + else { + MapTag entityHoverData = MapTag.valueOf(rawInput, CoreUtilities.noDebugContext); + if (entityHoverData == null) { + return true; + } + ElementTag uuid = entityHoverData.getElement("uuid"); + if (uuid == null) { + return true; + } + ElementTag type = entityHoverData.getElement("type"); + ElementTag rawName = entityHoverData.getElement("name"); + BaseComponent name = rawName != null ? new TextComponent(com.denizenscript.denizen.utilities.FormattedTextHelper.parse(rawName.asString(), ChatColor.WHITE)) : null; + content = new Entity(type != null ? type.asString() : null, uuid.asString(), name); + } + } + else { + content = new Text(com.denizenscript.denizen.utilities.FormattedTextHelper.parse(com.denizenscript.denizen.utilities.FormattedTextHelper.unescape(input), ChatColor.WHITE)); + } + hoverableText.setHoverEvent(new HoverEvent(action, content)); + return false; + } + + public static String stringForHover(HoverEvent hover) { + if (hover.getContents().isEmpty()) { + return ""; + } + Content contentObject = hover.getContents().get(0); + if (contentObject instanceof Text textHover) { + Object value = textHover.getValue(); + if (value instanceof BaseComponent[] componentsValue) { + return com.denizenscript.denizen.utilities.FormattedTextHelper.stringify(componentsValue); + } + else { + return value.toString(); + } + } + else if (contentObject instanceof Item itemHover) { + ItemStack item = new ItemStack(Registry.MATERIAL.get(Utilities.parseNamespacedKey(itemHover.getId())), itemHover.getCount() == -1 ? 1 : itemHover.getCount()); + if (itemHover instanceof com.denizenscript.denizen.utilities.HoverFormatHelper.FixedItemHover fixedItemHover && fixedItemHover.getComponents() != null) { + item = NMSHandler.itemHelper.applyRawHoverComponentsJson(item, fixedItemHover.getComponents()); + } + else if (NMSHandler.getVersion().isAtMost(NMSVersion.v1_19) && itemHover.getTag() != null && itemHover.getTag().getNbt() != null) { + item = Bukkit.getUnsafe().modifyItemStack(item, itemHover.getTag().getNbt()); + } + return new ItemTag(item).identify(); + } + else if (contentObject instanceof Entity entityHover) { + return createEntityHoverData(entityHover.getId(), entityHover.getType(), entityHover.getName()).savable(); + } + else { + throw new UnsupportedOperationException(); + } + } + + public static MapTag createEntityHoverData(String uuid, String type, BaseComponent name) { + MapTag entityHoverData = new MapTag(); + entityHoverData.putObject("uuid", new ElementTag(uuid, true)); + if (type != null) { + entityHoverData.putObject("type", new ElementTag(type, true)); + } + else { + try { + // This isn't even optional, but is in Bungee for some reason - try our best to have a value + org.bukkit.entity.Entity found = EntityTag.getEntityForID(UUID.fromString(uuid)); + if (found != null) { + entityHoverData.putObject("type", new ElementTag(found.getType().getKey().toString(), true)); + } + } + catch (IllegalArgumentException ignore) {} + } + if (name != null) { + entityHoverData.putObject("name", new ElementTag(com.denizenscript.denizen.utilities.FormattedTextHelper.stringify(name), true)); + } + return entityHoverData; + } + + public static String parseObjectToHover(ObjectTag object, HoverEvent.Action action, Attribute attribute) { + return switch (action) { + case SHOW_ENTITY -> { + EntityTag toShow = object.asType(EntityTag.class, attribute.context); + if (toShow == null) { + attribute.echoError("Invalid hover object '" + object + "' specified for type 'SHOW_ENTITY': must be an EntityTag."); + yield null; + } + BaseComponent[] customName = PaperAPITools.instance.getCustomNameComponent(toShow.getBukkitEntity()); + yield createEntityHoverData(toShow.getUUID().toString(), toShow.getBukkitEntityType().getKey().toString(), customName != null ? new TextComponent(customName) : null).savable(); + } + case SHOW_ITEM -> { + ItemTag toShow = object.asType(ItemTag.class, attribute.context); + if (toShow == null) { + attribute.echoError("Invalid hover object '" + object + "' specified for type 'SHOW_ITEM': must be an ItemTag."); + yield null; + } + yield toShow.identify(); + } + case SHOW_TEXT -> object.toString(); + default -> { + attribute.echoError("Using unsupported hover type: " + action + '.'); + yield null; + } + }; + } + + private static Entity parseLegacyEntityHover(String input) { + EntityTag entity = EntityTag.valueOf(input, CoreUtilities.basicContext); + if (entity == null) { + return null; + } + BaseComponent name = null; + if (entity.getBukkitEntity() != null && entity.getBukkitEntity().isCustomNameVisible()) { + name = new TextComponent(); + for (BaseComponent component : com.denizenscript.denizen.utilities.FormattedTextHelper.parse(entity.getBukkitEntity().getCustomName(), ChatColor.WHITE)) { + name.addExtra(component); + } + } + return new Entity(entity.getBukkitEntityType().getKey().toString(), entity.getUUID().toString(), name); + } + + public static void tryInitializeItemHoverFix() { + if (!NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20)) { + return; + } + Gson bungeeGson = FormattedTextHelper.getBungeeGson(); + if (bungeeGson == null) { + return; + } + Gson fixedGson = bungeeGson.newBuilder() + .registerTypeAdapter(com.denizenscript.denizen.utilities.HoverFormatHelper.FixedItemHover.class, new com.denizenscript.denizen.utilities.HoverFormatHelper.FixedItemHoverSerializer()) + .registerTypeAdapter(Item.class, new com.denizenscript.denizen.utilities.HoverFormatHelper.FixedItemHoverSerializer()) + .create(); + try { + if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21)) { + ReflectionHelper.setFieldValue(VersionedComponentSerializer.class, "gson", VersionedComponentSerializer.forVersion(ChatVersion.V1_21_5), fixedGson); + } + else { + ReflectionHelper.getFinalSetter(ComponentSerializer.class, "gson").invoke(fixedGson); + } + } + catch (Throwable e) { + Debug.echoError(e); + } + } + + public static class FixedItemHover extends Item { + + private final JsonObject components; + + public FixedItemHover(String id, int count, JsonObject components) { + super(id, count, null); + this.components = components; + } + + public JsonObject getComponents() { + return components; + } + } + + public static class FixedItemHoverSerializer extends ItemSerializer { + + @Override + public Item deserialize(JsonElement element, Type type, JsonDeserializationContext context) throws JsonParseException { + Item deserialized = super.deserialize(element, type, context); + if (deserialized.getTag() != null) { + return deserialized; + } + JsonObject componentsObject = element.getAsJsonObject().getAsJsonObject("components"); + if (componentsObject == null) { + return deserialized; + } + return new com.denizenscript.denizen.utilities.HoverFormatHelper.FixedItemHover(deserialized.getId(), deserialized.getCount(), componentsObject); + } + + @Override + public JsonElement serialize(Item content, Type type, JsonSerializationContext context) { + JsonElement serialized = super.serialize(content, type, context); + if (!(content instanceof com.denizenscript.denizen.utilities.HoverFormatHelper.FixedItemHover fixedItemHover) || fixedItemHover.getComponents() == null) { + return serialized; + } + JsonObject serializedObject = serialized.getAsJsonObject(); + serializedObject.remove("tag"); + serializedObject.add("components", fixedItemHover.getComponents()); + return serializedObject; + } + } +} From b306a28cd4028189fc77db9fdc5598de19395b67 Mon Sep 17 00:00:00 2001 From: Aya <31237389+tal5@users.noreply.github.com> Date: Fri, 5 Sep 2025 22:06:52 +0100 Subject: [PATCH 03/24] Initial migration + TODOs --- .../paper/utilities/FormattedTextHelper.java | 662 +++++++++--------- .../paper/utilities/HoverFormatHelper.java | 224 ++---- 2 files changed, 411 insertions(+), 475 deletions(-) diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/FormattedTextHelper.java b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/FormattedTextHelper.java index d00fa1219a..fc52035d55 100644 --- a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/FormattedTextHelper.java +++ b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/FormattedTextHelper.java @@ -3,7 +3,6 @@ import com.denizenscript.denizen.nms.NMSHandler; import com.denizenscript.denizen.nms.NMSVersion; import com.denizenscript.denizen.objects.properties.bukkit.BukkitElementExtensions; -import com.denizenscript.denizen.utilities.HoverFormatHelper; import com.denizenscript.denizen.utilities.Utilities; import com.denizenscript.denizencore.objects.core.ColorTag; import com.denizenscript.denizencore.objects.core.ElementTag; @@ -12,16 +11,18 @@ import com.denizenscript.denizencore.utilities.AsciiMatcher; import com.denizenscript.denizencore.utilities.CoreConfiguration; import com.denizenscript.denizencore.utilities.CoreUtilities; -import com.denizenscript.denizencore.utilities.ReflectionHelper; import com.denizenscript.denizencore.utilities.debugging.Debug; -import com.google.gson.Gson; -import net.md_5.bungee.api.ChatColor; -import net.md_5.bungee.api.chat.*; -import net.md_5.bungee.chat.ChatVersion; -import net.md_5.bungee.chat.ComponentSerializer; -import net.md_5.bungee.chat.VersionedComponentSerializer; - +import net.kyori.adventure.key.Key; +import net.kyori.adventure.text.*; +import net.kyori.adventure.text.event.ClickEvent; +import net.kyori.adventure.text.event.HoverEvent; +import net.kyori.adventure.text.format.*; +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; + +import java.util.ArrayList; +import java.util.IdentityHashMap; import java.util.List; +import java.util.Map; public class FormattedTextHelper { @@ -49,58 +50,117 @@ public class FormattedTextHelper { // --> public static AsciiMatcher needsEscapeMatcher = new AsciiMatcher("&;[]"); + public static final char LEGACY_SECTION = LegacyComponentSerializer.SECTION_CHAR; + + public enum LegacyColor { + BLACK('0', NamedTextColor.BLACK), + DARK_BLUE('1', NamedTextColor.DARK_BLUE), + DARK_GREEN('2', NamedTextColor.DARK_GREEN), + DARK_AQUA('3', NamedTextColor.DARK_AQUA), + DARK_RED('4', NamedTextColor.DARK_RED), + DARK_PURPLE('5', NamedTextColor.DARK_PURPLE), + GOLD('6', NamedTextColor.GOLD), + GRAY('7', NamedTextColor.GRAY), + DARK_GRAY('8', NamedTextColor.DARK_GRAY), + BLUE('9', NamedTextColor.BLUE), + GREEN('a', NamedTextColor.GREEN), + AQUA('b', NamedTextColor.AQUA), + RED('c', NamedTextColor.RED), + LIGHT_PURPLE('d', NamedTextColor.LIGHT_PURPLE), + YELLOW('e', NamedTextColor.YELLOW), + WHITE('f', NamedTextColor.WHITE); + + public final String formatString; + public final NamedTextColor color; + + LegacyColor(char formatChar, NamedTextColor color) { + this.formatString = new String(new char[]{LEGACY_SECTION, formatChar}); + this.color = color; + } + + @Override + public String toString() { + return formatString; + } + + public static LegacyColor fromModern(NamedTextColor textColor) { + return TO_LEGACY.get(textColor); + } + + private static final Map TO_LEGACY; + + static { + LegacyColor[] legacyColors = values(); + TO_LEGACY = new IdentityHashMap<>(legacyColors.length); + for (LegacyColor legacyColor : legacyColors) { + TO_LEGACY.put(legacyColor.color, legacyColor); + } + } + } + + public enum LegacyFormatting { + BOLD('l'), + ITALIC('o'), + STRIKETHROUGH('m'), + UNDERLINE('n'), + OBFUSCATED('k'), + RESET('r'); + + public final String formatString; + + LegacyFormatting(char formatChar) { + this.formatString = new String(new char[]{LEGACY_SECTION, formatChar}); + } + + @Override + public String toString() { + return formatString; + } + } public static String escape(String input) { if (needsEscapeMatcher.containsAnyMatch(input)) { input = input.replace("&", "&").replace(";", "&sc").replace("[", "&lb").replace("]", "&rb").replace("\n", "&nl"); } - return input.replace(String.valueOf(ChatColor.COLOR_CHAR), "&ss"); + return input.replace(String.valueOf(LEGACY_SECTION), "&ss"); } public static String unescape(String input) { if (input.indexOf('&') != -1) { - return input.replace("&sc", ";").replace("&lb", "[").replace("&rb", "]").replace("&nl", "\n").replace("&ss", String.valueOf(ChatColor.COLOR_CHAR)).replace("&", "&"); + return input.replace("&sc", ";").replace("&lb", "[").replace("&rb", "]").replace("&nl", "\n").replace("&ss", String.valueOf(LEGACY_SECTION)).replace("&", "&"); } return input; } - public static boolean hasRootFormat(BaseComponent component) { + public static boolean hasRootFormat(Component component) { if (component == null) { return false; } - if (component.hasFormatting()) { + if (component.hasStyling()) { return true; } - if (!(component instanceof TextComponent)) { + if (!(component instanceof TextComponent textComponent)) { return false; } - if (!((TextComponent) component).getText().isEmpty()) { + if (!textComponent.content().isEmpty()) { return false; } - List extra = component.getExtra(); - if (extra == null || extra.isEmpty()) { + List children = component.children(); + if (children.isEmpty()) { return false; } - return hasRootFormat(extra.get(0)); + return hasRootFormat(children.get(0)); } - public static String stringify(BaseComponent[] components) { - if (components == null) { + // TODO stringification methods? + public static String stringify(Component component) { + if (component == null) { return null; } - if (components.length == 0) { - return ""; - } - StringBuilder builder = new StringBuilder(128 * components.length); - if (hasRootFormat(components[0])) { - builder.append(RESET); + String output = stringifySub(component, null); + if (hasRootFormat(component)) { + output = RESET + output; } - for (BaseComponent component : components) { - if (component != null) { - builder.append(stringify(component)); - } - } - String output = builder.toString(); while (output.endsWith(RESET)) { output = output.substring(0, output.length() - RESET.length()); } @@ -120,132 +180,140 @@ public static String stringifyRGBSpigot(String hex) { hex = hexBuilder.toString(); StringBuilder outColor = new StringBuilder(); for (char c : hex.toCharArray()) { - outColor.append(org.bukkit.ChatColor.COLOR_CHAR).append(c); + outColor.append(LEGACY_SECTION).append(c); } return outColor.toString(); } - public static String stringify(BaseComponent component) { - return stringifySub(component, null); - } + // TODO stringification methods? +// public static String stringify(Component component) { +// return stringifySub(component, null); +// } - public static String stringifySub(BaseComponent component, ChatColor parentColor) { + public static String stringifySub(Component component, TextColor parentColor) { if (component == null) { return null; } StringBuilder builder = new StringBuilder(128); - ChatColor color = component.getColorRaw(); + TextColor color = component.color(); if (color == null) { color = parentColor; } if (color != null) { - builder.append(color); + if (color instanceof NamedTextColor namedTextColor) { + builder.append(LegacyColor.fromModern(namedTextColor)); + } + else { + builder.append(stringifyRGBSpigot(color.asHexString().substring(1))); + } } - if (component.isBold()) { - builder.append(ChatColor.BOLD); + if (component.hasDecoration(TextDecoration.BOLD)) { + builder.append(LegacyFormatting.BOLD); } - if (component.isItalic()) { - builder.append(ChatColor.ITALIC); + if (component.hasDecoration(TextDecoration.ITALIC)) { + builder.append(LegacyFormatting.ITALIC); } - if (component.isStrikethrough()) { - builder.append(ChatColor.STRIKETHROUGH); + if (component.hasDecoration(TextDecoration.STRIKETHROUGH)) { + builder.append(LegacyFormatting.STRIKETHROUGH); } - if (component.isUnderlined()) { - builder.append(ChatColor.UNDERLINE); + if (component.hasDecoration(TextDecoration.UNDERLINED)) { + builder.append(LegacyFormatting.UNDERLINE); } - if (component.isObfuscated()) { - builder.append(ChatColor.MAGIC); + if (component.hasDecoration(TextDecoration.OBFUSCATED)) { + builder.append(LegacyFormatting.OBFUSCATED); } - boolean hasFont = component.getFontRaw() != null; + boolean hasFont = component.font() != null; if (hasFont) { - builder.append(ChatColor.COLOR_CHAR).append("[font=").append(component.getFont()).append("]"); + builder.append(LEGACY_SECTION).append("[font=").append(component.font()).append("]"); } - boolean hasInsertion = component.getInsertion() != null; + boolean hasInsertion = component.insertion() != null; if (hasInsertion) { - builder.append(ChatColor.COLOR_CHAR).append("[insertion=").append(escape(component.getInsertion())).append("]"); + builder.append(LEGACY_SECTION).append("[insertion=").append(escape(component.insertion())).append("]"); } - boolean hasHover = component.getHoverEvent() != null; + boolean hasHover = component.hoverEvent() != null; if (hasHover) { - HoverEvent hover = component.getHoverEvent(); - builder.append(ChatColor.COLOR_CHAR).append("[hover=").append(hover.getAction().name()).append(";").append(escape(HoverFormatHelper.stringForHover(hover))).append("]"); + HoverEvent hover = component.hoverEvent(); + builder.append(LEGACY_SECTION).append("[hover=").append(hover.action()).append(";").append(escape(HoverFormatHelper.stringForHover(hover))).append("]"); } - boolean hasClick = component.getClickEvent() != null; + boolean hasClick = component.clickEvent() != null; if (hasClick) { - ClickEvent click = component.getClickEvent(); - builder.append(ChatColor.COLOR_CHAR).append("[click=").append(click.getAction().name()).append(";").append(escape(click.getValue())).append("]"); + ClickEvent click = component.clickEvent(); + // TODO modern click events + builder.append(LEGACY_SECTION).append("[click=").append(click.action().name()).append(";").append(escape(click.value())).append("]"); } - if (component instanceof TextComponent) { - builder.append(((TextComponent) component).getText()); + if (component instanceof TextComponent textComponent) { + builder.append(textComponent.content()); } else if (component instanceof TranslatableComponent translatableComponent) { MapTag map = new MapTag(); - map.putObject("key", new ElementTag(translatableComponent.getTranslate(), true)); - if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20) && translatableComponent.getFallback() != null) { - map.putObject("fallback", new ElementTag(translatableComponent.getFallback(), true)); + map.putObject("key", new ElementTag(translatableComponent.key(), true)); + if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20) && translatableComponent.fallback() != null) { + map.putObject("fallback", new ElementTag(translatableComponent.fallback(), true)); } - if (translatableComponent.getWith() != null) { - map.putObject("with", new ListTag(translatableComponent.getWith(), baseComponent -> new ElementTag(stringify(baseComponent), true))); + if (!translatableComponent.arguments().isEmpty()) { + map.putObject("with", new ListTag(translatableComponent.arguments(), argument -> new ElementTag(stringify(argument.asComponent()), true))); } - builder.append(ChatColor.COLOR_CHAR).append("[translate=").append(escape(map.savable())).append(']'); + builder.append(LEGACY_SECTION).append("[translate=").append(escape(map.savable())).append(']'); } else if (component instanceof SelectorComponent) { - builder.append(ChatColor.COLOR_CHAR).append("[selector=").append(escape(((SelectorComponent) component).getSelector())).append("]"); + // TODO separator + builder.append(LEGACY_SECTION).append("[selector=").append(escape(((SelectorComponent) component).pattern())).append("]"); } else if (component instanceof KeybindComponent) { - builder.append(ChatColor.COLOR_CHAR).append("[keybind=").append(escape(((KeybindComponent) component).getKeybind())).append("]"); + builder.append(LEGACY_SECTION).append("[keybind=").append(escape(((KeybindComponent) component).keybind())).append("]"); } else if (component instanceof ScoreComponent) { - builder.append(ChatColor.COLOR_CHAR).append("[score=").append(escape(((ScoreComponent) component).getName())) - .append(";").append(escape(((ScoreComponent) component).getObjective())) - .append(";").append(escape(((ScoreComponent) component).getValue())).append("]"); - } - List after = component.getExtra(); - if (after != null) { - for (BaseComponent afterComponent : after) { - builder.append(stringifySub(afterComponent, color)); - } + // TODO value is deprecated + builder.append(LEGACY_SECTION).append("[score=").append(escape(((ScoreComponent) component).name())) + .append(";").append(escape(((ScoreComponent) component).objective())) + .append(";").append(escape(((ScoreComponent) component).value())).append("]"); + } + for (Component afterComponent : component.children()) { + builder.append(stringifySub(afterComponent, color)); } if (hasClick) { - builder.append(ChatColor.COLOR_CHAR + "[/click]"); + builder.append(LEGACY_SECTION + "[/click]"); } if (hasHover) { - builder.append(ChatColor.COLOR_CHAR + "[/hover]"); + builder.append(LEGACY_SECTION + "[/hover]"); } if (hasInsertion) { - builder.append(ChatColor.COLOR_CHAR + "[/insertion]"); + builder.append(LEGACY_SECTION + "[/insertion]"); } if (hasFont) { - builder.append(ChatColor.COLOR_CHAR + "[reset=font]"); + builder.append(LEGACY_SECTION + "[reset=font]"); } builder.append(RESET); String output = builder.toString(); return cleanRedundantCodes(output); } - public static final String RESET = ChatColor.RESET.toString(), POSSIBLE_RESET_PREFIX = RESET + ChatColor.COLOR_CHAR; + public static final String RESET = LegacyFormatting.RESET.toString(), POSSIBLE_RESET_PREFIX = RESET + LEGACY_SECTION; - private static Boolean procBool(Boolean input, boolean optimize) { - if (input == null) { - return null; + private static void copyDecoration(TextDecoration decoration, StyleGetter origin, StyleSetter destination, boolean optimize) { + TextDecoration.State state = origin.decoration(decoration); + if (state == TextDecoration.State.NOT_SET) { + return; } - if (optimize) { - return input ? true : null; + if (optimize && state == TextDecoration.State.FALSE) { + return; } - return input; + destination.decoration(decoration, state); } - public static TextComponent copyFormatToNewText(TextComponent last, boolean optimize) { - TextComponent toRet = new TextComponent(); - toRet.setObfuscated(procBool(last.isObfuscatedRaw(), optimize)); - toRet.setBold(procBool(last.isBoldRaw(), optimize)); - toRet.setStrikethrough(procBool(last.isStrikethroughRaw(), optimize)); - toRet.setUnderlined(procBool(last.isUnderlinedRaw(), optimize)); - toRet.setItalic(procBool(last.isItalicRaw(), optimize)); - toRet.setColor(last.getColorRaw()); + public static TextComponent.Builder copyFormatToNewText(TextComponent.Builder last, boolean minimize) { + TextComponent.Builder toRet = Component.text(); + Component lastBuilt = last.build(); + copyDecoration(TextDecoration.OBFUSCATED, lastBuilt, toRet, minimize); + copyDecoration(TextDecoration.BOLD, lastBuilt, toRet, minimize); + copyDecoration(TextDecoration.STRIKETHROUGH, lastBuilt, toRet, minimize); + copyDecoration(TextDecoration.UNDERLINED, lastBuilt, toRet, minimize); + copyDecoration(TextDecoration.ITALIC, lastBuilt, toRet, minimize); + toRet.color(lastBuilt.color()); return toRet; } - public static BaseComponent[] parse(String str, ChatColor baseColor) { + public static Component parse(String str, TextColor baseColor) { if (str == null) { return null; } @@ -254,7 +322,7 @@ public static BaseComponent[] parse(String str, ChatColor baseColor) { public static int findNextNormalColorSymbol(String base, int startAt) { while (true) { - int next = base.indexOf(ChatColor.COLOR_CHAR, startAt); + int next = base.indexOf(LEGACY_SECTION, startAt); if (next == -1 || next + 1 >= base.length()) { return -1; } @@ -269,7 +337,7 @@ public static int findNextNormalColorSymbol(String base, int startAt) { public static int findEndIndexFor(String base, String startSymbol, String endSymbol, int startAt) { int layers = 1; while (true) { - int next = base.indexOf(ChatColor.COLOR_CHAR, startAt); + int next = base.indexOf(LEGACY_SECTION, startAt); if (next == -1) { return -1; } @@ -304,7 +372,7 @@ public static int findEndIndexFor(String base, String type, int startAt) { public static AsciiMatcher colorCodeInvalidator = new AsciiMatcher(HEX + "rRxX"); // Any code that can invalidate the colors above public static String cleanRedundantCodes(String str) { - int index = str.indexOf(ChatColor.COLOR_CHAR); + int index = str.indexOf(LEGACY_SECTION); if (index == -1) { return str; } @@ -319,10 +387,10 @@ public static String cleanRedundantCodes(String str) { char symbol = str.charAt(index + 1); if (allowedCharCodes.isMatch(symbol)) { if (symbol == 'x' || symbol == 'X') { // Skip entire hex block - index = str.indexOf(ChatColor.COLOR_CHAR, index + 14); + index = str.indexOf(LEGACY_SECTION, index + 14); continue; } - int nextIndex = str.indexOf(ChatColor.COLOR_CHAR, index + 1); + int nextIndex = str.indexOf(LEGACY_SECTION, index + 1); if (colorCodesOrReset.isMatch(symbol) && nextIndex == index + 2 && nextIndex + 1 < str.length()) { char nextSymbol = str.charAt(nextIndex + 1); if (colorCodeInvalidator.isMatch(nextSymbol)) { @@ -332,38 +400,40 @@ public static String cleanRedundantCodes(String str) { } } } - index = str.indexOf(ChatColor.COLOR_CHAR, index + 1); + index = str.indexOf(LEGACY_SECTION, index + 1); } output.append(str, start, str.length()); return output.toString(); } - public static TextComponent getCleanRef() { - TextComponent reference = new TextComponent(); - reference.setBold(false); - reference.setItalic(false); - reference.setStrikethrough(false); - reference.setUnderlined(false); - reference.setObfuscated(false); - return reference; + public static final Style CLEAN_BASE_STYLE = Style.style() + .decoration(TextDecoration.BOLD, false) + .decoration(TextDecoration.ITALIC, false) + .decoration(TextDecoration.STRIKETHROUGH, false) + .decoration(TextDecoration.UNDERLINED, false) + .decoration(TextDecoration.OBFUSCATED, false) + .build(); + + public static TextComponent.Builder getCleanRef() { + return Component.text().style(CLEAN_BASE_STYLE); } - public static BaseComponent[] parseSimpleColorsOnly(String str) { - TextComponent root = new TextComponent(); - int firstChar = str.indexOf(ChatColor.COLOR_CHAR); + public static Component parseSimpleColorsOnly(String str) { + TextComponent.Builder root = Component.text(); + int firstChar = str.indexOf(LEGACY_SECTION); int lastStart = 0; if (firstChar > 0) { - root.addExtra(new TextComponent(str.substring(0, firstChar))); + root.append(Component.text(str.substring(0, firstChar))); lastStart = firstChar; } - TextComponent nextText = new TextComponent(); + TextComponent.Builder nextText = Component.text(); while (firstChar != -1 && firstChar + 1 < str.length()) { char c = str.charAt(firstChar + 1); if (allowedCharCodes.isMatch(c)) { if (c == 'r' || c == 'R') { - nextText.setText(str.substring(lastStart, firstChar)); - if (!nextText.getText().isEmpty()) { - root.addExtra(nextText); + nextText.content(str.substring(lastStart, firstChar)); + if (!nextText.content().isEmpty()) { + root.append(nextText); } nextText = getCleanRef(); lastStart = firstChar + 2; @@ -372,7 +442,7 @@ else if (c == 'X' || c == 'x' && firstChar + 13 < str.length()) { StringBuilder color = new StringBuilder(12); color.append("#"); for (int i = 1; i <= 6; i++) { - if (str.charAt(firstChar + i * 2) != ChatColor.COLOR_CHAR) { + if (str.charAt(firstChar + i * 2) != LEGACY_SECTION) { color = null; break; } @@ -384,59 +454,59 @@ else if (c == 'X' || c == 'x' && firstChar + 13 < str.length()) { color.append(hexChar); } if (color != null) { - nextText.setText(str.substring(lastStart, firstChar)); - if (!nextText.getText().isEmpty()) { - root.addExtra(nextText); + nextText.content(str.substring(lastStart, firstChar)); + if (!nextText.content().isEmpty()) { + root.append(nextText); } nextText = getCleanRef(); - nextText.setColor(ChatColor.of(CoreUtilities.toUpperCase(color.toString()))); + nextText.color(TextColor.fromHexString(CoreUtilities.toUpperCase(color.toString()))); firstChar += 12; lastStart = firstChar + 2; } } else if (colorCodesOrReset.isMatch(c)) { - nextText.setText(str.substring(lastStart, firstChar)); - if (!nextText.getText().isEmpty()) { - root.addExtra(nextText); + nextText.content(str.substring(lastStart, firstChar)); + if (!nextText.content().isEmpty()) { + root.append(nextText); } nextText = getCleanRef(); - nextText.setColor(ChatColor.getByChar(c)); + nextText.color(LegacyComponentSerializer.parseChar(c).color()); lastStart = firstChar + 2; } else { // format code - nextText.setText(str.substring(lastStart, firstChar)); - if (!nextText.getText().isEmpty()) { - root.addExtra(nextText); + nextText.content(str.substring(lastStart, firstChar)); + if (!nextText.content().isEmpty()) { + root.append(nextText); } nextText = copyFormatToNewText(nextText, false); if (c == 'k' || c == 'K') { - nextText.setObfuscated(true); + nextText.decoration(TextDecoration.OBFUSCATED, true); } else if (c == 'l' || c == 'L') { - nextText.setBold(true); + nextText.decoration(TextDecoration.BOLD, true); } else if (c == 'm' || c == 'M') { - nextText.setStrikethrough(true); + nextText.decoration(TextDecoration.STRIKETHROUGH, true); } else if (c == 'n' || c == 'N') { - nextText.setUnderlined(true); + nextText.decoration(TextDecoration.UNDERLINED, true); } else if (c == 'o' || c == 'O') { - nextText.setItalic(true); + nextText.decoration(TextDecoration.ITALIC, true); } lastStart = firstChar + 2; } } - firstChar = str.indexOf(ChatColor.COLOR_CHAR, firstChar + 1); + firstChar = str.indexOf(LEGACY_SECTION, firstChar + 1); } if (lastStart < str.length()) { - nextText.setText(str.substring(lastStart)); - root.addExtra(nextText); + nextText.content(str.substring(lastStart)); + root.append(nextText); } - return new BaseComponent[] { root }; + return root.build(); } - public static BaseComponent[] parse(String str, ChatColor baseColor, boolean cleanBase) { + public static Component parse(String str, TextColor baseColor, boolean cleanBase) { if (str == null) { return null; } @@ -446,100 +516,102 @@ public static BaseComponent[] parse(String str, ChatColor baseColor, boolean cle catch (Throwable ex) { Debug.echoError(ex); } - return new BaseComponent[]{new TextComponent(str)}; + return Component.text(str); } - private static BaseComponent parseTranslatable(String str, ChatColor baseColor, boolean optimize) { + // TODO cleanup handling here? + private static Component parseTranslatable(String str, TextColor baseColor, boolean optimize) { if (!str.startsWith("map@")) { List innardParts = CoreUtilities.split(str, ';'); - TranslatableComponent component = new TranslatableComponent(unescape(innardParts.get(0))); + String translation = unescape(innardParts.get(0)); + if (innardParts.size() == 1) { + return Component.translatable(translation); + } + List args = new ArrayList<>(innardParts.size() - 1); for (int i = 1; i < innardParts.size(); i++) { - for (BaseComponent subComponent : parseInternal(unescape(innardParts.get(i)), baseColor, false, optimize)) { - component.addWith(subComponent); - } + args.add(parseInternal(unescape(innardParts.get(i)), baseColor, false, optimize)); } - return component; + return Component.translatable(translation, args); } MapTag map = MapTag.valueOf(unescape(str), CoreUtilities.noDebugContext); if (map == null) { - return new TextComponent(str); + return Component.text(str); } ElementTag translationKey = map.getElement("key"); if (translationKey == null) { - return new TextComponent(str); - } - TranslatableComponent component = new TranslatableComponent(translationKey.asString()); - ElementTag fallback = map.getElement("fallback"); - if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20) && fallback != null) { - component.setFallback(fallback.asString()); + return Component.text(str); } ListTag withList = map.getObjectAs("with", ListTag.class, CoreUtilities.noDebugContext); + List args; if (withList != null) { + args = new ArrayList<>(withList.size()); for (String with : withList) { - for (BaseComponent withComponent : parseInternal(with, baseColor, false, optimize)) { - component.addWith(withComponent); - } + args.add(parseInternal(with, baseColor, false, optimize)); } } - return component; + else { + args = List.of(); + } + if (NMSHandler.getVersion().isAtMost(NMSVersion.v1_19)) { + return Component.translatable(translationKey.asString(), args); + } + ElementTag fallback = map.getElement("fallback"); + return Component.translatable(translationKey.asString(), fallback != null ? fallback.asString() : null, args, List.of()); } - public static BaseComponent[] parseInternal(String str, ChatColor baseColor, boolean cleanBase, boolean optimize) { + public static Component parseInternal(String str, TextColor baseColor, boolean cleanBase, boolean optimize) { str = CoreUtilities.clearNBSPs(str); - int firstChar = str.indexOf(ChatColor.COLOR_CHAR); + int firstChar = str.indexOf(LEGACY_SECTION); if (firstChar == -1) { if (str.contains("://")) { firstChar = 0; } else { - TextComponent base = new TextComponent(); - base.addExtra(new TextComponent(str)); // This is for compat with how Spigot does parsing of plaintext. - return new BaseComponent[]{base}; + // This is for compat with how Spigot does parsing of plaintext. + return Component.textOfChildren(Component.text(str)); } } str = cleanRedundantCodes(str); if (cleanBase && str.length() < 512) { - if (!str.contains(ChatColor.COLOR_CHAR + "[") && !str.contains("://")) { + if (!str.contains(LEGACY_SECTION + "[") && !str.contains("://")) { return parseSimpleColorsOnly(str); } - // Ensure compat with certain weird vanilla translate strings. - if (str.startsWith(ChatColor.COLOR_CHAR + "[translate=") && str.indexOf(']') == str.length() - 1) { - return new BaseComponent[] {parseTranslatable(str.substring("&[translate=".length(), str.length() - 1), baseColor, optimize)}; + // Ensure compact with certain weird vanilla translate strings. + if (str.startsWith(LEGACY_SECTION + "[translate=") && str.indexOf(']') == str.length() - 1) { + return parseTranslatable(str.substring("&[translate=".length(), str.length() - 1), baseColor, optimize); } - if (str.length() > 3 && str.startsWith((ChatColor.COLOR_CHAR + "")) && hexMatcher.isMatch(str.charAt(1)) - && str.startsWith(ChatColor.COLOR_CHAR + "[translate=", 2) && str.indexOf(']') == str.length() - 1) { // eg "&6&[translate=block.minecraft.ominous_banner]" - BaseComponent component = parseTranslatable(str.substring("&[translate=".length() + 2, str.length() - 1), baseColor, optimize); - component.setColor(ChatColor.getByChar(str.charAt(1))); - return new BaseComponent[] {component}; + if (str.length() > 3 && str.startsWith((LEGACY_SECTION + "")) && hexMatcher.isMatch(str.charAt(1)) + && str.startsWith(LEGACY_SECTION + "[translate=", 2) && str.indexOf(']') == str.length() - 1) { // eg "&6&[translate=block.minecraft.ominous_banner]" + Component component = parseTranslatable(str.substring("&[translate=".length() + 2, str.length() - 1), baseColor, optimize); + component.color(LegacyComponentSerializer.parseChar(str.charAt(1)).color()); + return component; } } if (!optimize) { - optimize = str.contains(ChatColor.COLOR_CHAR + "[optimize=true]"); + optimize = str.contains(LEGACY_SECTION + "[optimize=true]"); } - TextComponent root = new TextComponent(); - TextComponent base = new TextComponent(); + TextComponent.Builder root = Component.text(); + TextComponent.Builder base; if (cleanBase && !optimize) { - base.setBold(false); - base.setItalic(false); - base.setStrikethrough(false); - base.setUnderlined(false); - base.setObfuscated(false); - base.setColor(baseColor); + base = getCleanRef(); + base.color(baseColor); if (firstChar > 0) { - root.addExtra(new TextComponent(str.substring(0, firstChar))); + root.append(Component.text(str.substring(0, firstChar))); } } else { - base.setText(str.substring(0, firstChar)); + base = Component.text(); + base.content(str.substring(0, firstChar)); } - root.addExtra(base); + // TODO immutable + root.append(base); str = str.substring(firstChar); char[] chars = str.toCharArray(); int started = 0; - TextComponent nextText = new TextComponent(); - TextComponent lastText; + TextComponent.Builder nextText = Component.text(); + TextComponent.Builder lastText; for (int i = 0; i < chars.length; i++) { - if (chars[i] == ChatColor.COLOR_CHAR && i + 1 < chars.length) { + if (chars[i] == LEGACY_SECTION && i + 1 < chars.length) { char code = chars[i + 1]; if (!allowedCharCodes.isMatch(code)) { continue; @@ -555,39 +627,38 @@ public static BaseComponent[] parseInternal(String str, ChatColor baseColor, boo innardParts.remove(0); String innardType = CoreUtilities.toLowerCase(innardBase.get(0)); if (innardBase.size() == 2) { - nextText.setText(nextText.getText() + str.substring(started, i)); - base.addExtra(nextText); + nextText.content(nextText.content() + str.substring(started, i)); + base.append(nextText); lastText = nextText; nextText = copyFormatToNewText(lastText, optimize); - nextText.setText(""); + nextText.content(""); if (innardType.equals("score") && innardParts.size() == 2) { - ScoreComponent component = new ScoreComponent(unescape(innardBase.get(1)), unescape(innardParts.get(0)), unescape(innardParts.get(1))); - lastText.addExtra(component); + // TODO value is no longer a thing? + ScoreComponent component = Component.score(unescape(innardBase.get(1)), unescape(innardParts.get(0)), unescape(innardParts.get(1))); + lastText.append(component); } else if (innardType.equals("keybind") && Utilities.matchesNamespacedKeyButCaseInsensitive(innardBase.get(1))) { - KeybindComponent component = new KeybindComponent(); - component.setKeybind(unescape(innardBase.get(1))); - lastText.addExtra(component); + KeybindComponent component = Component.keybind(unescape(innardBase.get(1))); + lastText.append(component); } else if (innardType.equals("selector")) { - SelectorComponent component = new SelectorComponent(unescape(innardBase.get(1))); - lastText.addExtra(component); + SelectorComponent component = Component.selector(unescape(innardBase.get(1))); + lastText.append(component); } else if (innardType.equals("translate")) { - lastText.addExtra(parseTranslatable(innards.substring("translate=".length()), baseColor, optimize)); + lastText.append(parseTranslatable(innards.substring("translate=".length()), baseColor, optimize)); } else if (innardType.equals("click") && innardParts.size() == 1) { int endIndex = findEndIndexFor(str, "click", endBracket); if (endIndex == -1) { continue; } - TextComponent clickableText = new TextComponent(); + TextComponent.Builder clickableText = Component.text(); ClickEvent.Action action = ElementTag.asEnum(ClickEvent.Action.class, innardBase.get(1)); - clickableText.setClickEvent(new ClickEvent(action == null ? ClickEvent.Action.SUGGEST_COMMAND : action, unescape(innardParts.get(0)))); - for (BaseComponent subComponent : parseInternal(str.substring(endBracket + 1, endIndex), baseColor, false, optimize)) { - clickableText.addExtra(subComponent); - } - lastText.addExtra(clickableText); + // TODO click event types + clickableText.clickEvent(ClickEvent.clickEvent(action == null ? ClickEvent.Action.SUGGEST_COMMAND : action, unescape(innardParts.get(0)))); + clickableText.append(parseInternal(str.substring(endBracket + 1, endIndex), baseColor, false, optimize)); + lastText.append(clickableText); endBracket = endIndex + "&[/click".length(); } else if (innardType.equals("hover")) { @@ -595,68 +666,66 @@ else if (innardType.equals("hover")) { if (endIndex == -1) { continue; } - TextComponent hoverableText = new TextComponent(); - HoverEvent.Action action = ElementTag.asEnum(HoverEvent.Action.class, innardBase.get(1)); + TextComponent.Builder hoverableText = Component.text(); + HoverEvent.Action action = ElementTag.asEnum(HoverEvent.Action.class, innardBase.get(1)); if (HoverFormatHelper.processHoverInput(action == null ? HoverEvent.Action.SHOW_TEXT : action, hoverableText, innardParts.get(0))) { continue; } - for (BaseComponent subComponent : parseInternal(str.substring(endBracket + 1, endIndex), baseColor, false, optimize)) { - hoverableText.addExtra(subComponent); - } - lastText.addExtra(hoverableText); + hoverableText.append(parseInternal(str.substring(endBracket + 1, endIndex), baseColor, false, optimize)); + lastText.append(hoverableText); endBracket = endIndex + "&[/hover".length(); } else if (innardType.equals("insertion")) { - int endIndex = str.indexOf(ChatColor.COLOR_CHAR + "[/insertion]", i); - int backupEndIndex = str.indexOf(ChatColor.COLOR_CHAR + "[insertion=", i + 5); + int endIndex = str.indexOf(LEGACY_SECTION + "[/insertion]", i); + int backupEndIndex = str.indexOf(LEGACY_SECTION + "[insertion=", i + 5); if (backupEndIndex > 0 && backupEndIndex < endIndex) { endIndex = backupEndIndex; } if (endIndex == -1) { continue; } - TextComponent insertableText = new TextComponent(); - insertableText.setInsertion(unescape(innardBase.get(1))); - for (BaseComponent subComponent : parseInternal(str.substring(endBracket + 1, endIndex), baseColor, false, optimize)) { - insertableText.addExtra(subComponent); - } - lastText.addExtra(insertableText); + TextComponent.Builder insertableText = Component.text(); + insertableText.insertion(unescape(innardBase.get(1))); + insertableText.append(parseInternal(str.substring(endBracket + 1, endIndex), baseColor, false, optimize)); + lastText.append(insertableText); endBracket = endIndex + "&[/insertion".length(); } else if (innardType.equals("reset")) { if (innardBase.get(1).length() == 1) { char subCode = innardBase.get(1).charAt(0); if (subCode == 'k' || subCode == 'K') { - nextText.setObfuscated(false); + nextText.decoration(TextDecoration.OBFUSCATED, false); } else if (subCode == 'l' || subCode == 'L') { - nextText.setBold(false); + nextText.decoration(TextDecoration.BOLD, false); } else if (subCode == 'm' || subCode == 'M') { - nextText.setStrikethrough(false); + nextText.decoration(TextDecoration.STRIKETHROUGH, false); } else if (subCode == 'n' || subCode == 'N') { - nextText.setUnderlined(false); + nextText.decoration(TextDecoration.UNDERLINED, false); } else if (subCode == 'o' || subCode == 'O') { - nextText.setItalic(false); + nextText.decoration(TextDecoration.ITALIC, false); } } else if (innardBase.get(1).equals("font")) { - nextText.setFont(base.getFont()); + // TODO builder + nextText.font(base.build().font()); } else { - nextText.setColor(base.getColor()); + // TODO builder + nextText.color(base.build().color()); } } else if (innardType.equals("color")) { String colorChar = innardBase.get(1); - ChatColor color = null; + TextColor color = null; if (colorChar.length() == 1) { - color = ChatColor.getByChar(colorChar.charAt(0)); + color = LegacyComponentSerializer.parseChar(colorChar.charAt(0)).color(); } else if (colorChar.length() == 7) { - color = ChatColor.of(CoreUtilities.toUpperCase(colorChar)); + color = TextColor.fromHexString(CoreUtilities.toUpperCase(colorChar)); } else if (CoreConfiguration.debugVerbose) { Debug.echoError("Text parse issue: cannot interpret color '" + innardBase.get(1) + "'."); @@ -664,15 +733,13 @@ else if (CoreConfiguration.debugVerbose) { if (color != null) { int endIndex = findEndIndexFor(str, "[color=", "[reset=color]", endBracket); if (endIndex == -1) { - nextText.setColor(color); + nextText.color(color); } else { - TextComponent colorText = new TextComponent(); - colorText.setColor(color); - for (BaseComponent subComponent : parseInternal(str.substring(endBracket + 1, endIndex), color, false, optimize)) { - colorText.addExtra(subComponent); - } - lastText.addExtra(colorText); + TextComponent.Builder colorText = Component.text(); + colorText.color(color); + colorText.append(parseInternal(str.substring(endBracket + 1, endIndex), color, false, optimize)); + lastText.append(colorText); endBracket = endIndex + "&[reset=color".length(); } } @@ -693,24 +760,20 @@ else if (innardType.equals("gradient") && innardParts.size() == 2) { endIndex = str.length(); } String gradientText = BukkitElementExtensions.doGradient(str.substring(endBracket + 1, endIndex), fromColor, toColor, styleEnum); - for (BaseComponent subComponent : parseInternal(gradientText, baseColor, false, optimize)) { - lastText.addExtra(subComponent); - } + lastText.append(parseInternal(gradientText, baseColor, false, optimize)); endBracket = endIndex - 1; } } else if (innardType.equals("font") && Utilities.matchesNamespacedKey(innardBase.get(1))) { int endIndex = findEndIndexFor(str, "[font=", "[reset=font]", endBracket); if (endIndex == -1) { - nextText.setFont(innardBase.get(1)); + nextText.font(Key.key(innardBase.get(1))); } else { - TextComponent fontText = new TextComponent(); - fontText.setFont(innardBase.get(1)); - for (BaseComponent subComponent : parseInternal(str.substring(endBracket + 1, endIndex), baseColor, false, optimize)) { - fontText.addExtra(subComponent); - } - lastText.addExtra(fontText); + TextComponent.Builder fontText = Component.text(); + fontText.font(Key.key(innardBase.get(1))); + fontText.append(parseInternal(str.substring(endBracket + 1, endIndex), baseColor, false, optimize)); + lastText.append(fontText); endBracket = endIndex + "&[reset=font".length(); } } @@ -728,20 +791,20 @@ else if (innardType.equals("optimize")) { continue; } else if (code == 'r' || code == 'R') { - nextText.setText(nextText.getText() + str.substring(started, i)); - if (!nextText.getText().isEmpty()) { - base.addExtra(nextText); + nextText.content(nextText.content() + str.substring(started, i)); + if (!nextText.content().isEmpty()) { + base.append(nextText); } - nextText = new TextComponent(); - nextText.setColor(baseColor); + nextText = Component.text(); + nextText.color(baseColor); } else if (colorCodesOrReset.isMatch(code)) { - nextText.setText(nextText.getText() + str.substring(started, i)); - if (!nextText.getText().isEmpty()) { - base.addExtra(nextText); + nextText.content(nextText.content() + str.substring(started, i)); + if (!nextText.content().isEmpty()) { + base.append(nextText); } - nextText = new TextComponent(); - nextText.setColor(ChatColor.getByChar(code)); + nextText = Component.text(); + nextText.color(LegacyComponentSerializer.parseChar(code).color()); } else if (code == 'x') { if (i + 13 >= chars.length) { @@ -750,7 +813,7 @@ else if (code == 'x') { StringBuilder color = new StringBuilder(12); color.append("#"); for (int c = 1; c <= 6; c++) { - if (chars[i + c * 2] != ChatColor.COLOR_CHAR) { + if (chars[i + c * 2] != LEGACY_SECTION) { color = null; break; } @@ -764,36 +827,36 @@ else if (code == 'x') { if (color == null) { continue; } - nextText.setText(nextText.getText() + str.substring(started, i)); - if (!nextText.getText().isEmpty()) { - base.addExtra(nextText); + nextText.content(nextText.content() + str.substring(started, i)); + if (!nextText.content().isEmpty()) { + base.append(nextText); } - nextText = new TextComponent(); - nextText.setColor(ChatColor.of(CoreUtilities.toUpperCase(color.toString()))); + nextText = Component.text(); + nextText.color(TextColor.fromHexString(CoreUtilities.toUpperCase(color.toString()))); i += 13; started = i + 1; continue; } else { - nextText.setText(nextText.getText() + str.substring(started, i)); - if (!nextText.getText().isEmpty()) { - base.addExtra(nextText); + nextText.content(nextText.content() + str.substring(started, i)); + if (!nextText.content().isEmpty()) { + base.append(nextText); } nextText = copyFormatToNewText(nextText, optimize); if (code == 'k' || code == 'K') { - nextText.setObfuscated(true); + nextText.decoration(TextDecoration.OBFUSCATED, true); } else if (code == 'l' || code == 'L') { - nextText.setBold(true); + nextText.decoration(TextDecoration.BOLD, true); } else if (code == 'm' || code == 'M') { - nextText.setStrikethrough(true); + nextText.decoration(TextDecoration.STRIKETHROUGH, true); } else if (code == 'n' || code == 'N') { - nextText.setUnderlined(true); + nextText.decoration(TextDecoration.UNDERLINED, true); } else if (code == 'o' || code == 'O') { - nextText.setItalic(true); + nextText.decoration(TextDecoration.ITALIC, true); } } i++; @@ -802,34 +865,35 @@ else if (code == 'o' || code == 'O') { else if (i + "https://a.".length() < chars.length && chars[i] == 'h' && chars[i + 1] == 't' && chars[i + 2] == 't' && chars[i + 3] == 'p') { String subStr = str.substring(i, i + "https://a.".length()); if (subStr.startsWith("https://") || subStr.startsWith("http://")) { - int nextSpace = CoreUtilities.indexOfAny(str, i, ' ', '\t', '\n', ChatColor.COLOR_CHAR); + int nextSpace = CoreUtilities.indexOfAny(str, i, ' ', '\t', '\n', LEGACY_SECTION); if (nextSpace == -1) { nextSpace = str.length(); } String url = str.substring(i, nextSpace); - nextText.setText(nextText.getText() + str.substring(started, i)); - base.addExtra(nextText); + nextText.content(nextText.content() + str.substring(started, i)); + base.append(nextText); lastText = nextText; - nextText = new TextComponent(lastText); - nextText.setText(""); - TextComponent clickableText = new TextComponent(url); - clickableText.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, url)); - lastText.addExtra(clickableText); + // TODO builder copying + nextText = lastText.build().toBuilder(); + nextText.content(""); + TextComponent.Builder clickableText = Component.text().content(url); + clickableText.clickEvent(ClickEvent.openUrl(url)); + lastText.append(clickableText); i = nextSpace - 1; started = nextSpace; continue; } } } - nextText.setText(nextText.getText() + str.substring(started)); - if (!nextText.getText().isEmpty()) { - base.addExtra(nextText); + nextText.content(nextText.content() + str.substring(started)); + if (!nextText.content().isEmpty()) { + base.append(nextText); } - return new BaseComponent[] { cleanBase && !optimize ? root : base }; + return cleanBase && !optimize ? root.build() : base.build(); } public static int indexOfLastColorBlockStart(String text) { - int result = text.lastIndexOf(ChatColor.COLOR_CHAR + "["); + int result = text.lastIndexOf(LEGACY_SECTION + "["); if (result == -1 || text.indexOf(']', result + 2) != -1) { return -1; } @@ -862,34 +926,4 @@ public static String bukkitSafeDebugTrimming(String message) { } return message; } - - public static Gson getBungeeGson() { - if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21)) { - return VersionedComponentSerializer.forVersion(ChatVersion.V1_21_5).getGson(); - } - else { - return ReflectionHelper.getFieldValue(ComponentSerializer.class, "gson", null); - } - } - - static { - // Explicitly before initializing vanillaStyleSpigotComponentGSON - HoverFormatHelper.tryInitializeItemHoverFix(); - } - - public static final Gson vanillaStyleSpigotComponentGSON = getBungeeGson().newBuilder().disableHtmlEscaping().create(); - - public static String componentToJson(BaseComponent[] components) { - if (components.length == 1) { - return vanillaStyleSpigotComponentGSON.toJson(components[0]); - } - return vanillaStyleSpigotComponentGSON.toJson(new TextComponent(components)); - } - - public static BaseComponent[] parseJson(String json) { - if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21)) { - return VersionedComponentSerializer.forVersion(ChatVersion.V1_21_5).parse(json); - } - return ComponentSerializer.parse(json); - } } diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/HoverFormatHelper.java b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/HoverFormatHelper.java index fc8a52e3ca..9fae8cd356 100644 --- a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/HoverFormatHelper.java +++ b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/HoverFormatHelper.java @@ -4,47 +4,34 @@ import com.denizenscript.denizen.nms.NMSVersion; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.objects.ItemTag; -import com.denizenscript.denizen.utilities.FormattedTextHelper; -import com.denizenscript.denizen.utilities.PaperAPITools; -import com.denizenscript.denizen.utilities.Utilities; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.objects.core.MapTag; import com.denizenscript.denizencore.tags.Attribute; import com.denizenscript.denizencore.utilities.CoreUtilities; -import com.denizenscript.denizencore.utilities.ReflectionHelper; import com.denizenscript.denizencore.utilities.debugging.Debug; -import com.google.gson.*; -import net.md_5.bungee.api.ChatColor; -import net.md_5.bungee.api.chat.BaseComponent; -import net.md_5.bungee.api.chat.HoverEvent; -import net.md_5.bungee.api.chat.TextComponent; -import net.md_5.bungee.api.chat.hover.content.*; -import net.md_5.bungee.chat.ChatVersion; -import net.md_5.bungee.chat.ComponentSerializer; -import net.md_5.bungee.chat.VersionedComponentSerializer; +import net.kyori.adventure.key.Key; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.TextComponent; +import net.kyori.adventure.text.event.HoverEvent; +import net.kyori.adventure.text.event.HoverEventSource; +import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.Bukkit; import org.bukkit.Registry; import org.bukkit.inventory.ItemStack; -import java.lang.reflect.Type; import java.util.UUID; public class HoverFormatHelper { - public static boolean processHoverInput(HoverEvent.Action action, TextComponent hoverableText, String input) { - Content content; + public static boolean processHoverInput(HoverEvent.Action action, TextComponent.Builder hoverableText, String input) { + HoverEventSource content; if (action == HoverEvent.Action.SHOW_ITEM) { ItemTag item = ItemTag.valueOf(com.denizenscript.denizen.utilities.FormattedTextHelper.unescape(input), CoreUtilities.noDebugContext); if (item == null) { return true; } - if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20)) { - content = new com.denizenscript.denizen.utilities.HoverFormatHelper.FixedItemHover(item.getBukkitMaterial().getKey().toString(), item.getAmount(), NMSHandler.itemHelper.getRawHoverComponentsJson(item.getItemStack())); - } - else { - content = new Item(item.getBukkitMaterial().getKey().toString(), item.getAmount(), net.md_5.bungee.api.chat.ItemTag.ofNbt(NMSHandler.itemHelper.getLegacyHoverNbt(item))); - } + content = item.getItemStack(); } else if (action == HoverEvent.Action.SHOW_ENTITY) { String rawInput = com.denizenscript.denizen.utilities.FormattedTextHelper.unescape(input); @@ -59,183 +46,98 @@ else if (action == HoverEvent.Action.SHOW_ENTITY) { if (entityHoverData == null) { return true; } - ElementTag uuid = entityHoverData.getElement("uuid"); + ElementTag uuidElement = entityHoverData.getElement("uuid"); + if (uuidElement == null) { + return true; + } + UUID uuid = CoreUtilities.tryParseUUID(uuidElement.asString()); if (uuid == null) { return true; } ElementTag type = entityHoverData.getElement("type"); + if (type == null) { + return true; + } ElementTag rawName = entityHoverData.getElement("name"); - BaseComponent name = rawName != null ? new TextComponent(com.denizenscript.denizen.utilities.FormattedTextHelper.parse(rawName.asString(), ChatColor.WHITE)) : null; - content = new Entity(type != null ? type.asString() : null, uuid.asString(), name); + Component name = rawName != null ? FormattedTextHelper.parse(rawName.asString(), NamedTextColor.WHITE) : null; + content = HoverEvent.showEntity(Key.key(type.asString()), uuid, name); } } else { - content = new Text(com.denizenscript.denizen.utilities.FormattedTextHelper.parse(com.denizenscript.denizen.utilities.FormattedTextHelper.unescape(input), ChatColor.WHITE)); + content = FormattedTextHelper.parse(FormattedTextHelper.unescape(input), NamedTextColor.WHITE); } - hoverableText.setHoverEvent(new HoverEvent(action, content)); + hoverableText.hoverEvent(content); return false; } - public static String stringForHover(HoverEvent hover) { - if (hover.getContents().isEmpty()) { - return ""; + public static String stringForHover(HoverEvent hover) { + if (hover.value() instanceof Component textHover) { + return FormattedTextHelper.stringify(textHover); } - Content contentObject = hover.getContents().get(0); - if (contentObject instanceof Text textHover) { - Object value = textHover.getValue(); - if (value instanceof BaseComponent[] componentsValue) { - return com.denizenscript.denizen.utilities.FormattedTextHelper.stringify(componentsValue); - } - else { - return value.toString(); - } - } - else if (contentObject instanceof Item itemHover) { - ItemStack item = new ItemStack(Registry.MATERIAL.get(Utilities.parseNamespacedKey(itemHover.getId())), itemHover.getCount() == -1 ? 1 : itemHover.getCount()); - if (itemHover instanceof com.denizenscript.denizen.utilities.HoverFormatHelper.FixedItemHover fixedItemHover && fixedItemHover.getComponents() != null) { - item = NMSHandler.itemHelper.applyRawHoverComponentsJson(item, fixedItemHover.getComponents()); + else if (hover.value() instanceof HoverEvent.ShowItem itemHover) { + Debug.log("Item hover: " + itemHover.dataComponents()); + ItemStack item = new ItemStack(Registry.MATERIAL.get(itemHover.item()), itemHover.count()); + if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20)) { +// item = NMSHandler.itemHelper.applyRawHoverComponentsJson(item, fixedItemHover.getComponents()); TODO } - else if (NMSHandler.getVersion().isAtMost(NMSVersion.v1_19) && itemHover.getTag() != null && itemHover.getTag().getNbt() != null) { - item = Bukkit.getUnsafe().modifyItemStack(item, itemHover.getTag().getNbt()); + else if (itemHover.nbt() != null) { + item = Bukkit.getUnsafe().modifyItemStack(item, itemHover.nbt().string()); } return new ItemTag(item).identify(); } - else if (contentObject instanceof Entity entityHover) { - return createEntityHoverData(entityHover.getId(), entityHover.getType(), entityHover.getName()).savable(); + else if (hover.value() instanceof HoverEvent.ShowEntity entityHover) { + return createEntityHoverData(entityHover.id(), entityHover.type(), entityHover.name()).savable(); } else { throw new UnsupportedOperationException(); } } - public static MapTag createEntityHoverData(String uuid, String type, BaseComponent name) { + public static MapTag createEntityHoverData(UUID uuid, Key type, Component name) { MapTag entityHoverData = new MapTag(); - entityHoverData.putObject("uuid", new ElementTag(uuid, true)); - if (type != null) { - entityHoverData.putObject("type", new ElementTag(type, true)); - } - else { - try { - // This isn't even optional, but is in Bungee for some reason - try our best to have a value - org.bukkit.entity.Entity found = EntityTag.getEntityForID(UUID.fromString(uuid)); - if (found != null) { - entityHoverData.putObject("type", new ElementTag(found.getType().getKey().toString(), true)); - } - } - catch (IllegalArgumentException ignore) {} - } + entityHoverData.putObject("uuid", new ElementTag(uuid.toString(), true)); + entityHoverData.putObject("type", new ElementTag(type.asString(), true)); if (name != null) { - entityHoverData.putObject("name", new ElementTag(com.denizenscript.denizen.utilities.FormattedTextHelper.stringify(name), true)); + entityHoverData.putObject("name", new ElementTag(FormattedTextHelper.stringify(name), true)); } return entityHoverData; } - public static String parseObjectToHover(ObjectTag object, HoverEvent.Action action, Attribute attribute) { - return switch (action) { - case SHOW_ENTITY -> { - EntityTag toShow = object.asType(EntityTag.class, attribute.context); - if (toShow == null) { - attribute.echoError("Invalid hover object '" + object + "' specified for type 'SHOW_ENTITY': must be an EntityTag."); - yield null; - } - BaseComponent[] customName = PaperAPITools.instance.getCustomNameComponent(toShow.getBukkitEntity()); - yield createEntityHoverData(toShow.getUUID().toString(), toShow.getBukkitEntityType().getKey().toString(), customName != null ? new TextComponent(customName) : null).savable(); - } - case SHOW_ITEM -> { - ItemTag toShow = object.asType(ItemTag.class, attribute.context); - if (toShow == null) { - attribute.echoError("Invalid hover object '" + object + "' specified for type 'SHOW_ITEM': must be an ItemTag."); - yield null; - } - yield toShow.identify(); + public static String parseObjectToHover(ObjectTag object, HoverEvent.Action action, Attribute attribute) { + if (action == HoverEvent.Action.SHOW_ENTITY) { + EntityTag toShow = object.asType(EntityTag.class, attribute.context); + if (toShow == null) { + attribute.echoError("Invalid hover object '" + object + "' specified for type 'SHOW_ENTITY': must be an EntityTag."); + return null; } - case SHOW_TEXT -> object.toString(); - default -> { - attribute.echoError("Using unsupported hover type: " + action + '.'); - yield null; - } - }; - } - - private static Entity parseLegacyEntityHover(String input) { - EntityTag entity = EntityTag.valueOf(input, CoreUtilities.basicContext); - if (entity == null) { - return null; + return createEntityHoverData(toShow.getUUID(), toShow.getBukkitEntityType().key(), toShow.getBukkitEntity() != null ? toShow.getBukkitEntity().customName() : null).savable(); } - BaseComponent name = null; - if (entity.getBukkitEntity() != null && entity.getBukkitEntity().isCustomNameVisible()) { - name = new TextComponent(); - for (BaseComponent component : com.denizenscript.denizen.utilities.FormattedTextHelper.parse(entity.getBukkitEntity().getCustomName(), ChatColor.WHITE)) { - name.addExtra(component); + else if (action == HoverEvent.Action.SHOW_ITEM) { + ItemTag toShow = object.asType(ItemTag.class, attribute.context); + if (toShow == null) { + attribute.echoError("Invalid hover object '" + object + "' specified for type 'SHOW_ITEM': must be an ItemTag."); + return null; } + return toShow.identify(); } - return new Entity(entity.getBukkitEntityType().getKey().toString(), entity.getUUID().toString(), name); - } - - public static void tryInitializeItemHoverFix() { - if (!NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20)) { - return; - } - Gson bungeeGson = FormattedTextHelper.getBungeeGson(); - if (bungeeGson == null) { - return; - } - Gson fixedGson = bungeeGson.newBuilder() - .registerTypeAdapter(com.denizenscript.denizen.utilities.HoverFormatHelper.FixedItemHover.class, new com.denizenscript.denizen.utilities.HoverFormatHelper.FixedItemHoverSerializer()) - .registerTypeAdapter(Item.class, new com.denizenscript.denizen.utilities.HoverFormatHelper.FixedItemHoverSerializer()) - .create(); - try { - if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21)) { - ReflectionHelper.setFieldValue(VersionedComponentSerializer.class, "gson", VersionedComponentSerializer.forVersion(ChatVersion.V1_21_5), fixedGson); - } - else { - ReflectionHelper.getFinalSetter(ComponentSerializer.class, "gson").invoke(fixedGson); - } - } - catch (Throwable e) { - Debug.echoError(e); - } - } - - public static class FixedItemHover extends Item { - - private final JsonObject components; - - public FixedItemHover(String id, int count, JsonObject components) { - super(id, count, null); - this.components = components; + else if (action == HoverEvent.Action.SHOW_TEXT) { + return object.identify(); } - - public JsonObject getComponents() { - return components; + else { + attribute.echoError("Using unsupported hover type: " + action + '.'); + return null; } } - public static class FixedItemHoverSerializer extends ItemSerializer { - - @Override - public Item deserialize(JsonElement element, Type type, JsonDeserializationContext context) throws JsonParseException { - Item deserialized = super.deserialize(element, type, context); - if (deserialized.getTag() != null) { - return deserialized; - } - JsonObject componentsObject = element.getAsJsonObject().getAsJsonObject("components"); - if (componentsObject == null) { - return deserialized; - } - return new com.denizenscript.denizen.utilities.HoverFormatHelper.FixedItemHover(deserialized.getId(), deserialized.getCount(), componentsObject); + private static HoverEventSource parseLegacyEntityHover(String input) { + EntityTag entity = EntityTag.valueOf(input, CoreUtilities.basicContext); + if (entity == null) { + return null; } - - @Override - public JsonElement serialize(Item content, Type type, JsonSerializationContext context) { - JsonElement serialized = super.serialize(content, type, context); - if (!(content instanceof com.denizenscript.denizen.utilities.HoverFormatHelper.FixedItemHover fixedItemHover) || fixedItemHover.getComponents() == null) { - return serialized; - } - JsonObject serializedObject = serialized.getAsJsonObject(); - serializedObject.remove("tag"); - serializedObject.add("components", fixedItemHover.getComponents()); - return serializedObject; + Component name = null; + if (entity.getBukkitEntity() != null && entity.getBukkitEntity().isCustomNameVisible()) { + name = entity.getBukkitEntity().customName(); } + return HoverEvent.showEntity(entity.getBukkitEntityType(), entity.getUUID(), name); } } From 35f5080ffd334d59d9c5af1d34aca92e56207889 Mon Sep 17 00:00:00 2001 From: Aya <31237389+tal5@users.noreply.github.com> Date: Sat, 6 Sep 2025 16:19:07 +0100 Subject: [PATCH 04/24] Attempt mutability fix --- .../denizen/paper/utilities/FormattedTextHelper.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/FormattedTextHelper.java b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/FormattedTextHelper.java index fc52035d55..b49c505a2b 100644 --- a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/FormattedTextHelper.java +++ b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/FormattedTextHelper.java @@ -603,8 +603,6 @@ public static Component parseInternal(String str, TextColor baseColor, boolean c base = Component.text(); base.content(str.substring(0, firstChar)); } - // TODO immutable - root.append(base); str = str.substring(firstChar); char[] chars = str.toCharArray(); int started = 0; @@ -889,7 +887,7 @@ else if (i + "https://a.".length() < chars.length && chars[i] == 'h' && chars[i if (!nextText.content().isEmpty()) { base.append(nextText); } - return cleanBase && !optimize ? root.build() : base.build(); + return cleanBase && !optimize ? root.append(base).build() : base.build(); } public static int indexOfLastColorBlockStart(String text) { From 5e75d3d1b9c86d75a089eeb6eb5e160903cd17f0 Mon Sep 17 00:00:00 2001 From: Aya <31237389+tal5@users.noreply.github.com> Date: Sat, 6 Sep 2025 23:04:45 +0100 Subject: [PATCH 05/24] `BukkitElementExtensions`: raw copy-paste --- .../properties/PaperElementExtensions.java | 623 ++++++++++++++++++ .../bukkit/BukkitElementExtensions.java | 615 ----------------- 2 files changed, 623 insertions(+), 615 deletions(-) diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/properties/PaperElementExtensions.java b/paper/src/main/java/com/denizenscript/denizen/paper/properties/PaperElementExtensions.java index 090124e434..d2ab19dc39 100644 --- a/paper/src/main/java/com/denizenscript/denizen/paper/properties/PaperElementExtensions.java +++ b/paper/src/main/java/com/denizenscript/denizen/paper/properties/PaperElementExtensions.java @@ -2,15 +2,546 @@ import com.denizenscript.denizen.nms.NMSHandler; import com.denizenscript.denizen.nms.NMSVersion; +import com.denizenscript.denizen.objects.ItemTag; +import com.denizenscript.denizen.objects.properties.bukkit.BukkitElementExtensions; import com.denizenscript.denizen.paper.PaperModule; +import com.denizenscript.denizen.paper.utilities.FormattedTextHelper; +import com.denizenscript.denizen.paper.utilities.HoverFormatHelper; +import com.denizenscript.denizen.tags.core.CustomColorTagBase; +import com.denizenscript.denizen.utilities.BukkitImplDeprecations; import com.denizenscript.denizen.utilities.PaperAPITools; +import com.denizenscript.denizencore.objects.ObjectTag; +import com.denizenscript.denizencore.objects.core.ColorTag; import com.denizenscript.denizencore.objects.core.ElementTag; +import com.denizenscript.denizencore.objects.core.MapTag; +import com.denizenscript.denizencore.tags.TagManager; +import com.denizenscript.denizencore.utilities.AsciiMatcher; +import com.denizenscript.denizencore.utilities.CoreUtilities; +import net.kyori.adventure.text.event.HoverEvent; import net.kyori.adventure.text.minimessage.MiniMessage; +import net.md_5.bungee.api.ChatColor; public class PaperElementExtensions { public static void register() { + + // <--[tag] + // @attribute + // @returns ElementTag + // @group text manipulation + // @description + // Returns the element with all color encoding stripped. + // This will remove any/all colors, formats (bold/italic/etc), advanced formats (fonts/clickables/etc), and translate any translatables (&translate, &score, etc). + // This will automatically translate translatable sections + // --> + ElementTag.tagProcessor.registerStaticTag(ElementTag.class, "strip_color", (attribute, object) -> { + return new ElementTag(FormattedTextHelper.parse(object.asString(), ChatColor.WHITE)[0].toPlainText()); + }); + + + // <--[tag] + // @attribute + // @returns ElementTag + // @group conversion + // @description + // Converts normal colored text to Minecraft-style "raw JSON" format. + // Inverts <@link tag ElementTag.from_raw_json>. + // --> + ElementTag.tagProcessor.registerStaticTag(ElementTag.class, "to_raw_json", (attribute, object) -> { + return new ElementTag(FormattedTextHelper.componentToJson(FormattedTextHelper.parse(object.asString(), ChatColor.WHITE))); + }); + + // <--[tag] + // @attribute + // @returns ElementTag + // @group conversion + // @description + // Un-hides the element's text from invisible color codes back to normal text. + // Inverts <@link tag ElementTag.to_raw_json>. + // --> + ElementTag.tagProcessor.registerStaticTag(ElementTag.class, "from_raw_json", (attribute, object) -> { + return new ElementTag(FormattedTextHelper.stringify(FormattedTextHelper.parseJson(object.asString()))); + }); + + // <--[tag] + // @attribute + // @returns ElementTag + // @group conversion + // @description + // Tells the formatted text parser to try to produce mininalist JSON text. + // This is useful in particular for very long text or where text is being sent rapidly/repeatedly. + // It is not needed in most normal messages. + // It will produce incompatibility issues if used in items or other locations where raw JSON matching is required. + // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. + // --> + ElementTag.tagProcessor.registerStaticTag(ElementTag.class, "optimize_json", (attribute, object) -> { + String opti = ChatColor.COLOR_CHAR + "[optimize=true]"; + if (object.asString().contains(opti)) { + return object; + } + return new ElementTag(opti + object.asString(), true); + }); + + // <--[tag] + // @attribute ]> + // @returns ElementTag + // @group text manipulation + // @description + // Adds a hover message to the element, which makes the element display the input ItemTag when the mouse is left over it. + // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. + // @example + // - narrate "You can ]> to see what you held!" + // --> + ElementTag.tagProcessor.registerStaticTag(ElementTag.class, ItemTag.class, "hover_item", (attribute, object, item) -> { + return new ElementTag(ChatColor.COLOR_CHAR + "[hover=SHOW_ITEM;" + FormattedTextHelper.escape(item.identify()) + "]" + object.asString() + ChatColor.COLOR_CHAR + "[/hover]"); + }); + + // <--[tag] + // @attribute ]> + // @returns ElementTag + // @group text manipulation + // @description + // Adds a hover message to the element, which makes the element display the input hover text when the mouse is left over it. + // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. + // --> + ElementTag.tagProcessor.registerTag(ElementTag.class, ObjectTag.class, "on_hover", (attribute, object, hover) -> { // non-static due to hacked sub-tag + HoverEvent.Action type = HoverEvent.Action.SHOW_TEXT; + + // <--[tag] + // @attribute ].type[]> + // @returns ElementTag + // @group text manipulation + // @description + // Adds a hover message to the element, which makes the element display the input hover text when the mouse is left over it. + // Available hover types: SHOW_TEXT, SHOW_ITEM, or SHOW_ENTITY. + // Note: for "SHOW_ITEM", replace the text with a valid ItemTag. For "SHOW_ENTITY", replace the text with a valid spawned EntityTag (requires F3+H to see entities). + // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. + // For show_text, prefer <@link tag ElementTag.on_hover> + // For show_item, prefer <@link tag ElementTag.hover_item> + // --> + if (attribute.startsWith("type", 2)) { + attribute.fulfill(1); + type = ElementTag.asEnum(HoverEvent.Action.class, attribute.getParam()); + if (type == null) { + attribute.echoError("Invalid hover type specified."); + return null; + } + } + String hoverData = HoverFormatHelper.parseObjectToHover(hover, type, attribute); + if (hoverData == null) { + return null; + } + return new ElementTag(ChatColor.COLOR_CHAR + "[hover=" + type + ';' + FormattedTextHelper.escape(hoverData) + ']' + + object.asString() + ChatColor.COLOR_CHAR + "[/hover]", true); + }); + + // <--[tag] + // @attribute ]> + // @returns ElementTag + // @group text manipulation + // @description + // Adds a click command to the element, which makes the element open the given URL when clicked. + // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. + // @example + // - narrate "You can to learn about Denizen!" + // --> + ElementTag.tagProcessor.registerStaticTag(ElementTag.class, ElementTag.class, "click_url", (attribute, object, url) -> { + return new ElementTag(ChatColor.COLOR_CHAR + "[click=OPEN_URL;" + FormattedTextHelper.escape(url.toString()) + "]" + object.asString() + ChatColor.COLOR_CHAR + "[/click]"); + }); + + // <--[tag] + // @attribute ]> + // @returns ElementTag + // @group text manipulation + // @description + // Adds a click command to the element, which makes the element pseudo-chat the input message when clicked, for activating interact script chat triggers (<@link language Chat Triggers>). + // This internally uses the command "/denizenclickable chat SOME MESSAGE HERE" (requires players have permission "denizen.clickable") + // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. + // @example + // - narrate "You can to say hello to an NPC's interact script!" + // --> + ElementTag.tagProcessor.registerStaticTag(ElementTag.class, ElementTag.class, "click_chat", (attribute, object, chat) -> { + return new ElementTag(ChatColor.COLOR_CHAR + "[click=RUN_COMMAND;/denizenclickable chat " + FormattedTextHelper.escape(chat.toString()) + "]" + object.asString() + ChatColor.COLOR_CHAR + "[/click]"); + }); + + // <--[tag] + // @attribute ]> + // @returns ElementTag + // @group text manipulation + // @description + // Adds a click command to the element, which makes the element execute the input command when clicked. + // To execute a command "/" should be used at the start. Prior to 1.19, leaving off the "/" would display the text as chat. This feature was removed as part of the 1.19 secure chat system. + // For activating interact script chat triggers (<@link language Chat Triggers>), you can use the command "/denizenclickable chat SOME MESSAGE HERE" (requires players have permission "denizen.clickable") + // For that, instead prefer <@link tag ElementTag.click_chat> + // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. + // @example + // - narrate "You can for help!" + // @example + // - narrate "You can to say hello to an NPC's interact script!" + // --> + ElementTag.tagProcessor.registerTag(ElementTag.class, ElementTag.class, "on_click", (attribute, object, command) -> { // non-static due to hacked sub-tag + String type = "RUN_COMMAND"; + + // <--[tag] + // @attribute ].type[]> + // @returns ElementTag + // @group text manipulation + // @description + // Adds a click command to the element, which makes the element execute the input command when clicked. + // Available command types: OPEN_URL, OPEN_FILE, RUN_COMMAND, SUGGEST_COMMAND, COPY_TO_CLIPBOARD, or CHANGE_PAGE. + // For example: - narrate "You can to learn about Denizen!" + // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. + // For run_command, prefer <@link tag ElementTag.on_click> + // For chat, prefer <@link tag ElementTag.click_chat> + // For URLs, prefer <@link tag ElementTag.click_url> + // --> + if (attribute.startsWith("type", 2)) { + type = attribute.getContext(2); + attribute.fulfill(1); + } + return new ElementTag(ChatColor.COLOR_CHAR + "[click=" + type + ";" + FormattedTextHelper.escape(command.asString()) + "]" + + object.asString() + ChatColor.COLOR_CHAR + "[/click]"); + }); + + // <--[tag] + // @attribute ]> + // @returns ElementTag + // @group text manipulation + // @description + // Adds an insertion message to the element, which makes the element insert the input message to chat when shift-clicked. + // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. + // --> + ElementTag.tagProcessor.registerStaticTag(ElementTag.class, ElementTag.class, "with_insertion", (attribute, object, insertion) -> { + return new ElementTag(ChatColor.COLOR_CHAR + "[insertion=" + FormattedTextHelper.escape(insertion.asString()) + "]" + + object.asString() + ChatColor.COLOR_CHAR + "[/insertion]"); + }); + + // <--[tag] + // @attribute + // @returns ElementTag + // @group text manipulation + // @description + // Makes a color code (&0123456789abcdef) not reset other formatting details. + // Use like '<&c.no_reset>' or ''. + // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. + // --> + ElementTag.tagProcessor.registerStaticTag(ElementTag.class, "no_reset", (attribute, object) -> { + if (object.asString().length() == 2 && object.asString().charAt(0) == ChatColor.COLOR_CHAR) { + return new ElementTag(ChatColor.COLOR_CHAR + "[color=" + object.asString().charAt(1) + "]"); + } + return null; + }); + + // <--[tag] + // @attribute + // @returns ElementTag + // @group text manipulation + // @description + // Makes a chat format code (&klmno, or &[font=...]) be the end of a format, as opposed to the start. + // Use like '<&o.end_format>' or ''. + // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. + // --> + ElementTag.tagProcessor.registerStaticTag(ElementTag.class, "end_format", (attribute, object) -> { + if (object.asString().length() == 2 && object.asString().charAt(0) == ChatColor.COLOR_CHAR) { + return new ElementTag(ChatColor.COLOR_CHAR + "[reset=" + object.asString().charAt(1) + "]"); + } + else if (object.asString().startsWith(ChatColor.COLOR_CHAR + "[font=") && object.asString().endsWith("]")) { + return new ElementTag(ChatColor.COLOR_CHAR + "[reset=font]"); + } + return null; + }); + + // <--[tag] + // @attribute + // @returns ElementTag + // @group text manipulation + // @description + // Makes the input text italic. Equivalent to "<&o><&o.end_format>" + // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. + // --> + ElementTag.tagProcessor.registerStaticTag(ElementTag.class, "italicize", (attribute, object) -> { + return new ElementTag(ChatColor.ITALIC + object.asString() + ChatColor.COLOR_CHAR + "[reset=o]"); + }); + + // <--[tag] + // @attribute + // @returns ElementTag + // @group text manipulation + // @description + // Makes the input text bold. Equivalent to "<&l><&l.end_format>" + // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. + // --> + ElementTag.tagProcessor.registerStaticTag(ElementTag.class, "bold", (attribute, object) -> { + return new ElementTag(ChatColor.BOLD + object.asString() + ChatColor.COLOR_CHAR + "[reset=l]"); + }); + + // <--[tag] + // @attribute + // @returns ElementTag + // @group text manipulation + // @description + // Makes the input text underlined. Equivalent to "<&n><&n.end_format>" + // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. + // --> + ElementTag.tagProcessor.registerStaticTag(ElementTag.class, "underline", (attribute, object) -> { + return new ElementTag(ChatColor.UNDERLINE + object.asString() + ChatColor.COLOR_CHAR + "[reset=n]"); + }); + + // <--[tag] + // @attribute + // @returns ElementTag + // @group text manipulation + // @description + // Makes the input text struck-through. Equivalent to "<&m><&m.end_format>" + // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. + // --> + ElementTag.tagProcessor.registerStaticTag(ElementTag.class, "strikethrough", (attribute, object) -> { + return new ElementTag(ChatColor.STRIKETHROUGH + object.asString() + ChatColor.COLOR_CHAR + "[reset=m]"); + }); + + // <--[tag] + // @attribute + // @returns ElementTag + // @group text manipulation + // @description + // Makes the input text obfuscated. Equivalent to "<&k><&k.end_format>" + // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. + // --> + ElementTag.tagProcessor.registerStaticTag(ElementTag.class, "obfuscate", (attribute, object) -> { + return new ElementTag(ChatColor.MAGIC + object.asString() + ChatColor.COLOR_CHAR + "[reset=k]"); + }); + + // <--[tag] + // @attribute ]> + // @returns ElementTag + // @group text manipulation + // @description + // Makes the input text colored by the custom color value based on the common base color names defined in the Denizen config file. + // If the color name is unrecognized, returns the value of color named 'default'. + // Default color names are 'base', 'emphasis', 'warning', 'error'. + // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. + // --> + ElementTag.tagProcessor.registerStaticTag(ElementTag.class, ElementTag.class, "custom_color", (attribute, object, name) -> { + String color = CustomColorTagBase.getColor(name.asLowerString(), attribute.context); + if (color == null) { + return null; + } + return new ElementTag(ChatColor.COLOR_CHAR + "[color=f]" + color + object.asString() + ChatColor.COLOR_CHAR + "[reset=color]"); + }); + + // <--[tag] + // @attribute ]> + // @returns ElementTag + // @group text manipulation + // @description + // Makes the input text colored by the input color. Equivalent to "" + // Color can be a color name, color code, hex, or ColorTag... that is: ".color[gold]", ".color[6]", and ".color[#AABB00]" are all valid. + // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. + // --> + ElementTag.tagProcessor.registerStaticTag(ElementTag.class, ElementTag.class, "color", (attribute, object, colorElement) -> { + String colorName = colorElement.asString(); + String colorOut = null; + if (colorName.length() == 1) { + ChatColor color = ChatColor.getByChar(colorName.charAt(0)); + if (color != null) { + colorOut = color.toString(); + } + } + else if (colorName.length() == 7 && colorName.startsWith("#")) { + return new ElementTag(ChatColor.COLOR_CHAR + "[color=" + colorName + "]" + object.asString() + ChatColor.COLOR_CHAR + "[reset=color]"); + } + else if (colorName.length() == 14 && colorName.startsWith(ChatColor.COLOR_CHAR + "x")) { + return new ElementTag(ChatColor.COLOR_CHAR + "[color=#" + CoreUtilities.replace(colorName.substring(2), String.valueOf(ChatColor.COLOR_CHAR), "") + "]" + object.asString() + ChatColor.COLOR_CHAR + "[reset=color]"); + } + else if (colorName.startsWith("co@")) { + ColorTag color = ColorTag.valueOf(colorName, attribute.context); + if (color == null && TagManager.isStaticParsing) { + return null; + } + StringBuilder hex = new StringBuilder(Integer.toHexString(color.asRGB())); + while (hex.length() < 6) { + hex.insert(0, "0"); + } + return new ElementTag(ChatColor.COLOR_CHAR + "[color=#" + hex + "]" + object.asString() + ChatColor.COLOR_CHAR + "[reset=color]"); + } + if (colorOut == null) { + try { + ChatColor color = ChatColor.of(colorName.toUpperCase()); + if (color.getColor() == null) { + if (!TagManager.isStaticParsing) { + attribute.echoError("Color '" + colorName + "' is valid but is a format code not a real color (for ElementTag.color[...])."); + } + return null; + } + String colorStr = color.toString().replace(String.valueOf(ChatColor.COLOR_CHAR), "").replace("x", "#"); + colorOut = ChatColor.COLOR_CHAR + "[color=" + colorStr + "]"; + } + catch (IllegalArgumentException ex) { + ColorTag color = ColorTag.valueOf(colorName, attribute.context); + if (color != null) { + StringBuilder hex = new StringBuilder(Integer.toHexString(color.asRGB())); + while (hex.length() < 6) { + hex.insert(0, "0"); + } + return new ElementTag(ChatColor.COLOR_CHAR + "[color=#" + hex + "]" + object.asString() + ChatColor.COLOR_CHAR + "[reset=color]"); + } + if (!TagManager.isStaticParsing) { + attribute.echoError("Color '" + colorName + "' doesn't exist (for ElementTag.color[...])."); + } + return null; + } + } + return new ElementTag(colorOut + object.asString() + ChatColor.COLOR_CHAR + "[reset=color]"); + }); + + // <--[tag] + // @attribute ]> + // @returns ElementTag + // @group text manipulation + // @description + // Makes the input text display with the input font name. Equivalent to "<&font[new-font]><&font[new-font].end_format>" + // The default font is "minecraft:default". + // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. + // --> + ElementTag.tagProcessor.registerStaticTag(ElementTag.class, ElementTag.class, "font", (attribute, object, fontName) -> { + return new ElementTag(ChatColor.COLOR_CHAR + "[font=" + fontName + "]" + object.asString() + ChatColor.COLOR_CHAR + "[reset=font]"); + }); + + // <--[tag] + // @attribute )]> + // @returns ElementTag + // @group text manipulation + // @description + // Returns the element with rainbow colors applied. + // Optionally, specify a color pattern to follow. By default, this is "4c6e2ab319d5". + // That is, a repeating color of: Red, Orange, Yellow, Green, Cyan, Blue, Purple. + // --> + ElementTag.tagProcessor.registerStaticTag(ElementTag.class, "rainbow", (attribute, object) -> { + String str = object.asString(); + String pattern = "4c6e2ab319d5"; + if (attribute.hasParam()) { + pattern = attribute.getParam(); + } + StringBuilder output = new StringBuilder(str.length() * 3); + for (int i = 0; i < str.length(); i++) { + output.append(ChatColor.COLOR_CHAR).append(pattern.charAt(i % pattern.length())).append(str.charAt(i)); + } + return new ElementTag(output.toString()); + }); + + // <--[tag] + // @attribute )]> + // @returns ElementTag + // @group text manipulation + // @description + // Returns the element with RGB rainbow colors applied. + // Optionally, specify a length (how many characters before the colors repeat). If unspecified, will use the input element length. + // If the element starts with a hex color code, that will be used as the starting color of the rainbow. + // --> + ElementTag.tagProcessor.registerStaticTag(ElementTag.class, "hex_rainbow", (attribute, object) -> { + String str = object.asString(); + int[] HSB = new int[] { 0, 255, 255 }; + if (str.startsWith(ChatColor.COLOR_CHAR + "x") && str.length() > 14) { + char[] colors = new char[6]; + for (int i = 0; i < 6; i++) { + colors[i] = str.charAt(3 + (i * 2)); + } + int rgb = Integer.parseInt(new String(colors), 16); + HSB = ColorTag.fromRGB(rgb).toHSB(); + str = str.substring(14); + } + float hue = HSB[0] / 255f; + int length = ChatColor.stripColor(str).length(); + if (length == 0) { + return new ElementTag(""); + } + if (attribute.hasParam()) { + length = attribute.getIntParam(); + } + float increment = 1.0f / length; + String addedFormat = ""; + StringBuilder output = new StringBuilder(str.length() * 8); + for (int i = 0; i < str.length(); i++) { + char c = str.charAt(i); + if (c == ChatColor.COLOR_CHAR && i + 1 < str.length()) { + char c2 = str.charAt(i + 1); + if (FORMAT_CODES_MATCHER.isMatch(c2)) { + addedFormat += String.valueOf(ChatColor.COLOR_CHAR) + c2; + } + else { + addedFormat = ""; + } + i++; + continue; + } + String hex = Integer.toHexString(ColorTag.fromHSB(HSB).asRGB()); + output.append(FormattedTextHelper.stringifyRGBSpigot(hex)).append(addedFormat).append(c); + hue += increment; + HSB[0] = Math.round(hue * 255f); + } + return new ElementTag(output.toString()); + }); + + // <--[tag] + // @attribute ;to=;(style={RGB}/HSB)]> + // @returns ElementTag + // @group text manipulation + // @description + // Returns the element with an RGB color gradient applied, with a unique color per character. + // Specify the input as a map with keys 'from' and 'to' both set to hex colors (or any valid ColorTag). + // You can also choose a style (defaults to RGB): + // "style=RGB" tends to produce smooth gradients, + // "style=HSB" tends to produce bright rainbow-like color patterns. + // @example + // - narrate "" + // @example + // - narrate "" + // @example + // - narrate "" + // @example + // - narrate "" + // --> + ElementTag.tagProcessor.registerStaticTag(ElementTag.class, MapTag.class, "color_gradient", (attribute, object, inputMap) -> { + ColorTag fromColor = inputMap.getRequiredObjectAs("from", ColorTag.class, attribute); + ColorTag toColor = inputMap.getRequiredObjectAs("to", ColorTag.class, attribute); + ElementTag style = inputMap.getElement("style", "RGB"); + if (fromColor == null || toColor == null) { + return null; + } + if (!style.matchesEnum(BukkitElementExtensions.GradientStyle.class)) { + attribute.echoError("Invalid gradient style '" + style + "'"); + return null; + } + String res = doGradient(object.asString(), fromColor, toColor, style.asEnum(GradientStyle.class)); + if (res == null) { + return null; + } + return new ElementTag(res); + }); + + // <--[tag] + // @attribute ;to=]> + // @returns ElementTag + // @group text manipulation + // @deprecated use color_gradient[from=color;to=color;style=HSB] + // @description + // Deprecated in favor of using <@link tag ElementTag.color_gradient> with "style=hsb" + // --> + ElementTag.tagProcessor.registerStaticTag(ElementTag.class, MapTag.class, "hsb_color_gradient", (attribute, object, inputMap) -> { + BukkitImplDeprecations.hsbColorGradientTag.warn(attribute.context); + ColorTag fromColor = inputMap.getRequiredObjectAs("from", ColorTag.class, attribute); + ColorTag toColor = inputMap.getRequiredObjectAs("to", ColorTag.class, attribute); + if (fromColor == null || toColor == null) { + return null; + } + String res = doGradient(object.asString(), fromColor, toColor, GradientStyle.HSB); + if (res == null) { + return null; + } + return new ElementTag(res); + }); + if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_18)) { // <--[tag] @@ -40,4 +571,96 @@ public static void register() { }); } } + + public enum GradientStyle { RGB, HSB } + + public static String doGradient(String str, ColorTag fromColor, ColorTag toColor, GradientStyle style) { + int length = FormattedTextHelper.parse(str, ChatColor.WHITE)[0].toPlainText().length(); + if (length == 0) { + return ""; + } + if (fromColor == null || toColor == null) { + return null; + } + float r, g, b, x = 0, rMove, gMove, bMove, xMove = 0, toR, toG, toB; + int[] hsbHelper = null; + if (style == GradientStyle.RGB) { + r = ColorTag.fromSRGB(fromColor.red); + g = ColorTag.fromSRGB(fromColor.green); + b = ColorTag.fromSRGB(fromColor.blue); + x = (float) Math.pow(r + g + b, 0.43); + toR = ColorTag.fromSRGB(toColor.red); + toG = ColorTag.fromSRGB(toColor.green); + toB = ColorTag.fromSRGB(toColor.blue); + float toBrightness = (float) Math.pow(toR + toG + toB, 0.43); + xMove = (toBrightness - x) / length; + } + else { + hsbHelper = fromColor.toHSB(); + int[] toHSB = toColor.toHSB(); + r = hsbHelper[0]; + g = hsbHelper[1]; + b = hsbHelper[2]; + toR = toHSB[0]; + toG = toHSB[1]; + toB = toHSB[2]; + } + rMove = (toR - r) / length; + gMove = (toG - g) / length; + bMove = (toB - b) / length; + String addedFormat = ""; + StringBuilder output = new StringBuilder(str.length() * 15); + for (int i = 0; i < str.length(); i++) { + char c = str.charAt(i); + if (c == ChatColor.COLOR_CHAR && i + 1 < str.length()) { + char c2 = str.charAt(i + 1); + if (FORMAT_CODES_MATCHER.isMatch(c2)) { + addedFormat += String.valueOf(ChatColor.COLOR_CHAR) + c2; + } + else if (c2 == '[') { + int endBracket = str.indexOf(']', i); + if (endBracket != -1) { + addedFormat += str.substring(i, endBracket + 1); + i = endBracket - 1; + } + } + else { + addedFormat = ""; + } + i++; + continue; + } + String hex; + if (style == GradientStyle.RGB) { + // Based on https://stackoverflow.com/questions/22607043/color-gradient-algorithm/49321304#49321304 + float newRed = r, newGreen = g, newBlue = b; + float sum = newRed + newGreen + newBlue; + if (sum > 0) { + float multiplier = (float) Math.pow(x, 1f / 0.43f) / sum; + newRed *= multiplier; + newGreen *= multiplier; + newBlue *= multiplier; + } + newRed = ColorTag.toSRGB(newRed); + newGreen = ColorTag.toSRGB(newGreen); + newBlue = ColorTag.toSRGB(newBlue); + hex = Integer.toHexString((((int) newRed) << 16) | (((int) newGreen) << 8) | ((int) newBlue)); + x += xMove; + } + else { + hsbHelper[0] = (int)r; + hsbHelper[1] = (int)g; + hsbHelper[2] = (int)b; + ColorTag currentColor = ColorTag.fromHSB(hsbHelper); + hex = Integer.toHexString(currentColor.asRGB()); + } + output.append(FormattedTextHelper.stringifyRGBSpigot(hex)).append(addedFormat).append(str.charAt(i)); + r += rMove; + g += gMove; + b += bMove; + } + return output.toString(); + } + + public static AsciiMatcher FORMAT_CODES_MATCHER = new AsciiMatcher("klmnoKLMNO"); } diff --git a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/bukkit/BukkitElementExtensions.java b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/bukkit/BukkitElementExtensions.java index 32a8a85a28..af114ff6eb 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/bukkit/BukkitElementExtensions.java +++ b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/bukkit/BukkitElementExtensions.java @@ -3,24 +3,16 @@ import com.denizenscript.denizen.objects.*; import com.denizenscript.denizen.objects.properties.item.ItemRawNBT; import com.denizenscript.denizen.scripts.containers.core.ItemScriptHelper; -import com.denizenscript.denizen.tags.core.CustomColorTagBase; -import com.denizenscript.denizen.utilities.BukkitImplDeprecations; -import com.denizenscript.denizen.utilities.FormattedTextHelper; -import com.denizenscript.denizen.utilities.HoverFormatHelper; import com.denizenscript.denizen.utilities.TextWidthHelper; import com.denizenscript.denizencore.objects.ArgumentHelper; -import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ColorTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.objects.core.ListTag; import com.denizenscript.denizencore.objects.core.MapTag; -import com.denizenscript.denizencore.tags.TagManager; -import com.denizenscript.denizencore.utilities.AsciiMatcher; import com.denizenscript.denizencore.utilities.CoreConfiguration; import com.denizenscript.denizencore.utilities.CoreUtilities; import com.denizenscript.denizencore.utilities.Deprecations; import net.md_5.bungee.api.ChatColor; -import net.md_5.bungee.api.chat.HoverEvent; import java.io.IOException; import java.nio.charset.StandardCharsets; @@ -326,19 +318,6 @@ public static void register() { return new ElementTag(org.bukkit.ChatColor.getLastColors(object.asString())); }); - // <--[tag] - // @attribute - // @returns ElementTag - // @group text manipulation - // @description - // Returns the element with all color encoding stripped. - // This will remove any/all colors, formats (bold/italic/etc), advanced formats (fonts/clickables/etc), and translate any translatables (&translate, &score, etc). - // This will automatically translate translatable sections - // --> - ElementTag.tagProcessor.registerStaticTag(ElementTag.class, "strip_color", (attribute, object) -> { - return new ElementTag(FormattedTextHelper.parse(object.asString(), ChatColor.WHITE)[0].toPlainText()); - }); - // <--[tag] // @attribute )]> // @returns ElementTag @@ -404,508 +383,6 @@ public static void register() { return new ElementTag(new String(bytes, StandardCharsets.UTF_8)); }); - // <--[tag] - // @attribute - // @returns ElementTag - // @group conversion - // @description - // Converts normal colored text to Minecraft-style "raw JSON" format. - // Inverts <@link tag ElementTag.from_raw_json>. - // --> - ElementTag.tagProcessor.registerStaticTag(ElementTag.class, "to_raw_json", (attribute, object) -> { - return new ElementTag(FormattedTextHelper.componentToJson(FormattedTextHelper.parse(object.asString(), ChatColor.WHITE))); - }); - - // <--[tag] - // @attribute - // @returns ElementTag - // @group conversion - // @description - // Un-hides the element's text from invisible color codes back to normal text. - // Inverts <@link tag ElementTag.to_raw_json>. - // --> - ElementTag.tagProcessor.registerStaticTag(ElementTag.class, "from_raw_json", (attribute, object) -> { - return new ElementTag(FormattedTextHelper.stringify(FormattedTextHelper.parseJson(object.asString()))); - }); - - // <--[tag] - // @attribute - // @returns ElementTag - // @group conversion - // @description - // Tells the formatted text parser to try to produce mininalist JSON text. - // This is useful in particular for very long text or where text is being sent rapidly/repeatedly. - // It is not needed in most normal messages. - // It will produce incompatibility issues if used in items or other locations where raw JSON matching is required. - // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. - // --> - ElementTag.tagProcessor.registerStaticTag(ElementTag.class, "optimize_json", (attribute, object) -> { - String opti = ChatColor.COLOR_CHAR + "[optimize=true]"; - if (object.asString().contains(opti)) { - return object; - } - return new ElementTag(opti + object.asString(), true); - }); - - // <--[tag] - // @attribute ]> - // @returns ElementTag - // @group text manipulation - // @description - // Adds a hover message to the element, which makes the element display the input ItemTag when the mouse is left over it. - // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. - // @example - // - narrate "You can ]> to see what you held!" - // --> - ElementTag.tagProcessor.registerStaticTag(ElementTag.class, ItemTag.class, "hover_item", (attribute, object, item) -> { - return new ElementTag(ChatColor.COLOR_CHAR + "[hover=SHOW_ITEM;" + FormattedTextHelper.escape(item.identify()) + "]" + object.asString() + ChatColor.COLOR_CHAR + "[/hover]"); - }); - - // <--[tag] - // @attribute ]> - // @returns ElementTag - // @group text manipulation - // @description - // Adds a hover message to the element, which makes the element display the input hover text when the mouse is left over it. - // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. - // --> - ElementTag.tagProcessor.registerTag(ElementTag.class, ObjectTag.class, "on_hover", (attribute, object, hover) -> { // non-static due to hacked sub-tag - HoverEvent.Action type = HoverEvent.Action.SHOW_TEXT; - - // <--[tag] - // @attribute ].type[]> - // @returns ElementTag - // @group text manipulation - // @description - // Adds a hover message to the element, which makes the element display the input hover text when the mouse is left over it. - // Available hover types: SHOW_TEXT, SHOW_ITEM, or SHOW_ENTITY. - // Note: for "SHOW_ITEM", replace the text with a valid ItemTag. For "SHOW_ENTITY", replace the text with a valid spawned EntityTag (requires F3+H to see entities). - // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. - // For show_text, prefer <@link tag ElementTag.on_hover> - // For show_item, prefer <@link tag ElementTag.hover_item> - // --> - if (attribute.startsWith("type", 2)) { - attribute.fulfill(1); - type = ElementTag.asEnum(HoverEvent.Action.class, attribute.getParam()); - if (type == null) { - attribute.echoError("Invalid hover type specified."); - return null; - } - } - String hoverData = HoverFormatHelper.parseObjectToHover(hover, type, attribute); - if (hoverData == null) { - return null; - } - return new ElementTag(ChatColor.COLOR_CHAR + "[hover=" + type + ';' + FormattedTextHelper.escape(hoverData) + ']' - + object.asString() + ChatColor.COLOR_CHAR + "[/hover]", true); - }); - - // <--[tag] - // @attribute ]> - // @returns ElementTag - // @group text manipulation - // @description - // Adds a click command to the element, which makes the element open the given URL when clicked. - // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. - // @example - // - narrate "You can to learn about Denizen!" - // --> - ElementTag.tagProcessor.registerStaticTag(ElementTag.class, ElementTag.class, "click_url", (attribute, object, url) -> { - return new ElementTag(ChatColor.COLOR_CHAR + "[click=OPEN_URL;" + FormattedTextHelper.escape(url.toString()) + "]" + object.asString() + ChatColor.COLOR_CHAR + "[/click]"); - }); - - // <--[tag] - // @attribute ]> - // @returns ElementTag - // @group text manipulation - // @description - // Adds a click command to the element, which makes the element pseudo-chat the input message when clicked, for activating interact script chat triggers (<@link language Chat Triggers>). - // This internally uses the command "/denizenclickable chat SOME MESSAGE HERE" (requires players have permission "denizen.clickable") - // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. - // @example - // - narrate "You can to say hello to an NPC's interact script!" - // --> - ElementTag.tagProcessor.registerStaticTag(ElementTag.class, ElementTag.class, "click_chat", (attribute, object, chat) -> { - return new ElementTag(ChatColor.COLOR_CHAR + "[click=RUN_COMMAND;/denizenclickable chat " + FormattedTextHelper.escape(chat.toString()) + "]" + object.asString() + ChatColor.COLOR_CHAR + "[/click]"); - }); - - // <--[tag] - // @attribute ]> - // @returns ElementTag - // @group text manipulation - // @description - // Adds a click command to the element, which makes the element execute the input command when clicked. - // To execute a command "/" should be used at the start. Prior to 1.19, leaving off the "/" would display the text as chat. This feature was removed as part of the 1.19 secure chat system. - // For activating interact script chat triggers (<@link language Chat Triggers>), you can use the command "/denizenclickable chat SOME MESSAGE HERE" (requires players have permission "denizen.clickable") - // For that, instead prefer <@link tag ElementTag.click_chat> - // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. - // @example - // - narrate "You can for help!" - // @example - // - narrate "You can to say hello to an NPC's interact script!" - // --> - ElementTag.tagProcessor.registerTag(ElementTag.class, ElementTag.class, "on_click", (attribute, object, command) -> { // non-static due to hacked sub-tag - String type = "RUN_COMMAND"; - - // <--[tag] - // @attribute ].type[]> - // @returns ElementTag - // @group text manipulation - // @description - // Adds a click command to the element, which makes the element execute the input command when clicked. - // Available command types: OPEN_URL, OPEN_FILE, RUN_COMMAND, SUGGEST_COMMAND, COPY_TO_CLIPBOARD, or CHANGE_PAGE. - // For example: - narrate "You can to learn about Denizen!" - // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. - // For run_command, prefer <@link tag ElementTag.on_click> - // For chat, prefer <@link tag ElementTag.click_chat> - // For URLs, prefer <@link tag ElementTag.click_url> - // --> - if (attribute.startsWith("type", 2)) { - type = attribute.getContext(2); - attribute.fulfill(1); - } - return new ElementTag(ChatColor.COLOR_CHAR + "[click=" + type + ";" + FormattedTextHelper.escape(command.asString()) + "]" - + object.asString() + ChatColor.COLOR_CHAR + "[/click]"); - }); - - // <--[tag] - // @attribute ]> - // @returns ElementTag - // @group text manipulation - // @description - // Adds an insertion message to the element, which makes the element insert the input message to chat when shift-clicked. - // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. - // --> - ElementTag.tagProcessor.registerStaticTag(ElementTag.class, ElementTag.class, "with_insertion", (attribute, object, insertion) -> { - return new ElementTag(ChatColor.COLOR_CHAR + "[insertion=" + FormattedTextHelper.escape(insertion.asString()) + "]" - + object.asString() + ChatColor.COLOR_CHAR + "[/insertion]"); - }); - - // <--[tag] - // @attribute - // @returns ElementTag - // @group text manipulation - // @description - // Makes a color code (&0123456789abcdef) not reset other formatting details. - // Use like '<&c.no_reset>' or ''. - // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. - // --> - ElementTag.tagProcessor.registerStaticTag(ElementTag.class, "no_reset", (attribute, object) -> { - if (object.asString().length() == 2 && object.asString().charAt(0) == ChatColor.COLOR_CHAR) { - return new ElementTag(ChatColor.COLOR_CHAR + "[color=" + object.asString().charAt(1) + "]"); - } - return null; - }); - - // <--[tag] - // @attribute - // @returns ElementTag - // @group text manipulation - // @description - // Makes a chat format code (&klmno, or &[font=...]) be the end of a format, as opposed to the start. - // Use like '<&o.end_format>' or ''. - // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. - // --> - ElementTag.tagProcessor.registerStaticTag(ElementTag.class, "end_format", (attribute, object) -> { - if (object.asString().length() == 2 && object.asString().charAt(0) == ChatColor.COLOR_CHAR) { - return new ElementTag(ChatColor.COLOR_CHAR + "[reset=" + object.asString().charAt(1) + "]"); - } - else if (object.asString().startsWith(ChatColor.COLOR_CHAR + "[font=") && object.asString().endsWith("]")) { - return new ElementTag(ChatColor.COLOR_CHAR + "[reset=font]"); - } - return null; - }); - - // <--[tag] - // @attribute - // @returns ElementTag - // @group text manipulation - // @description - // Makes the input text italic. Equivalent to "<&o><&o.end_format>" - // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. - // --> - ElementTag.tagProcessor.registerStaticTag(ElementTag.class, "italicize", (attribute, object) -> { - return new ElementTag(ChatColor.ITALIC + object.asString() + ChatColor.COLOR_CHAR + "[reset=o]"); - }); - - // <--[tag] - // @attribute - // @returns ElementTag - // @group text manipulation - // @description - // Makes the input text bold. Equivalent to "<&l><&l.end_format>" - // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. - // --> - ElementTag.tagProcessor.registerStaticTag(ElementTag.class, "bold", (attribute, object) -> { - return new ElementTag(ChatColor.BOLD + object.asString() + ChatColor.COLOR_CHAR + "[reset=l]"); - }); - - // <--[tag] - // @attribute - // @returns ElementTag - // @group text manipulation - // @description - // Makes the input text underlined. Equivalent to "<&n><&n.end_format>" - // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. - // --> - ElementTag.tagProcessor.registerStaticTag(ElementTag.class, "underline", (attribute, object) -> { - return new ElementTag(ChatColor.UNDERLINE + object.asString() + ChatColor.COLOR_CHAR + "[reset=n]"); - }); - - // <--[tag] - // @attribute - // @returns ElementTag - // @group text manipulation - // @description - // Makes the input text struck-through. Equivalent to "<&m><&m.end_format>" - // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. - // --> - ElementTag.tagProcessor.registerStaticTag(ElementTag.class, "strikethrough", (attribute, object) -> { - return new ElementTag(ChatColor.STRIKETHROUGH + object.asString() + ChatColor.COLOR_CHAR + "[reset=m]"); - }); - - // <--[tag] - // @attribute - // @returns ElementTag - // @group text manipulation - // @description - // Makes the input text obfuscated. Equivalent to "<&k><&k.end_format>" - // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. - // --> - ElementTag.tagProcessor.registerStaticTag(ElementTag.class, "obfuscate", (attribute, object) -> { - return new ElementTag(ChatColor.MAGIC + object.asString() + ChatColor.COLOR_CHAR + "[reset=k]"); - }); - - // <--[tag] - // @attribute ]> - // @returns ElementTag - // @group text manipulation - // @description - // Makes the input text colored by the custom color value based on the common base color names defined in the Denizen config file. - // If the color name is unrecognized, returns the value of color named 'default'. - // Default color names are 'base', 'emphasis', 'warning', 'error'. - // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. - // --> - ElementTag.tagProcessor.registerStaticTag(ElementTag.class, ElementTag.class, "custom_color", (attribute, object, name) -> { - String color = CustomColorTagBase.getColor(name.asLowerString(), attribute.context); - if (color == null) { - return null; - } - return new ElementTag(ChatColor.COLOR_CHAR + "[color=f]" + color + object.asString() + ChatColor.COLOR_CHAR + "[reset=color]"); - }); - - // <--[tag] - // @attribute ]> - // @returns ElementTag - // @group text manipulation - // @description - // Makes the input text colored by the input color. Equivalent to "" - // Color can be a color name, color code, hex, or ColorTag... that is: ".color[gold]", ".color[6]", and ".color[#AABB00]" are all valid. - // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. - // --> - ElementTag.tagProcessor.registerStaticTag(ElementTag.class, ElementTag.class, "color", (attribute, object, colorElement) -> { - String colorName = colorElement.asString(); - String colorOut = null; - if (colorName.length() == 1) { - ChatColor color = ChatColor.getByChar(colorName.charAt(0)); - if (color != null) { - colorOut = color.toString(); - } - } - else if (colorName.length() == 7 && colorName.startsWith("#")) { - return new ElementTag(ChatColor.COLOR_CHAR + "[color=" + colorName + "]" + object.asString() + ChatColor.COLOR_CHAR + "[reset=color]"); - } - else if (colorName.length() == 14 && colorName.startsWith(ChatColor.COLOR_CHAR + "x")) { - return new ElementTag(ChatColor.COLOR_CHAR + "[color=#" + CoreUtilities.replace(colorName.substring(2), String.valueOf(ChatColor.COLOR_CHAR), "") + "]" + object.asString() + ChatColor.COLOR_CHAR + "[reset=color]"); - } - else if (colorName.startsWith("co@")) { - ColorTag color = ColorTag.valueOf(colorName, attribute.context); - if (color == null && TagManager.isStaticParsing) { - return null; - } - StringBuilder hex = new StringBuilder(Integer.toHexString(color.asRGB())); - while (hex.length() < 6) { - hex.insert(0, "0"); - } - return new ElementTag(ChatColor.COLOR_CHAR + "[color=#" + hex + "]" + object.asString() + ChatColor.COLOR_CHAR + "[reset=color]"); - } - if (colorOut == null) { - try { - ChatColor color = ChatColor.of(colorName.toUpperCase()); - if (color.getColor() == null) { - if (!TagManager.isStaticParsing) { - attribute.echoError("Color '" + colorName + "' is valid but is a format code not a real color (for ElementTag.color[...])."); - } - return null; - } - String colorStr = color.toString().replace(String.valueOf(ChatColor.COLOR_CHAR), "").replace("x", "#"); - colorOut = ChatColor.COLOR_CHAR + "[color=" + colorStr + "]"; - } - catch (IllegalArgumentException ex) { - ColorTag color = ColorTag.valueOf(colorName, attribute.context); - if (color != null) { - StringBuilder hex = new StringBuilder(Integer.toHexString(color.asRGB())); - while (hex.length() < 6) { - hex.insert(0, "0"); - } - return new ElementTag(ChatColor.COLOR_CHAR + "[color=#" + hex + "]" + object.asString() + ChatColor.COLOR_CHAR + "[reset=color]"); - } - if (!TagManager.isStaticParsing) { - attribute.echoError("Color '" + colorName + "' doesn't exist (for ElementTag.color[...])."); - } - return null; - } - } - return new ElementTag(colorOut + object.asString() + ChatColor.COLOR_CHAR + "[reset=color]"); - }); - - // <--[tag] - // @attribute ]> - // @returns ElementTag - // @group text manipulation - // @description - // Makes the input text display with the input font name. Equivalent to "<&font[new-font]><&font[new-font].end_format>" - // The default font is "minecraft:default". - // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. - // --> - ElementTag.tagProcessor.registerStaticTag(ElementTag.class, ElementTag.class, "font", (attribute, object, fontName) -> { - return new ElementTag(ChatColor.COLOR_CHAR + "[font=" + fontName + "]" + object.asString() + ChatColor.COLOR_CHAR + "[reset=font]"); - }); - - // <--[tag] - // @attribute )]> - // @returns ElementTag - // @group text manipulation - // @description - // Returns the element with rainbow colors applied. - // Optionally, specify a color pattern to follow. By default, this is "4c6e2ab319d5". - // That is, a repeating color of: Red, Orange, Yellow, Green, Cyan, Blue, Purple. - // --> - ElementTag.tagProcessor.registerStaticTag(ElementTag.class, "rainbow", (attribute, object) -> { - String str = object.asString(); - String pattern = "4c6e2ab319d5"; - if (attribute.hasParam()) { - pattern = attribute.getParam(); - } - StringBuilder output = new StringBuilder(str.length() * 3); - for (int i = 0; i < str.length(); i++) { - output.append(ChatColor.COLOR_CHAR).append(pattern.charAt(i % pattern.length())).append(str.charAt(i)); - } - return new ElementTag(output.toString()); - }); - - // <--[tag] - // @attribute )]> - // @returns ElementTag - // @group text manipulation - // @description - // Returns the element with RGB rainbow colors applied. - // Optionally, specify a length (how many characters before the colors repeat). If unspecified, will use the input element length. - // If the element starts with a hex color code, that will be used as the starting color of the rainbow. - // --> - ElementTag.tagProcessor.registerStaticTag(ElementTag.class, "hex_rainbow", (attribute, object) -> { - String str = object.asString(); - int[] HSB = new int[] { 0, 255, 255 }; - if (str.startsWith(ChatColor.COLOR_CHAR + "x") && str.length() > 14) { - char[] colors = new char[6]; - for (int i = 0; i < 6; i++) { - colors[i] = str.charAt(3 + (i * 2)); - } - int rgb = Integer.parseInt(new String(colors), 16); - HSB = ColorTag.fromRGB(rgb).toHSB(); - str = str.substring(14); - } - float hue = HSB[0] / 255f; - int length = ChatColor.stripColor(str).length(); - if (length == 0) { - return new ElementTag(""); - } - if (attribute.hasParam()) { - length = attribute.getIntParam(); - } - float increment = 1.0f / length; - String addedFormat = ""; - StringBuilder output = new StringBuilder(str.length() * 8); - for (int i = 0; i < str.length(); i++) { - char c = str.charAt(i); - if (c == ChatColor.COLOR_CHAR && i + 1 < str.length()) { - char c2 = str.charAt(i + 1); - if (FORMAT_CODES_MATCHER.isMatch(c2)) { - addedFormat += String.valueOf(ChatColor.COLOR_CHAR) + c2; - } - else { - addedFormat = ""; - } - i++; - continue; - } - String hex = Integer.toHexString(ColorTag.fromHSB(HSB).asRGB()); - output.append(FormattedTextHelper.stringifyRGBSpigot(hex)).append(addedFormat).append(c); - hue += increment; - HSB[0] = Math.round(hue * 255f); - } - return new ElementTag(output.toString()); - }); - - // <--[tag] - // @attribute ;to=;(style={RGB}/HSB)]> - // @returns ElementTag - // @group text manipulation - // @description - // Returns the element with an RGB color gradient applied, with a unique color per character. - // Specify the input as a map with keys 'from' and 'to' both set to hex colors (or any valid ColorTag). - // You can also choose a style (defaults to RGB): - // "style=RGB" tends to produce smooth gradients, - // "style=HSB" tends to produce bright rainbow-like color patterns. - // @example - // - narrate "" - // @example - // - narrate "" - // @example - // - narrate "" - // @example - // - narrate "" - // --> - ElementTag.tagProcessor.registerStaticTag(ElementTag.class, MapTag.class, "color_gradient", (attribute, object, inputMap) -> { - ColorTag fromColor = inputMap.getRequiredObjectAs("from", ColorTag.class, attribute); - ColorTag toColor = inputMap.getRequiredObjectAs("to", ColorTag.class, attribute); - ElementTag style = inputMap.getElement("style", "RGB"); - if (fromColor == null || toColor == null) { - return null; - } - if (!style.matchesEnum(BukkitElementExtensions.GradientStyle.class)) { - attribute.echoError("Invalid gradient style '" + style + "'"); - return null; - } - String res = doGradient(object.asString(), fromColor, toColor, style.asEnum(GradientStyle.class)); - if (res == null) { - return null; - } - return new ElementTag(res); - }); - - // <--[tag] - // @attribute ;to=]> - // @returns ElementTag - // @group text manipulation - // @deprecated use color_gradient[from=color;to=color;style=HSB] - // @description - // Deprecated in favor of using <@link tag ElementTag.color_gradient> with "style=hsb" - // --> - ElementTag.tagProcessor.registerStaticTag(ElementTag.class, MapTag.class, "hsb_color_gradient", (attribute, object, inputMap) -> { - BukkitImplDeprecations.hsbColorGradientTag.warn(attribute.context); - ColorTag fromColor = inputMap.getRequiredObjectAs("from", ColorTag.class, attribute); - ColorTag toColor = inputMap.getRequiredObjectAs("to", ColorTag.class, attribute); - if (fromColor == null || toColor == null) { - return null; - } - String res = doGradient(object.asString(), fromColor, toColor, GradientStyle.HSB); - if (res == null) { - return null; - } - return new ElementTag(res); - }); - // <--[tag] // @attribute // @returns MapTag @@ -930,96 +407,4 @@ else if (colorName.startsWith("co@")) { } }); } - - public enum GradientStyle { RGB, HSB } - - public static String doGradient(String str, ColorTag fromColor, ColorTag toColor, GradientStyle style) { - int length = FormattedTextHelper.parse(str, ChatColor.WHITE)[0].toPlainText().length(); - if (length == 0) { - return ""; - } - if (fromColor == null || toColor == null) { - return null; - } - float r, g, b, x = 0, rMove, gMove, bMove, xMove = 0, toR, toG, toB; - int[] hsbHelper = null; - if (style == GradientStyle.RGB) { - r = ColorTag.fromSRGB(fromColor.red); - g = ColorTag.fromSRGB(fromColor.green); - b = ColorTag.fromSRGB(fromColor.blue); - x = (float) Math.pow(r + g + b, 0.43); - toR = ColorTag.fromSRGB(toColor.red); - toG = ColorTag.fromSRGB(toColor.green); - toB = ColorTag.fromSRGB(toColor.blue); - float toBrightness = (float) Math.pow(toR + toG + toB, 0.43); - xMove = (toBrightness - x) / length; - } - else { - hsbHelper = fromColor.toHSB(); - int[] toHSB = toColor.toHSB(); - r = hsbHelper[0]; - g = hsbHelper[1]; - b = hsbHelper[2]; - toR = toHSB[0]; - toG = toHSB[1]; - toB = toHSB[2]; - } - rMove = (toR - r) / length; - gMove = (toG - g) / length; - bMove = (toB - b) / length; - String addedFormat = ""; - StringBuilder output = new StringBuilder(str.length() * 15); - for (int i = 0; i < str.length(); i++) { - char c = str.charAt(i); - if (c == ChatColor.COLOR_CHAR && i + 1 < str.length()) { - char c2 = str.charAt(i + 1); - if (FORMAT_CODES_MATCHER.isMatch(c2)) { - addedFormat += String.valueOf(ChatColor.COLOR_CHAR) + c2; - } - else if (c2 == '[') { - int endBracket = str.indexOf(']', i); - if (endBracket != -1) { - addedFormat += str.substring(i, endBracket + 1); - i = endBracket - 1; - } - } - else { - addedFormat = ""; - } - i++; - continue; - } - String hex; - if (style == GradientStyle.RGB) { - // Based on https://stackoverflow.com/questions/22607043/color-gradient-algorithm/49321304#49321304 - float newRed = r, newGreen = g, newBlue = b; - float sum = newRed + newGreen + newBlue; - if (sum > 0) { - float multiplier = (float) Math.pow(x, 1f / 0.43f) / sum; - newRed *= multiplier; - newGreen *= multiplier; - newBlue *= multiplier; - } - newRed = ColorTag.toSRGB(newRed); - newGreen = ColorTag.toSRGB(newGreen); - newBlue = ColorTag.toSRGB(newBlue); - hex = Integer.toHexString((((int) newRed) << 16) | (((int) newGreen) << 8) | ((int) newBlue)); - x += xMove; - } - else { - hsbHelper[0] = (int)r; - hsbHelper[1] = (int)g; - hsbHelper[2] = (int)b; - ColorTag currentColor = ColorTag.fromHSB(hsbHelper); - hex = Integer.toHexString(currentColor.asRGB()); - } - output.append(FormattedTextHelper.stringifyRGBSpigot(hex)).append(addedFormat).append(str.charAt(i)); - r += rMove; - g += gMove; - b += bMove; - } - return output.toString(); - } - - public static AsciiMatcher FORMAT_CODES_MATCHER = new AsciiMatcher("klmnoKLMNO"); } From 65e5d518f481ed98cf7414e3f04dd75839e71c20 Mon Sep 17 00:00:00 2001 From: Aya <31237389+tal5@users.noreply.github.com> Date: Sat, 6 Sep 2025 23:29:02 +0100 Subject: [PATCH 06/24] `PaperElementExtensions`: initial update --- .../properties/PaperElementExtensions.java | 127 +++++++++--------- .../paper/utilities/FormattedTextHelper.java | 49 ++++--- 2 files changed, 97 insertions(+), 79 deletions(-) diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/properties/PaperElementExtensions.java b/paper/src/main/java/com/denizenscript/denizen/paper/properties/PaperElementExtensions.java index d2ab19dc39..99ece2aaa2 100644 --- a/paper/src/main/java/com/denizenscript/denizen/paper/properties/PaperElementExtensions.java +++ b/paper/src/main/java/com/denizenscript/denizen/paper/properties/PaperElementExtensions.java @@ -3,7 +3,6 @@ import com.denizenscript.denizen.nms.NMSHandler; import com.denizenscript.denizen.nms.NMSVersion; import com.denizenscript.denizen.objects.ItemTag; -import com.denizenscript.denizen.objects.properties.bukkit.BukkitElementExtensions; import com.denizenscript.denizen.paper.PaperModule; import com.denizenscript.denizen.paper.utilities.FormattedTextHelper; import com.denizenscript.denizen.paper.utilities.HoverFormatHelper; @@ -18,8 +17,13 @@ import com.denizenscript.denizencore.utilities.AsciiMatcher; import com.denizenscript.denizencore.utilities.CoreUtilities; import net.kyori.adventure.text.event.HoverEvent; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.format.TextColor; import net.kyori.adventure.text.minimessage.MiniMessage; -import net.md_5.bungee.api.ChatColor; +import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; + +import static com.denizenscript.denizen.paper.utilities.FormattedTextHelper.LegacyColor; +import static com.denizenscript.denizen.paper.utilities.FormattedTextHelper.LegacyFormatting; public class PaperElementExtensions { @@ -36,10 +40,9 @@ public static void register() { // This will automatically translate translatable sections // --> ElementTag.tagProcessor.registerStaticTag(ElementTag.class, "strip_color", (attribute, object) -> { - return new ElementTag(FormattedTextHelper.parse(object.asString(), ChatColor.WHITE)[0].toPlainText()); + return new ElementTag(PlainTextComponentSerializer.plainText().serialize(FormattedTextHelper.parse(object.asString(), NamedTextColor.WHITE)), true); }); - // <--[tag] // @attribute // @returns ElementTag @@ -49,7 +52,7 @@ public static void register() { // Inverts <@link tag ElementTag.from_raw_json>. // --> ElementTag.tagProcessor.registerStaticTag(ElementTag.class, "to_raw_json", (attribute, object) -> { - return new ElementTag(FormattedTextHelper.componentToJson(FormattedTextHelper.parse(object.asString(), ChatColor.WHITE))); + return new ElementTag(PaperModule.componentToJson(FormattedTextHelper.parse(object.asString(), NamedTextColor.WHITE)), true); }); // <--[tag] @@ -61,7 +64,7 @@ public static void register() { // Inverts <@link tag ElementTag.to_raw_json>. // --> ElementTag.tagProcessor.registerStaticTag(ElementTag.class, "from_raw_json", (attribute, object) -> { - return new ElementTag(FormattedTextHelper.stringify(FormattedTextHelper.parseJson(object.asString()))); + return new ElementTag(FormattedTextHelper.stringify(PaperModule.jsonToComponent(object.asString()))); }); // <--[tag] @@ -76,7 +79,7 @@ public static void register() { // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. // --> ElementTag.tagProcessor.registerStaticTag(ElementTag.class, "optimize_json", (attribute, object) -> { - String opti = ChatColor.COLOR_CHAR + "[optimize=true]"; + String opti = FormattedTextHelper.LEGACY_SECTION + "[optimize=true]"; if (object.asString().contains(opti)) { return object; } @@ -94,7 +97,7 @@ public static void register() { // - narrate "You can ]> to see what you held!" // --> ElementTag.tagProcessor.registerStaticTag(ElementTag.class, ItemTag.class, "hover_item", (attribute, object, item) -> { - return new ElementTag(ChatColor.COLOR_CHAR + "[hover=SHOW_ITEM;" + FormattedTextHelper.escape(item.identify()) + "]" + object.asString() + ChatColor.COLOR_CHAR + "[/hover]"); + return new ElementTag(FormattedTextHelper.LEGACY_SECTION + "[hover=SHOW_ITEM;" + FormattedTextHelper.escape(item.identify()) + "]" + object.asString() + FormattedTextHelper.LEGACY_SECTION + "[/hover]", true); }); // <--[tag] @@ -106,7 +109,7 @@ public static void register() { // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. // --> ElementTag.tagProcessor.registerTag(ElementTag.class, ObjectTag.class, "on_hover", (attribute, object, hover) -> { // non-static due to hacked sub-tag - HoverEvent.Action type = HoverEvent.Action.SHOW_TEXT; + HoverEvent.Action type = HoverEvent.Action.SHOW_TEXT; // <--[tag] // @attribute ].type[]> @@ -122,7 +125,11 @@ public static void register() { // --> if (attribute.startsWith("type", 2)) { attribute.fulfill(1); - type = ElementTag.asEnum(HoverEvent.Action.class, attribute.getParam()); + if (!attribute.hasParam()) { + attribute.echoError("Must specify an hover type."); + return null; + } + type = HoverEvent.Action.NAMES.value(CoreUtilities.toLowerCase(attribute.getParam())); if (type == null) { attribute.echoError("Invalid hover type specified."); return null; @@ -132,8 +139,8 @@ public static void register() { if (hoverData == null) { return null; } - return new ElementTag(ChatColor.COLOR_CHAR + "[hover=" + type + ';' + FormattedTextHelper.escape(hoverData) + ']' - + object.asString() + ChatColor.COLOR_CHAR + "[/hover]", true); + return new ElementTag(FormattedTextHelper.LEGACY_SECTION + "[hover=" + type + ';' + FormattedTextHelper.escape(hoverData) + ']' + + object.asString() + FormattedTextHelper.LEGACY_SECTION + "[/hover]", true); }); // <--[tag] @@ -147,7 +154,7 @@ public static void register() { // - narrate "You can to learn about Denizen!" // --> ElementTag.tagProcessor.registerStaticTag(ElementTag.class, ElementTag.class, "click_url", (attribute, object, url) -> { - return new ElementTag(ChatColor.COLOR_CHAR + "[click=OPEN_URL;" + FormattedTextHelper.escape(url.toString()) + "]" + object.asString() + ChatColor.COLOR_CHAR + "[/click]"); + return new ElementTag(FormattedTextHelper.LEGACY_SECTION + "[click=OPEN_URL;" + FormattedTextHelper.escape(url.asString()) + "]" + object.asString() + FormattedTextHelper.LEGACY_SECTION + "[/click]", true); }); // <--[tag] @@ -162,7 +169,7 @@ public static void register() { // - narrate "You can to say hello to an NPC's interact script!" // --> ElementTag.tagProcessor.registerStaticTag(ElementTag.class, ElementTag.class, "click_chat", (attribute, object, chat) -> { - return new ElementTag(ChatColor.COLOR_CHAR + "[click=RUN_COMMAND;/denizenclickable chat " + FormattedTextHelper.escape(chat.toString()) + "]" + object.asString() + ChatColor.COLOR_CHAR + "[/click]"); + return new ElementTag(FormattedTextHelper.LEGACY_SECTION + "[click=RUN_COMMAND;/denizenclickable chat " + FormattedTextHelper.escape(chat.asString()) + "]" + object.asString() + FormattedTextHelper.LEGACY_SECTION + "[/click]", true); }); // <--[tag] @@ -200,8 +207,8 @@ public static void register() { type = attribute.getContext(2); attribute.fulfill(1); } - return new ElementTag(ChatColor.COLOR_CHAR + "[click=" + type + ";" + FormattedTextHelper.escape(command.asString()) + "]" - + object.asString() + ChatColor.COLOR_CHAR + "[/click]"); + return new ElementTag(FormattedTextHelper.LEGACY_SECTION + "[click=" + type + ";" + FormattedTextHelper.escape(command.asString()) + "]" + + object.asString() + FormattedTextHelper.LEGACY_SECTION + "[/click]", true); }); // <--[tag] @@ -213,8 +220,8 @@ public static void register() { // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. // --> ElementTag.tagProcessor.registerStaticTag(ElementTag.class, ElementTag.class, "with_insertion", (attribute, object, insertion) -> { - return new ElementTag(ChatColor.COLOR_CHAR + "[insertion=" + FormattedTextHelper.escape(insertion.asString()) + "]" - + object.asString() + ChatColor.COLOR_CHAR + "[/insertion]"); + return new ElementTag(FormattedTextHelper.LEGACY_SECTION + "[insertion=" + FormattedTextHelper.escape(insertion.asString()) + "]" + + object.asString() + FormattedTextHelper.LEGACY_SECTION + "[/insertion]", true); }); // <--[tag] @@ -227,8 +234,8 @@ public static void register() { // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. // --> ElementTag.tagProcessor.registerStaticTag(ElementTag.class, "no_reset", (attribute, object) -> { - if (object.asString().length() == 2 && object.asString().charAt(0) == ChatColor.COLOR_CHAR) { - return new ElementTag(ChatColor.COLOR_CHAR + "[color=" + object.asString().charAt(1) + "]"); + if (object.asString().length() == 2 && object.asString().charAt(0) == FormattedTextHelper.LEGACY_SECTION) { + return new ElementTag(FormattedTextHelper.LEGACY_SECTION + "[color=" + object.asString().charAt(1) + "]", true); } return null; }); @@ -243,11 +250,11 @@ public static void register() { // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. // --> ElementTag.tagProcessor.registerStaticTag(ElementTag.class, "end_format", (attribute, object) -> { - if (object.asString().length() == 2 && object.asString().charAt(0) == ChatColor.COLOR_CHAR) { - return new ElementTag(ChatColor.COLOR_CHAR + "[reset=" + object.asString().charAt(1) + "]"); + if (object.asString().length() == 2 && object.asString().charAt(0) == FormattedTextHelper.LEGACY_SECTION) { + return new ElementTag(FormattedTextHelper.LEGACY_SECTION + "[reset=" + object.asString().charAt(1) + "]", true); } - else if (object.asString().startsWith(ChatColor.COLOR_CHAR + "[font=") && object.asString().endsWith("]")) { - return new ElementTag(ChatColor.COLOR_CHAR + "[reset=font]"); + else if (object.asString().startsWith(FormattedTextHelper.LEGACY_SECTION + "[font=") && object.asString().endsWith("]")) { + return new ElementTag(FormattedTextHelper.LEGACY_SECTION + "[reset=font]", true); } return null; }); @@ -261,7 +268,7 @@ else if (object.asString().startsWith(ChatColor.COLOR_CHAR + "[font=") && object // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. // --> ElementTag.tagProcessor.registerStaticTag(ElementTag.class, "italicize", (attribute, object) -> { - return new ElementTag(ChatColor.ITALIC + object.asString() + ChatColor.COLOR_CHAR + "[reset=o]"); + return new ElementTag(LegacyFormatting.ITALIC + object.asString() + FormattedTextHelper.LEGACY_SECTION + "[reset=o]", true); }); // <--[tag] @@ -273,7 +280,7 @@ else if (object.asString().startsWith(ChatColor.COLOR_CHAR + "[font=") && object // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. // --> ElementTag.tagProcessor.registerStaticTag(ElementTag.class, "bold", (attribute, object) -> { - return new ElementTag(ChatColor.BOLD + object.asString() + ChatColor.COLOR_CHAR + "[reset=l]"); + return new ElementTag(LegacyFormatting.BOLD + object.asString() + FormattedTextHelper.LEGACY_SECTION + "[reset=l]", true); }); // <--[tag] @@ -285,7 +292,7 @@ else if (object.asString().startsWith(ChatColor.COLOR_CHAR + "[font=") && object // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. // --> ElementTag.tagProcessor.registerStaticTag(ElementTag.class, "underline", (attribute, object) -> { - return new ElementTag(ChatColor.UNDERLINE + object.asString() + ChatColor.COLOR_CHAR + "[reset=n]"); + return new ElementTag(LegacyFormatting.UNDERLINE + object.asString() + FormattedTextHelper.LEGACY_SECTION + "[reset=n]", true); }); // <--[tag] @@ -297,7 +304,7 @@ else if (object.asString().startsWith(ChatColor.COLOR_CHAR + "[font=") && object // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. // --> ElementTag.tagProcessor.registerStaticTag(ElementTag.class, "strikethrough", (attribute, object) -> { - return new ElementTag(ChatColor.STRIKETHROUGH + object.asString() + ChatColor.COLOR_CHAR + "[reset=m]"); + return new ElementTag(LegacyFormatting.STRIKETHROUGH + object.asString() + FormattedTextHelper.LEGACY_SECTION + "[reset=m]", true); }); // <--[tag] @@ -309,7 +316,7 @@ else if (object.asString().startsWith(ChatColor.COLOR_CHAR + "[font=") && object // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. // --> ElementTag.tagProcessor.registerStaticTag(ElementTag.class, "obfuscate", (attribute, object) -> { - return new ElementTag(ChatColor.MAGIC + object.asString() + ChatColor.COLOR_CHAR + "[reset=k]"); + return new ElementTag(LegacyFormatting.OBFUSCATED + object.asString() + FormattedTextHelper.LEGACY_SECTION + "[reset=k]", true); }); // <--[tag] @@ -327,7 +334,7 @@ else if (object.asString().startsWith(ChatColor.COLOR_CHAR + "[font=") && object if (color == null) { return null; } - return new ElementTag(ChatColor.COLOR_CHAR + "[color=f]" + color + object.asString() + ChatColor.COLOR_CHAR + "[reset=color]"); + return new ElementTag(FormattedTextHelper.LEGACY_SECTION + "[color=f]" + color + object.asString() + FormattedTextHelper.LEGACY_SECTION + "[reset=color]", true); }); // <--[tag] @@ -343,16 +350,16 @@ else if (object.asString().startsWith(ChatColor.COLOR_CHAR + "[font=") && object String colorName = colorElement.asString(); String colorOut = null; if (colorName.length() == 1) { - ChatColor color = ChatColor.getByChar(colorName.charAt(0)); + TextColor color = LegacyColor.fromChar(colorName.charAt(0)); if (color != null) { colorOut = color.toString(); } } else if (colorName.length() == 7 && colorName.startsWith("#")) { - return new ElementTag(ChatColor.COLOR_CHAR + "[color=" + colorName + "]" + object.asString() + ChatColor.COLOR_CHAR + "[reset=color]"); + return new ElementTag(FormattedTextHelper.LEGACY_SECTION + "[color=" + colorName + "]" + object.asString() + FormattedTextHelper.LEGACY_SECTION + "[reset=color]", true); } - else if (colorName.length() == 14 && colorName.startsWith(ChatColor.COLOR_CHAR + "x")) { - return new ElementTag(ChatColor.COLOR_CHAR + "[color=#" + CoreUtilities.replace(colorName.substring(2), String.valueOf(ChatColor.COLOR_CHAR), "") + "]" + object.asString() + ChatColor.COLOR_CHAR + "[reset=color]"); + else if (colorName.length() == 14 && colorName.startsWith(FormattedTextHelper.LEGACY_SECTION + "x")) { + return new ElementTag(FormattedTextHelper.LEGACY_SECTION + "[color=#" + CoreUtilities.replace(colorName.substring(2), String.valueOf(FormattedTextHelper.LEGACY_SECTION), "") + "]" + object.asString() + FormattedTextHelper.LEGACY_SECTION + "[reset=color]", true); } else if (colorName.startsWith("co@")) { ColorTag color = ColorTag.valueOf(colorName, attribute.context); @@ -363,36 +370,28 @@ else if (colorName.startsWith("co@")) { while (hex.length() < 6) { hex.insert(0, "0"); } - return new ElementTag(ChatColor.COLOR_CHAR + "[color=#" + hex + "]" + object.asString() + ChatColor.COLOR_CHAR + "[reset=color]"); + return new ElementTag(FormattedTextHelper.LEGACY_SECTION + "[color=#" + hex + "]" + object.asString() + FormattedTextHelper.LEGACY_SECTION + "[reset=color]", true); } if (colorOut == null) { - try { - ChatColor color = ChatColor.of(colorName.toUpperCase()); - if (color.getColor() == null) { - if (!TagManager.isStaticParsing) { - attribute.echoError("Color '" + colorName + "' is valid but is a format code not a real color (for ElementTag.color[...])."); - } - return null; - } - String colorStr = color.toString().replace(String.valueOf(ChatColor.COLOR_CHAR), "").replace("x", "#"); - colorOut = ChatColor.COLOR_CHAR + "[color=" + colorStr + "]"; - } - catch (IllegalArgumentException ex) { + NamedTextColor namedColor = NamedTextColor.NAMES.value(CoreUtilities.toLowerCase(colorName)); + if (namedColor == null) { ColorTag color = ColorTag.valueOf(colorName, attribute.context); if (color != null) { StringBuilder hex = new StringBuilder(Integer.toHexString(color.asRGB())); while (hex.length() < 6) { hex.insert(0, "0"); } - return new ElementTag(ChatColor.COLOR_CHAR + "[color=#" + hex + "]" + object.asString() + ChatColor.COLOR_CHAR + "[reset=color]"); + return new ElementTag(FormattedTextHelper.LEGACY_SECTION + "[color=#" + hex + "]" + object.asString() + FormattedTextHelper.LEGACY_SECTION + "[reset=color]", true); } if (!TagManager.isStaticParsing) { attribute.echoError("Color '" + colorName + "' doesn't exist (for ElementTag.color[...])."); } return null; } + colorOut = FormattedTextHelper.LEGACY_SECTION + "[color=" + LegacyColor.fromModern(namedColor).colorChar + "]"; + } - return new ElementTag(colorOut + object.asString() + ChatColor.COLOR_CHAR + "[reset=color]"); + return new ElementTag(colorOut + object.asString() + FormattedTextHelper.LEGACY_SECTION + "[reset=color]", true); }); // <--[tag] @@ -405,7 +404,7 @@ else if (colorName.startsWith("co@")) { // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. // --> ElementTag.tagProcessor.registerStaticTag(ElementTag.class, ElementTag.class, "font", (attribute, object, fontName) -> { - return new ElementTag(ChatColor.COLOR_CHAR + "[font=" + fontName + "]" + object.asString() + ChatColor.COLOR_CHAR + "[reset=font]"); + return new ElementTag(FormattedTextHelper.LEGACY_SECTION + "[font=" + fontName + "]" + object.asString() + FormattedTextHelper.LEGACY_SECTION + "[reset=font]", true); }); // <--[tag] @@ -425,9 +424,9 @@ else if (colorName.startsWith("co@")) { } StringBuilder output = new StringBuilder(str.length() * 3); for (int i = 0; i < str.length(); i++) { - output.append(ChatColor.COLOR_CHAR).append(pattern.charAt(i % pattern.length())).append(str.charAt(i)); + output.append(FormattedTextHelper.LEGACY_SECTION).append(pattern.charAt(i % pattern.length())).append(str.charAt(i)); } - return new ElementTag(output.toString()); + return new ElementTag(output.toString(), true); }); // <--[tag] @@ -442,7 +441,7 @@ else if (colorName.startsWith("co@")) { ElementTag.tagProcessor.registerStaticTag(ElementTag.class, "hex_rainbow", (attribute, object) -> { String str = object.asString(); int[] HSB = new int[] { 0, 255, 255 }; - if (str.startsWith(ChatColor.COLOR_CHAR + "x") && str.length() > 14) { + if (str.startsWith(FormattedTextHelper.LEGACY_SECTION + "x") && str.length() > 14) { char[] colors = new char[6]; for (int i = 0; i < 6; i++) { colors[i] = str.charAt(3 + (i * 2)); @@ -452,9 +451,9 @@ else if (colorName.startsWith("co@")) { str = str.substring(14); } float hue = HSB[0] / 255f; - int length = ChatColor.stripColor(str).length(); + int length = PlainTextComponentSerializer.plainText().serialize(FormattedTextHelper.parse(str, NamedTextColor.WHITE)).length(); if (length == 0) { - return new ElementTag(""); + return new ElementTag("", true); } if (attribute.hasParam()) { length = attribute.getIntParam(); @@ -464,10 +463,10 @@ else if (colorName.startsWith("co@")) { StringBuilder output = new StringBuilder(str.length() * 8); for (int i = 0; i < str.length(); i++) { char c = str.charAt(i); - if (c == ChatColor.COLOR_CHAR && i + 1 < str.length()) { + if (c == FormattedTextHelper.LEGACY_SECTION && i + 1 < str.length()) { char c2 = str.charAt(i + 1); if (FORMAT_CODES_MATCHER.isMatch(c2)) { - addedFormat += String.valueOf(ChatColor.COLOR_CHAR) + c2; + addedFormat += String.valueOf(FormattedTextHelper.LEGACY_SECTION) + c2; } else { addedFormat = ""; @@ -480,7 +479,7 @@ else if (colorName.startsWith("co@")) { hue += increment; HSB[0] = Math.round(hue * 255f); } - return new ElementTag(output.toString()); + return new ElementTag(output.toString(), true); }); // <--[tag] @@ -509,7 +508,7 @@ else if (colorName.startsWith("co@")) { if (fromColor == null || toColor == null) { return null; } - if (!style.matchesEnum(BukkitElementExtensions.GradientStyle.class)) { + if (!style.matchesEnum(GradientStyle.class)) { attribute.echoError("Invalid gradient style '" + style + "'"); return null; } @@ -517,7 +516,7 @@ else if (colorName.startsWith("co@")) { if (res == null) { return null; } - return new ElementTag(res); + return new ElementTag(res, true); }); // <--[tag] @@ -539,7 +538,7 @@ else if (colorName.startsWith("co@")) { if (res == null) { return null; } - return new ElementTag(res); + return new ElementTag(res, true); }); if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_18)) { @@ -575,7 +574,7 @@ else if (colorName.startsWith("co@")) { public enum GradientStyle { RGB, HSB } public static String doGradient(String str, ColorTag fromColor, ColorTag toColor, GradientStyle style) { - int length = FormattedTextHelper.parse(str, ChatColor.WHITE)[0].toPlainText().length(); + int length = PlainTextComponentSerializer.plainText().serialize(FormattedTextHelper.parse(str, NamedTextColor.WHITE)).length(); if (length == 0) { return ""; } @@ -612,10 +611,10 @@ public static String doGradient(String str, ColorTag fromColor, ColorTag toColor StringBuilder output = new StringBuilder(str.length() * 15); for (int i = 0; i < str.length(); i++) { char c = str.charAt(i); - if (c == ChatColor.COLOR_CHAR && i + 1 < str.length()) { + if (c == FormattedTextHelper.LEGACY_SECTION && i + 1 < str.length()) { char c2 = str.charAt(i + 1); if (FORMAT_CODES_MATCHER.isMatch(c2)) { - addedFormat += String.valueOf(ChatColor.COLOR_CHAR) + c2; + addedFormat += String.valueOf(FormattedTextHelper.LEGACY_SECTION) + c2; } else if (c2 == '[') { int endBracket = str.indexOf(']', i); diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/FormattedTextHelper.java b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/FormattedTextHelper.java index b49c505a2b..7058be4b36 100644 --- a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/FormattedTextHelper.java +++ b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/FormattedTextHelper.java @@ -2,7 +2,7 @@ import com.denizenscript.denizen.nms.NMSHandler; import com.denizenscript.denizen.nms.NMSVersion; -import com.denizenscript.denizen.objects.properties.bukkit.BukkitElementExtensions; +import com.denizenscript.denizen.paper.properties.PaperElementExtensions; import com.denizenscript.denizen.utilities.Utilities; import com.denizenscript.denizencore.objects.core.ColorTag; import com.denizenscript.denizencore.objects.core.ElementTag; @@ -70,30 +70,49 @@ public enum LegacyColor { YELLOW('e', NamedTextColor.YELLOW), WHITE('f', NamedTextColor.WHITE); - public final String formatString; + public final char colorChar; + public final String colorString; public final NamedTextColor color; - LegacyColor(char formatChar, NamedTextColor color) { - this.formatString = new String(new char[]{LEGACY_SECTION, formatChar}); + LegacyColor(char colorChar, NamedTextColor color) { + this.colorChar = colorChar; + this.colorString = new String(new char[]{LEGACY_SECTION, colorChar}); this.color = color; } @Override public String toString() { - return formatString; + return colorString; + } + + private static int calculateIndex(char colorChar) { + if (colorChar >= '0' && colorChar <= '9') { + return colorChar - '0'; + } + else if (colorChar >= 'a' && colorChar <= 'f') { + return colorChar - 'a' + 10; + } + else { + return -1; + } + } + + public static NamedTextColor fromChar(char colorChar) { + int index = calculateIndex(colorChar); + return index != -1 ? FROM_LEGACY[index] : null; } public static LegacyColor fromModern(NamedTextColor textColor) { return TO_LEGACY.get(textColor); } - private static final Map TO_LEGACY; + private static final Map TO_LEGACY = new IdentityHashMap<>(16); + private static final NamedTextColor[] FROM_LEGACY = new NamedTextColor[16]; static { - LegacyColor[] legacyColors = values(); - TO_LEGACY = new IdentityHashMap<>(legacyColors.length); - for (LegacyColor legacyColor : legacyColors) { + for (LegacyColor legacyColor : values()) { TO_LEGACY.put(legacyColor.color, legacyColor); + FROM_LEGACY[calculateIndex(legacyColor.colorChar)] = legacyColor.color; } } } @@ -470,7 +489,7 @@ else if (colorCodesOrReset.isMatch(c)) { root.append(nextText); } nextText = getCleanRef(); - nextText.color(LegacyComponentSerializer.parseChar(c).color()); + nextText.color(LegacyColor.fromChar(c)); lastStart = firstChar + 2; } else { // format code @@ -583,7 +602,7 @@ public static Component parseInternal(String str, TextColor baseColor, boolean c if (str.length() > 3 && str.startsWith((LEGACY_SECTION + "")) && hexMatcher.isMatch(str.charAt(1)) && str.startsWith(LEGACY_SECTION + "[translate=", 2) && str.indexOf(']') == str.length() - 1) { // eg "&6&[translate=block.minecraft.ominous_banner]" Component component = parseTranslatable(str.substring("&[translate=".length() + 2, str.length() - 1), baseColor, optimize); - component.color(LegacyComponentSerializer.parseChar(str.charAt(1)).color()); + component.color(LegacyColor.fromChar(str.charAt(1))); return component; } } @@ -720,7 +739,7 @@ else if (innardType.equals("color")) { String colorChar = innardBase.get(1); TextColor color = null; if (colorChar.length() == 1) { - color = LegacyComponentSerializer.parseChar(colorChar.charAt(0)).color(); + color = LegacyColor.fromChar(colorChar.charAt(0)); } else if (colorChar.length() == 7) { color = TextColor.fromHexString(CoreUtilities.toUpperCase(colorChar)); @@ -746,7 +765,7 @@ else if (innardType.equals("gradient") && innardParts.size() == 2) { String from = innardBase.get(1), to = innardParts.get(0), style = innardParts.get(1); ColorTag fromColor = ColorTag.valueOf(from, CoreUtilities.noDebugContext); ColorTag toColor = ColorTag.valueOf(to, CoreUtilities.noDebugContext); - BukkitElementExtensions.GradientStyle styleEnum = new ElementTag(style).asEnum(BukkitElementExtensions.GradientStyle.class); + PaperElementExtensions.GradientStyle styleEnum = new ElementTag(style).asEnum(PaperElementExtensions.GradientStyle.class); if (fromColor == null || toColor == null || styleEnum == null) { if (CoreConfiguration.debugVerbose) { Debug.echoError("Text parse issue: cannot interpret gradient input '" + innards + "'."); @@ -757,7 +776,7 @@ else if (innardType.equals("gradient") && innardParts.size() == 2) { if (endIndex == -1) { endIndex = str.length(); } - String gradientText = BukkitElementExtensions.doGradient(str.substring(endBracket + 1, endIndex), fromColor, toColor, styleEnum); + String gradientText = PaperElementExtensions.doGradient(str.substring(endBracket + 1, endIndex), fromColor, toColor, styleEnum); lastText.append(parseInternal(gradientText, baseColor, false, optimize)); endBracket = endIndex - 1; } @@ -802,7 +821,7 @@ else if (colorCodesOrReset.isMatch(code)) { base.append(nextText); } nextText = Component.text(); - nextText.color(LegacyComponentSerializer.parseChar(code).color()); + nextText.color(LegacyColor.fromChar(code)); } else if (code == 'x') { if (i + 13 >= chars.length) { From 35bbac4d7d66250ea03efc1ab90cbce5d24cae78 Mon Sep 17 00:00:00 2001 From: Aya <31237389+tal5@users.noreply.github.com> Date: Sun, 7 Sep 2025 12:20:42 +0100 Subject: [PATCH 07/24] `TextTagBase`: copy over to `TextFormattingTags` --- .../denizen/paper/PaperModule.java | 2 + .../paper/tags/TextFormattingTags.java | 340 ++++++++++++++++++ .../denizen/tags/core/TextTagBase.java | 327 ----------------- 3 files changed, 342 insertions(+), 327 deletions(-) create mode 100644 paper/src/main/java/com/denizenscript/denizen/paper/tags/TextFormattingTags.java diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/PaperModule.java b/paper/src/main/java/com/denizenscript/denizen/paper/PaperModule.java index 58ff60ed66..fa4da24c82 100644 --- a/paper/src/main/java/com/denizenscript/denizen/paper/PaperModule.java +++ b/paper/src/main/java/com/denizenscript/denizen/paper/PaperModule.java @@ -9,6 +9,7 @@ import com.denizenscript.denizen.paper.events.*; import com.denizenscript.denizen.paper.properties.*; import com.denizenscript.denizen.paper.tags.PaperTagBase; +import com.denizenscript.denizen.paper.tags.TextFormattingTags; import com.denizenscript.denizen.paper.utilities.PaperAPIToolsImpl; import com.denizenscript.denizen.utilities.FormattedTextHelper; import com.denizenscript.denizen.utilities.PaperAPITools; @@ -135,6 +136,7 @@ public static void init() { PaperWorldExtensions.register(); // Paper Tags new PaperTagBase(); + new TextFormattingTags(); // Other helpers Bukkit.getPluginManager().registerEvents(new PaperEventHelpers(), Denizen.getInstance()); diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/tags/TextFormattingTags.java b/paper/src/main/java/com/denizenscript/denizen/paper/tags/TextFormattingTags.java new file mode 100644 index 0000000000..a8ceb5a45f --- /dev/null +++ b/paper/src/main/java/com/denizenscript/denizen/paper/tags/TextFormattingTags.java @@ -0,0 +1,340 @@ +package com.denizenscript.denizen.paper.tags; + +import com.denizenscript.denizen.objects.properties.bukkit.BukkitElementExtensions; +import com.denizenscript.denizen.utilities.BukkitImplDeprecations; +import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.HoverFormatHelper; +import com.denizenscript.denizencore.objects.ObjectTag; +import com.denizenscript.denizencore.objects.core.ColorTag; +import com.denizenscript.denizencore.objects.core.ElementTag; +import com.denizenscript.denizencore.objects.core.ListTag; +import com.denizenscript.denizencore.objects.core.MapTag; +import com.denizenscript.denizencore.tags.TagManager; +import com.denizenscript.denizencore.tags.core.EscapeTagUtil; +import com.denizenscript.denizencore.utilities.CoreUtilities; +import net.md_5.bungee.api.chat.HoverEvent; +import org.bukkit.ChatColor; + +public class TextFormattingTags { + + public TextFormattingTags() { + + // <--[tag] + // @attribute <&hover[]> + // @returns ElementTag + // @description + // Returns a special chat code that makes the following text display the input hover text when the mouse is left over it. + // This tag must be followed by an <&end_hover> tag. + // For example: - narrate "There is a <&hover[you found it!]>secret<&end_hover> in this message!" + // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. + // --> + TagManager.registerTagHandler(ElementTag.class, ObjectTag.class, "&hover", (attribute, hover) -> { // Cannot be static due to hacked sub-tag + + // <--[tag] + // @attribute <&hover[].type[]> + // @returns ElementTag + // @description + // Returns a special chat code that makes the following text display the input hover text when the mouse is left over it. + // This tag must be followed by an <&end_hover> tag. + // Available hover types: SHOW_TEXT, SHOW_ITEM, or SHOW_ENTITY. + // For example: - narrate "There is a <&hover[you found it!].type[SHOW_TEXT]>secret<&end_hover> in this message!" + // Note: for "SHOW_ITEM", replace the text with a valid ItemTag. For "SHOW_ENTITY", replace the text with a valid spawned EntityTag (requires F3+H to see entities). + // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. + // --> + HoverEvent.Action type = HoverEvent.Action.SHOW_TEXT; + if (attribute.startsWith("type", 2)) { + attribute.fulfill(1); + type = ElementTag.asEnum(HoverEvent.Action.class, attribute.getParam()); + if (type == null) { + attribute.echoError("Invalid hover type specified."); + return null; + } + } + String hoverData = HoverFormatHelper.parseObjectToHover(hover, type, attribute); + if (hoverData == null) { + return null; + } + return new ElementTag(ChatColor.COLOR_CHAR + "[hover=" + type + ';' + FormattedTextHelper.escape(hoverData) + ']', true); + }); + + // <--[tag] + // @attribute <&click[]> + // @returns ElementTag + // @description + // Returns a special chat code that makes the following text execute the input command line value when clicked. + // To execute a command "/" should be used at the start. Otherwise, it will display as chat. + // This tag must be followed by an <&end_click> tag. + // For example: - narrate "You can <&click[wow]>click here<&end_click> to say wow!" + // For example: - narrate "You can <&click[/help]>click here<&end_click> for help!" + // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. + // --> + TagManager.registerTagHandler(ElementTag.class, "&click", (attribute) -> { // Cannot be static due to hacked sub-tag + if (!attribute.hasParam()) { + return null; + } + String clickText = attribute.getParam(); + + // <--[tag] + // @attribute <&click[].type[]> + // @returns ElementTag + // @description + // Returns a special chat code that makes the following text execute the input command when clicked. + // This tag must be followed by an <&end_click> tag. + // Available command types: OPEN_URL, OPEN_FILE, RUN_COMMAND, SUGGEST_COMMAND, COPY_TO_CLIPBOARD, or CHANGE_PAGE. + // For example: - narrate "You can <&click[https://denizenscript.com].type[OPEN_URL]>click here<&end_click> to learn about Denizen!" + // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. + // --> + String type = "RUN_COMMAND"; + if (attribute.startsWith("type", 2)) { + type = attribute.getContext(2); + attribute.fulfill(1); + } + return new ElementTag(ChatColor.COLOR_CHAR + "[click=" + type + ";" + FormattedTextHelper.escape(clickText) + "]"); + }); + + // <--[tag] + // @attribute <&insertion[]> + // @returns ElementTag + // @description + // Returns a special chat code that makes the following text insert the input message to chat when shift-clicked. + // This tag must be followed by an <&end_insertion> tag. + // For example: - narrate "You can <&insertion[wow]>click here<&end_insertion> to add 'wow' to your chat!" + // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. + // --> + TagManager.registerStaticTagBaseHandler(ElementTag.class, "&insertion", (attribute) -> { + if (!attribute.hasParam()) { + return null; + } + String insertText = attribute.getParam(); + return new ElementTag(ChatColor.COLOR_CHAR + "[insertion=" + FormattedTextHelper.escape(insertText) + "]"); + }); + + // <--[tag] + // @attribute <&end_click> + // @returns ElementTag + // @description + // Returns a special chat code that ends a '&click' tag. + // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. + // --> + TagManager.registerStaticTagBaseHandler(ElementTag.class, "&end_click", (attribute) -> { + return new ElementTag(ChatColor.COLOR_CHAR + "[/click]"); + }); + + // <--[tag] + // @attribute <&end_hover> + // @returns ElementTag + // @description + // Returns a special chat code that ends a '&hover' tag. + // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. + // --> + TagManager.registerStaticTagBaseHandler(ElementTag.class, "&end_hover", (attribute) -> { + return new ElementTag(ChatColor.COLOR_CHAR + "[/hover]"); + }); + + // <--[tag] + // @attribute <&end_insertion> + // @returns ElementTag + // @description + // Returns a special chat code that ends an '&insertion' tag. + // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. + // --> + TagManager.registerStaticTagBaseHandler(ElementTag.class, "&end_insertion", (attribute) -> { + return new ElementTag(ChatColor.COLOR_CHAR + "[/insertion]"); + }); + + // <--[tag] + // @attribute <&keybind[]> + // @returns ElementTag + // @description + // Returns a special chat code that displays a keybind. + // For example: - narrate "Press your <&keybind[key.jump]> key!" + // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. + // --> + TagManager.registerStaticTagBaseHandler(ElementTag.class, "&keybind", (attribute) -> { + if (!attribute.hasParam()) { + return null; + } + String keybindText = attribute.getParam(); + return new ElementTag(ChatColor.COLOR_CHAR + "[keybind=" + FormattedTextHelper.escape(keybindText) + "]"); + }); + + // <--[tag] + // @attribute <&selector[]> + // @returns ElementTag + // @description + // Returns a special chat code that displays a vanilla selector. + // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. + // --> + TagManager.registerStaticTagBaseHandler(ElementTag.class, "&selector", (attribute) -> { + if (!attribute.hasParam()) { + return null; + } + String selectorText = attribute.getParam(); + return new ElementTag(ChatColor.COLOR_CHAR + "[selector=" + FormattedTextHelper.escape(selectorText) + "]"); + }); + + // <--[tag] + // @attribute <&translate[key=;(fallback=);(with=|...)]> + // @returns ElementTag + // @description + // Returns a special chat code that is read by the client to display an auto-translated message. + // "key" is the translation key. + // Optionally specify "fallback" as text to display when the client can't find a translation for the key. + // Optionally specify "with" as a list of input data for the translatable message (parts of the message that are dynamic). + // Be warned that language keys can change between Minecraft versions. + // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. + // You can use <@link tag ElementTag.strip_color> to convert the translated output to plain text (pre-translated). + // @example + // # Narrates a translatable of a diamond sword's name. + // - narrate "Reward: <&translate[key=item.minecraft.diamond_sword]>" + // @example + // # Narrates a translatable with some input data. + // - narrate <&translate[key=commands.give.success.single;with=32|<&translate[key=item.minecraft.diamond_sword]>|]> + // @example + // # Narrates a custom translatable (from something like a resource pack), with a fallback in case it can't be translated. + // - narrate <&translate[key=my.custom.translation;fallback=Please use the resource pack!]> + // --> + TagManager.registerTagHandler(ElementTag.class, ObjectTag.class, "&translate", (attribute, param) -> { // Cannot be static due to hacked sub-tag + MapTag translateMap = param.asType(MapTag.class, CoreUtilities.noDebugContext); + if (translateMap == null) { + BukkitImplDeprecations.translateLegacySyntax.warn(attribute.context); + translateMap = new MapTag(); + translateMap.putObject("key", param); + + // <--[tag] + // @attribute <&translate[].with[|...]> + // @returns ElementTag + // @deprecated Use '<&translate[key=;with=|...]>'. + // @description + // Deprecated in favor of <@link tag &translate>. + // --> + if (attribute.startsWith("with", 2)) { + translateMap.putObject("with", new ListTag(attribute.contextAsType(2, ListTag.class), with -> new ElementTag(EscapeTagUtil.unEscape(with), true))); + attribute.fulfill(1); + } + } + return new ElementTag(ChatColor.COLOR_CHAR + "[translate=" + FormattedTextHelper.escape(translateMap.savable()) + ']', true); + }); + + // <--[tag] + // @attribute <&score[|(|)]> + // @returns ElementTag + // @description + // Returns a special chat code that displays a scoreboard entry. Input is an escaped list of: + // Name of the relevant entity, name of the objective, then optionally a value (if unspecified, will use current scoreboard value). + // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. + // + // --> + TagManager.registerStaticTagBaseHandler(ElementTag.class, "&score", (attribute) -> { + if (!attribute.hasParam()) { + return null; + } + ListTag scoreList = attribute.paramAsType(ListTag.class); + if (scoreList.size() < 2) { + return null; + } + String name = FormattedTextHelper.escape(EscapeTagUtil.unEscape(scoreList.get(0))); + String objective = FormattedTextHelper.escape(EscapeTagUtil.unEscape(scoreList.get(1))); + String value = scoreList.size() >= 3 ? FormattedTextHelper.escape(EscapeTagUtil.unEscape(scoreList.get(2))) : ""; + return new ElementTag(ChatColor.COLOR_CHAR + "[score=" + name + ";" + objective + ";" + value + "]"); + }); + + // <--[tag] + // @attribute <&color[]> + // @returns ElementTag + // @description + // Returns a chat code that makes the following text be the specified color. + // Color can be a color name, color code, hex, or ColorTag... that is: "&color[gold]", "&color[6]", and "&color[#AABB00]" are all valid. + // The ColorTag input option can be used for dynamic color effects, such as automatic rainbows. + // --> + TagManager.registerStaticTagBaseHandler(ElementTag.class, "&color", (attribute) -> { + if (!attribute.hasParam()) { + return null; + } + String colorName = attribute.getParam(); + String colorOut = null; + if (colorName.length() == 1) { + ChatColor color = ChatColor.getByChar(colorName.charAt(0)); + if (color != null) { + colorOut = color.toString(); + } + } + else if (colorName.length() == 7 && colorName.startsWith("#")) { + colorOut = FormattedTextHelper.stringifyRGBSpigot(colorName.substring(1)); + } + else if (colorName.startsWith("co@") || colorName.lastIndexOf(',') > colorName.indexOf(',')) { + ColorTag color = ColorTag.valueOf(colorName, attribute.context); + if (color == null && TagManager.isStaticParsing) { + return null; + } + String hex = Integer.toHexString(color.asRGB()); + colorOut = FormattedTextHelper.stringifyRGBSpigot(hex); + } + if (colorOut == null) { + try { + ChatColor color = ChatColor.valueOf(CoreUtilities.toUpperCase(colorName)); + colorOut = color.toString(); + } + catch (IllegalArgumentException ex) { + attribute.echoError("Color '" + colorName + "' doesn't exist (for tag &color[...])."); + return null; + } + } + return new ElementTag(colorOut); + }); + + // <--[tag] + // @attribute <&gradient[from=;to=;(style={RGB}/HSB)]> + // @returns ElementTag + // @description + // Returns a chat code that makes the following text be the specified color. + // Input works equivalently to <@link tag ElementTag.color_gradient>, return to that tag for more documentation detail and input examples. + // The gradient runs from whatever text is after this gradient, until the next color tag (0-9, a-f, 'r' reset, or an RGB code. Does not get stop at formatting codes, they will be included in the gradient). + // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. + // @example + // - narrate "<&gradient[from=black;to=white]>these are the shades of gray that solidifies to pure white" + // --> + TagManager.registerStaticTagBaseHandler(ElementTag.class, MapTag.class, "&gradient", (attribute, inputMap) -> { + ColorTag fromColor = inputMap.getRequiredObjectAs("from", ColorTag.class, attribute); + ColorTag toColor = inputMap.getRequiredObjectAs("to", ColorTag.class, attribute); + ElementTag style = inputMap.getElement("style", "RGB"); + if (fromColor == null || toColor == null) { + return null; + } + if (!style.matchesEnum(BukkitElementExtensions.GradientStyle.class)) { + attribute.echoError("Invalid gradient style '" + style + "'"); + return null; + } + return new ElementTag(ChatColor.COLOR_CHAR + "[gradient=" + fromColor + ";" + toColor + ";" + style + "]"); + }); + + // <--[tag] + // @attribute <&font[]> + // @returns ElementTag + // @description + // Returns a chat code that makes the following text display with the specified font. + // The default font is "minecraft:default". + // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. + // --> + TagManager.registerStaticTagBaseHandler(ElementTag.class, "&font", (attribute) -> { + if (!attribute.hasParam()) { + return null; + } + return new ElementTag(ChatColor.COLOR_CHAR + "[font=" + attribute.getParam() + "]"); + }); + + // <--[tag] + // @attribute <&optimize> + // @returns ElementTag + // @description + // Returns a chat code that tells the formatted text parser to try to produce mininalist JSON text. + // This is useful in particular for very long text or where text is being sent rapidly/repeatedly. + // It is not needed in most normal messages. + // It will produce incompatibility issues if used in items or other locations where raw JSON matching is required. + // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. + // --> + TagManager.registerStaticTagBaseHandler(ElementTag.class, "&optimize", (attribute) -> { + return new ElementTag(ChatColor.COLOR_CHAR + "[optimize=true]", true); + }); + } +} diff --git a/plugin/src/main/java/com/denizenscript/denizen/tags/core/TextTagBase.java b/plugin/src/main/java/com/denizenscript/denizen/tags/core/TextTagBase.java index ac638557c9..5be9330afd 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/tags/core/TextTagBase.java +++ b/plugin/src/main/java/com/denizenscript/denizen/tags/core/TextTagBase.java @@ -1,18 +1,9 @@ package com.denizenscript.denizen.tags.core; -import com.denizenscript.denizen.objects.properties.bukkit.BukkitElementExtensions; import com.denizenscript.denizen.utilities.BukkitImplDeprecations; -import com.denizenscript.denizen.utilities.FormattedTextHelper; -import com.denizenscript.denizen.utilities.HoverFormatHelper; -import com.denizenscript.denizencore.objects.ObjectTag; -import com.denizenscript.denizencore.objects.core.ColorTag; import com.denizenscript.denizencore.objects.core.ElementTag; -import com.denizenscript.denizencore.objects.core.ListTag; -import com.denizenscript.denizencore.objects.core.MapTag; import com.denizenscript.denizencore.tags.TagManager; -import com.denizenscript.denizencore.tags.core.EscapeTagUtil; import com.denizenscript.denizencore.utilities.CoreUtilities; -import net.md_5.bungee.api.chat.HoverEvent; import org.bukkit.ChatColor; public class TextTagBase { @@ -32,324 +23,6 @@ public TextTagBase() { // --> TagManager.registerStaticTagBaseHandler(ElementTag.class, "p", (attribute) -> new ElementTag("\n " + ChatColor.RESET + " \n")); - // <--[tag] - // @attribute <&hover[]> - // @returns ElementTag - // @description - // Returns a special chat code that makes the following text display the input hover text when the mouse is left over it. - // This tag must be followed by an <&end_hover> tag. - // For example: - narrate "There is a <&hover[you found it!]>secret<&end_hover> in this message!" - // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. - // --> - TagManager.registerTagHandler(ElementTag.class, ObjectTag.class, "&hover", (attribute, hover) -> { // Cannot be static due to hacked sub-tag - - // <--[tag] - // @attribute <&hover[].type[]> - // @returns ElementTag - // @description - // Returns a special chat code that makes the following text display the input hover text when the mouse is left over it. - // This tag must be followed by an <&end_hover> tag. - // Available hover types: SHOW_TEXT, SHOW_ITEM, or SHOW_ENTITY. - // For example: - narrate "There is a <&hover[you found it!].type[SHOW_TEXT]>secret<&end_hover> in this message!" - // Note: for "SHOW_ITEM", replace the text with a valid ItemTag. For "SHOW_ENTITY", replace the text with a valid spawned EntityTag (requires F3+H to see entities). - // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. - // --> - HoverEvent.Action type = HoverEvent.Action.SHOW_TEXT; - if (attribute.startsWith("type", 2)) { - attribute.fulfill(1); - type = ElementTag.asEnum(HoverEvent.Action.class, attribute.getParam()); - if (type == null) { - attribute.echoError("Invalid hover type specified."); - return null; - } - } - String hoverData = HoverFormatHelper.parseObjectToHover(hover, type, attribute); - if (hoverData == null) { - return null; - } - return new ElementTag(ChatColor.COLOR_CHAR + "[hover=" + type + ';' + FormattedTextHelper.escape(hoverData) + ']', true); - }); - - // <--[tag] - // @attribute <&click[]> - // @returns ElementTag - // @description - // Returns a special chat code that makes the following text execute the input command line value when clicked. - // To execute a command "/" should be used at the start. Otherwise, it will display as chat. - // This tag must be followed by an <&end_click> tag. - // For example: - narrate "You can <&click[wow]>click here<&end_click> to say wow!" - // For example: - narrate "You can <&click[/help]>click here<&end_click> for help!" - // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. - // --> - TagManager.registerTagHandler(ElementTag.class, "&click", (attribute) -> { // Cannot be static due to hacked sub-tag - if (!attribute.hasParam()) { - return null; - } - String clickText = attribute.getParam(); - - // <--[tag] - // @attribute <&click[].type[]> - // @returns ElementTag - // @description - // Returns a special chat code that makes the following text execute the input command when clicked. - // This tag must be followed by an <&end_click> tag. - // Available command types: OPEN_URL, OPEN_FILE, RUN_COMMAND, SUGGEST_COMMAND, COPY_TO_CLIPBOARD, or CHANGE_PAGE. - // For example: - narrate "You can <&click[https://denizenscript.com].type[OPEN_URL]>click here<&end_click> to learn about Denizen!" - // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. - // --> - String type = "RUN_COMMAND"; - if (attribute.startsWith("type", 2)) { - type = attribute.getContext(2); - attribute.fulfill(1); - } - return new ElementTag(ChatColor.COLOR_CHAR + "[click=" + type + ";" + FormattedTextHelper.escape(clickText) + "]"); - }); - - // <--[tag] - // @attribute <&insertion[]> - // @returns ElementTag - // @description - // Returns a special chat code that makes the following text insert the input message to chat when shift-clicked. - // This tag must be followed by an <&end_insertion> tag. - // For example: - narrate "You can <&insertion[wow]>click here<&end_insertion> to add 'wow' to your chat!" - // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. - // --> - TagManager.registerStaticTagBaseHandler(ElementTag.class, "&insertion", (attribute) -> { - if (!attribute.hasParam()) { - return null; - } - String insertText = attribute.getParam(); - return new ElementTag(ChatColor.COLOR_CHAR + "[insertion=" + FormattedTextHelper.escape(insertText) + "]"); - }); - - // <--[tag] - // @attribute <&end_click> - // @returns ElementTag - // @description - // Returns a special chat code that ends a '&click' tag. - // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. - // --> - TagManager.registerStaticTagBaseHandler(ElementTag.class, "&end_click", (attribute) -> { - return new ElementTag(ChatColor.COLOR_CHAR + "[/click]"); - }); - - // <--[tag] - // @attribute <&end_hover> - // @returns ElementTag - // @description - // Returns a special chat code that ends a '&hover' tag. - // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. - // --> - TagManager.registerStaticTagBaseHandler(ElementTag.class, "&end_hover", (attribute) -> { - return new ElementTag(ChatColor.COLOR_CHAR + "[/hover]"); - }); - - // <--[tag] - // @attribute <&end_insertion> - // @returns ElementTag - // @description - // Returns a special chat code that ends an '&insertion' tag. - // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. - // --> - TagManager.registerStaticTagBaseHandler(ElementTag.class, "&end_insertion", (attribute) -> { - return new ElementTag(ChatColor.COLOR_CHAR + "[/insertion]"); - }); - - // <--[tag] - // @attribute <&keybind[]> - // @returns ElementTag - // @description - // Returns a special chat code that displays a keybind. - // For example: - narrate "Press your <&keybind[key.jump]> key!" - // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. - // --> - TagManager.registerStaticTagBaseHandler(ElementTag.class, "&keybind", (attribute) -> { - if (!attribute.hasParam()) { - return null; - } - String keybindText = attribute.getParam(); - return new ElementTag(ChatColor.COLOR_CHAR + "[keybind=" + FormattedTextHelper.escape(keybindText) + "]"); - }); - - // <--[tag] - // @attribute <&selector[]> - // @returns ElementTag - // @description - // Returns a special chat code that displays a vanilla selector. - // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. - // --> - TagManager.registerStaticTagBaseHandler(ElementTag.class, "&selector", (attribute) -> { - if (!attribute.hasParam()) { - return null; - } - String selectorText = attribute.getParam(); - return new ElementTag(ChatColor.COLOR_CHAR + "[selector=" + FormattedTextHelper.escape(selectorText) + "]"); - }); - - // <--[tag] - // @attribute <&translate[key=;(fallback=);(with=|...)]> - // @returns ElementTag - // @description - // Returns a special chat code that is read by the client to display an auto-translated message. - // "key" is the translation key. - // Optionally specify "fallback" as text to display when the client can't find a translation for the key. - // Optionally specify "with" as a list of input data for the translatable message (parts of the message that are dynamic). - // Be warned that language keys can change between Minecraft versions. - // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. - // You can use <@link tag ElementTag.strip_color> to convert the translated output to plain text (pre-translated). - // @example - // # Narrates a translatable of a diamond sword's name. - // - narrate "Reward: <&translate[key=item.minecraft.diamond_sword]>" - // @example - // # Narrates a translatable with some input data. - // - narrate <&translate[key=commands.give.success.single;with=32|<&translate[key=item.minecraft.diamond_sword]>|]> - // @example - // # Narrates a custom translatable (from something like a resource pack), with a fallback in case it can't be translated. - // - narrate <&translate[key=my.custom.translation;fallback=Please use the resource pack!]> - // --> - TagManager.registerTagHandler(ElementTag.class, ObjectTag.class, "&translate", (attribute, param) -> { // Cannot be static due to hacked sub-tag - MapTag translateMap = param.asType(MapTag.class, CoreUtilities.noDebugContext); - if (translateMap == null) { - BukkitImplDeprecations.translateLegacySyntax.warn(attribute.context); - translateMap = new MapTag(); - translateMap.putObject("key", param); - - // <--[tag] - // @attribute <&translate[].with[|...]> - // @returns ElementTag - // @deprecated Use '<&translate[key=;with=|...]>'. - // @description - // Deprecated in favor of <@link tag &translate>. - // --> - if (attribute.startsWith("with", 2)) { - translateMap.putObject("with", new ListTag(attribute.contextAsType(2, ListTag.class), with -> new ElementTag(EscapeTagUtil.unEscape(with), true))); - attribute.fulfill(1); - } - } - return new ElementTag(ChatColor.COLOR_CHAR + "[translate=" + FormattedTextHelper.escape(translateMap.savable()) + ']', true); - }); - - // <--[tag] - // @attribute <&score[|(|)]> - // @returns ElementTag - // @description - // Returns a special chat code that displays a scoreboard entry. Input is an escaped list of: - // Name of the relevant entity, name of the objective, then optionally a value (if unspecified, will use current scoreboard value). - // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. - // - // --> - TagManager.registerStaticTagBaseHandler(ElementTag.class, "&score", (attribute) -> { - if (!attribute.hasParam()) { - return null; - } - ListTag scoreList = attribute.paramAsType(ListTag.class); - if (scoreList.size() < 2) { - return null; - } - String name = FormattedTextHelper.escape(EscapeTagUtil.unEscape(scoreList.get(0))); - String objective = FormattedTextHelper.escape(EscapeTagUtil.unEscape(scoreList.get(1))); - String value = scoreList.size() >= 3 ? FormattedTextHelper.escape(EscapeTagUtil.unEscape(scoreList.get(2))) : ""; - return new ElementTag(ChatColor.COLOR_CHAR + "[score=" + name + ";" + objective + ";" + value + "]"); - }); - - // <--[tag] - // @attribute <&color[]> - // @returns ElementTag - // @description - // Returns a chat code that makes the following text be the specified color. - // Color can be a color name, color code, hex, or ColorTag... that is: "&color[gold]", "&color[6]", and "&color[#AABB00]" are all valid. - // The ColorTag input option can be used for dynamic color effects, such as automatic rainbows. - // --> - TagManager.registerStaticTagBaseHandler(ElementTag.class, "&color", (attribute) -> { - if (!attribute.hasParam()) { - return null; - } - String colorName = attribute.getParam(); - String colorOut = null; - if (colorName.length() == 1) { - ChatColor color = ChatColor.getByChar(colorName.charAt(0)); - if (color != null) { - colorOut = color.toString(); - } - } - else if (colorName.length() == 7 && colorName.startsWith("#")) { - colorOut = FormattedTextHelper.stringifyRGBSpigot(colorName.substring(1)); - } - else if (colorName.startsWith("co@") || colorName.lastIndexOf(',') > colorName.indexOf(',')) { - ColorTag color = ColorTag.valueOf(colorName, attribute.context); - if (color == null && TagManager.isStaticParsing) { - return null; - } - String hex = Integer.toHexString(color.asRGB()); - colorOut = FormattedTextHelper.stringifyRGBSpigot(hex); - } - if (colorOut == null) { - try { - ChatColor color = ChatColor.valueOf(CoreUtilities.toUpperCase(colorName)); - colorOut = color.toString(); - } - catch (IllegalArgumentException ex) { - attribute.echoError("Color '" + colorName + "' doesn't exist (for tag &color[...])."); - return null; - } - } - return new ElementTag(colorOut); - }); - - // <--[tag] - // @attribute <&gradient[from=;to=;(style={RGB}/HSB)]> - // @returns ElementTag - // @description - // Returns a chat code that makes the following text be the specified color. - // Input works equivalently to <@link tag ElementTag.color_gradient>, return to that tag for more documentation detail and input examples. - // The gradient runs from whatever text is after this gradient, until the next color tag (0-9, a-f, 'r' reset, or an RGB code. Does not get stop at formatting codes, they will be included in the gradient). - // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. - // @example - // - narrate "<&gradient[from=black;to=white]>these are the shades of gray that solidifies to pure white" - // --> - TagManager.registerStaticTagBaseHandler(ElementTag.class, MapTag.class, "&gradient", (attribute, inputMap) -> { - ColorTag fromColor = inputMap.getRequiredObjectAs("from", ColorTag.class, attribute); - ColorTag toColor = inputMap.getRequiredObjectAs("to", ColorTag.class, attribute); - ElementTag style = inputMap.getElement("style", "RGB"); - if (fromColor == null || toColor == null) { - return null; - } - if (!style.matchesEnum(BukkitElementExtensions.GradientStyle.class)) { - attribute.echoError("Invalid gradient style '" + style + "'"); - return null; - } - return new ElementTag(ChatColor.COLOR_CHAR + "[gradient=" + fromColor + ";" + toColor + ";" + style + "]"); - }); - - // <--[tag] - // @attribute <&font[]> - // @returns ElementTag - // @description - // Returns a chat code that makes the following text display with the specified font. - // The default font is "minecraft:default". - // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. - // --> - TagManager.registerStaticTagBaseHandler(ElementTag.class, "&font", (attribute) -> { - if (!attribute.hasParam()) { - return null; - } - return new ElementTag(ChatColor.COLOR_CHAR + "[font=" + attribute.getParam() + "]"); - }); - - // <--[tag] - // @attribute <&optimize> - // @returns ElementTag - // @description - // Returns a chat code that tells the formatted text parser to try to produce mininalist JSON text. - // This is useful in particular for very long text or where text is being sent rapidly/repeatedly. - // It is not needed in most normal messages. - // It will produce incompatibility issues if used in items or other locations where raw JSON matching is required. - // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. - // --> - TagManager.registerStaticTagBaseHandler(ElementTag.class, "&optimize", (attribute) -> { - return new ElementTag(ChatColor.COLOR_CHAR + "[optimize=true]", true); - }); - // <--[tag] // @attribute <&0> // @returns ElementTag From 9a7baf98676e265b43d220ed6368f8d038418dca Mon Sep 17 00:00:00 2001 From: Aya <31237389+tal5@users.noreply.github.com> Date: Sun, 7 Sep 2025 13:45:01 +0100 Subject: [PATCH 08/24] `TextFormattingTags`: initial update --- .../properties/PaperElementExtensions.java | 34 +++++++-- .../paper/tags/TextFormattingTags.java | 76 ++++++++++++------- .../paper/utilities/FormattedTextHelper.java | 9 ++- 3 files changed, 84 insertions(+), 35 deletions(-) diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/properties/PaperElementExtensions.java b/paper/src/main/java/com/denizenscript/denizen/paper/properties/PaperElementExtensions.java index 99ece2aaa2..7ed2426398 100644 --- a/paper/src/main/java/com/denizenscript/denizen/paper/properties/PaperElementExtensions.java +++ b/paper/src/main/java/com/denizenscript/denizen/paper/properties/PaperElementExtensions.java @@ -5,6 +5,8 @@ import com.denizenscript.denizen.objects.ItemTag; import com.denizenscript.denizen.paper.PaperModule; import com.denizenscript.denizen.paper.utilities.FormattedTextHelper; +import com.denizenscript.denizen.paper.utilities.FormattedTextHelper.LegacyColor; +import com.denizenscript.denizen.paper.utilities.FormattedTextHelper.LegacyFormatting; import com.denizenscript.denizen.paper.utilities.HoverFormatHelper; import com.denizenscript.denizen.tags.core.CustomColorTagBase; import com.denizenscript.denizen.utilities.BukkitImplDeprecations; @@ -18,13 +20,9 @@ import com.denizenscript.denizencore.utilities.CoreUtilities; import net.kyori.adventure.text.event.HoverEvent; import net.kyori.adventure.text.format.NamedTextColor; -import net.kyori.adventure.text.format.TextColor; import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; -import static com.denizenscript.denizen.paper.utilities.FormattedTextHelper.LegacyColor; -import static com.denizenscript.denizen.paper.utilities.FormattedTextHelper.LegacyFormatting; - public class PaperElementExtensions { @@ -33,6 +31,7 @@ public static void register() { // <--[tag] // @attribute // @returns ElementTag + // @Plugin Paper // @group text manipulation // @description // Returns the element with all color encoding stripped. @@ -46,6 +45,7 @@ public static void register() { // <--[tag] // @attribute // @returns ElementTag + // @Plugin Paper // @group conversion // @description // Converts normal colored text to Minecraft-style "raw JSON" format. @@ -58,6 +58,7 @@ public static void register() { // <--[tag] // @attribute // @returns ElementTag + // @Plugin Paper // @group conversion // @description // Un-hides the element's text from invisible color codes back to normal text. @@ -70,6 +71,7 @@ public static void register() { // <--[tag] // @attribute // @returns ElementTag + // @Plugin Paper // @group conversion // @description // Tells the formatted text parser to try to produce mininalist JSON text. @@ -89,6 +91,7 @@ public static void register() { // <--[tag] // @attribute ]> // @returns ElementTag + // @Plugin Paper // @group text manipulation // @description // Adds a hover message to the element, which makes the element display the input ItemTag when the mouse is left over it. @@ -103,6 +106,7 @@ public static void register() { // <--[tag] // @attribute ]> // @returns ElementTag + // @Plugin Paper // @group text manipulation // @description // Adds a hover message to the element, which makes the element display the input hover text when the mouse is left over it. @@ -114,6 +118,7 @@ public static void register() { // <--[tag] // @attribute ].type[]> // @returns ElementTag + // @Plugin Paper // @group text manipulation // @description // Adds a hover message to the element, which makes the element display the input hover text when the mouse is left over it. @@ -146,6 +151,7 @@ public static void register() { // <--[tag] // @attribute ]> // @returns ElementTag + // @Plugin Paper // @group text manipulation // @description // Adds a click command to the element, which makes the element open the given URL when clicked. @@ -160,6 +166,7 @@ public static void register() { // <--[tag] // @attribute ]> // @returns ElementTag + // @Plugin Paper // @group text manipulation // @description // Adds a click command to the element, which makes the element pseudo-chat the input message when clicked, for activating interact script chat triggers (<@link language Chat Triggers>). @@ -175,6 +182,7 @@ public static void register() { // <--[tag] // @attribute ]> // @returns ElementTag + // @Plugin Paper // @group text manipulation // @description // Adds a click command to the element, which makes the element execute the input command when clicked. @@ -193,6 +201,7 @@ public static void register() { // <--[tag] // @attribute ].type[]> // @returns ElementTag + // @Plugin Paper // @group text manipulation // @description // Adds a click command to the element, which makes the element execute the input command when clicked. @@ -214,6 +223,7 @@ public static void register() { // <--[tag] // @attribute ]> // @returns ElementTag + // @Plugin Paper // @group text manipulation // @description // Adds an insertion message to the element, which makes the element insert the input message to chat when shift-clicked. @@ -227,6 +237,7 @@ public static void register() { // <--[tag] // @attribute // @returns ElementTag + // @Plugin Paper // @group text manipulation // @description // Makes a color code (&0123456789abcdef) not reset other formatting details. @@ -243,6 +254,7 @@ public static void register() { // <--[tag] // @attribute // @returns ElementTag + // @Plugin Paper // @group text manipulation // @description // Makes a chat format code (&klmno, or &[font=...]) be the end of a format, as opposed to the start. @@ -262,6 +274,7 @@ else if (object.asString().startsWith(FormattedTextHelper.LEGACY_SECTION + "[fon // <--[tag] // @attribute // @returns ElementTag + // @Plugin Paper // @group text manipulation // @description // Makes the input text italic. Equivalent to "<&o><&o.end_format>" @@ -274,6 +287,7 @@ else if (object.asString().startsWith(FormattedTextHelper.LEGACY_SECTION + "[fon // <--[tag] // @attribute // @returns ElementTag + // @Plugin Paper // @group text manipulation // @description // Makes the input text bold. Equivalent to "<&l><&l.end_format>" @@ -286,6 +300,7 @@ else if (object.asString().startsWith(FormattedTextHelper.LEGACY_SECTION + "[fon // <--[tag] // @attribute // @returns ElementTag + // @Plugin Paper // @group text manipulation // @description // Makes the input text underlined. Equivalent to "<&n><&n.end_format>" @@ -298,6 +313,7 @@ else if (object.asString().startsWith(FormattedTextHelper.LEGACY_SECTION + "[fon // <--[tag] // @attribute // @returns ElementTag + // @Plugin Paper // @group text manipulation // @description // Makes the input text struck-through. Equivalent to "<&m><&m.end_format>" @@ -310,6 +326,7 @@ else if (object.asString().startsWith(FormattedTextHelper.LEGACY_SECTION + "[fon // <--[tag] // @attribute // @returns ElementTag + // @Plugin Paper // @group text manipulation // @description // Makes the input text obfuscated. Equivalent to "<&k><&k.end_format>" @@ -322,6 +339,7 @@ else if (object.asString().startsWith(FormattedTextHelper.LEGACY_SECTION + "[fon // <--[tag] // @attribute ]> // @returns ElementTag + // @Plugin Paper // @group text manipulation // @description // Makes the input text colored by the custom color value based on the common base color names defined in the Denizen config file. @@ -340,6 +358,7 @@ else if (object.asString().startsWith(FormattedTextHelper.LEGACY_SECTION + "[fon // <--[tag] // @attribute ]> // @returns ElementTag + // @Plugin Paper // @group text manipulation // @description // Makes the input text colored by the input color. Equivalent to "" @@ -350,7 +369,7 @@ else if (object.asString().startsWith(FormattedTextHelper.LEGACY_SECTION + "[fon String colorName = colorElement.asString(); String colorOut = null; if (colorName.length() == 1) { - TextColor color = LegacyColor.fromChar(colorName.charAt(0)); + LegacyColor color = LegacyColor.legacyFromChar(colorName.charAt(0)); if (color != null) { colorOut = color.toString(); } @@ -397,6 +416,7 @@ else if (colorName.startsWith("co@")) { // <--[tag] // @attribute ]> // @returns ElementTag + // @Plugin Paper // @group text manipulation // @description // Makes the input text display with the input font name. Equivalent to "<&font[new-font]><&font[new-font].end_format>" @@ -410,6 +430,7 @@ else if (colorName.startsWith("co@")) { // <--[tag] // @attribute )]> // @returns ElementTag + // @Plugin Paper // @group text manipulation // @description // Returns the element with rainbow colors applied. @@ -432,6 +453,7 @@ else if (colorName.startsWith("co@")) { // <--[tag] // @attribute )]> // @returns ElementTag + // @Plugin Paper // @group text manipulation // @description // Returns the element with RGB rainbow colors applied. @@ -485,6 +507,7 @@ else if (colorName.startsWith("co@")) { // <--[tag] // @attribute ;to=;(style={RGB}/HSB)]> // @returns ElementTag + // @Plugin Paper // @group text manipulation // @description // Returns the element with an RGB color gradient applied, with a unique color per character. @@ -522,6 +545,7 @@ else if (colorName.startsWith("co@")) { // <--[tag] // @attribute ;to=]> // @returns ElementTag + // @Plugin Paper // @group text manipulation // @deprecated use color_gradient[from=color;to=color;style=HSB] // @description diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/tags/TextFormattingTags.java b/paper/src/main/java/com/denizenscript/denizen/paper/tags/TextFormattingTags.java index a8ceb5a45f..0a2a1e6df4 100644 --- a/paper/src/main/java/com/denizenscript/denizen/paper/tags/TextFormattingTags.java +++ b/paper/src/main/java/com/denizenscript/denizen/paper/tags/TextFormattingTags.java @@ -1,9 +1,10 @@ package com.denizenscript.denizen.paper.tags; -import com.denizenscript.denizen.objects.properties.bukkit.BukkitElementExtensions; +import com.denizenscript.denizen.paper.properties.PaperElementExtensions; +import com.denizenscript.denizen.paper.utilities.FormattedTextHelper; +import com.denizenscript.denizen.paper.utilities.FormattedTextHelper.LegacyColor; +import com.denizenscript.denizen.paper.utilities.HoverFormatHelper; import com.denizenscript.denizen.utilities.BukkitImplDeprecations; -import com.denizenscript.denizen.utilities.FormattedTextHelper; -import com.denizenscript.denizen.utilities.HoverFormatHelper; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ColorTag; import com.denizenscript.denizencore.objects.core.ElementTag; @@ -12,8 +13,8 @@ import com.denizenscript.denizencore.tags.TagManager; import com.denizenscript.denizencore.tags.core.EscapeTagUtil; import com.denizenscript.denizencore.utilities.CoreUtilities; -import net.md_5.bungee.api.chat.HoverEvent; -import org.bukkit.ChatColor; +import net.kyori.adventure.text.event.HoverEvent; +import net.kyori.adventure.text.format.NamedTextColor; public class TextFormattingTags { @@ -22,6 +23,7 @@ public TextFormattingTags() { // <--[tag] // @attribute <&hover[]> // @returns ElementTag + // @Plugin Paper // @description // Returns a special chat code that makes the following text display the input hover text when the mouse is left over it. // This tag must be followed by an <&end_hover> tag. @@ -33,6 +35,7 @@ public TextFormattingTags() { // <--[tag] // @attribute <&hover[].type[]> // @returns ElementTag + // @Plugin Paper // @description // Returns a special chat code that makes the following text display the input hover text when the mouse is left over it. // This tag must be followed by an <&end_hover> tag. @@ -41,10 +44,14 @@ public TextFormattingTags() { // Note: for "SHOW_ITEM", replace the text with a valid ItemTag. For "SHOW_ENTITY", replace the text with a valid spawned EntityTag (requires F3+H to see entities). // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. // --> - HoverEvent.Action type = HoverEvent.Action.SHOW_TEXT; + HoverEvent.Action type = HoverEvent.Action.SHOW_TEXT; if (attribute.startsWith("type", 2)) { attribute.fulfill(1); - type = ElementTag.asEnum(HoverEvent.Action.class, attribute.getParam()); + if (!attribute.hasParam()) { + attribute.echoError("Must specify an hover type."); + return null; + } + type = HoverEvent.Action.NAMES.value(CoreUtilities.toLowerCase(attribute.getParam())); if (type == null) { attribute.echoError("Invalid hover type specified."); return null; @@ -54,12 +61,13 @@ public TextFormattingTags() { if (hoverData == null) { return null; } - return new ElementTag(ChatColor.COLOR_CHAR + "[hover=" + type + ';' + FormattedTextHelper.escape(hoverData) + ']', true); + return new ElementTag(FormattedTextHelper.LEGACY_SECTION + "[hover=" + type + ';' + FormattedTextHelper.escape(hoverData) + ']', true); }); // <--[tag] // @attribute <&click[]> // @returns ElementTag + // @Plugin Paper // @description // Returns a special chat code that makes the following text execute the input command line value when clicked. // To execute a command "/" should be used at the start. Otherwise, it will display as chat. @@ -77,6 +85,7 @@ public TextFormattingTags() { // <--[tag] // @attribute <&click[].type[]> // @returns ElementTag + // @Plugin Paper // @description // Returns a special chat code that makes the following text execute the input command when clicked. // This tag must be followed by an <&end_click> tag. @@ -89,12 +98,13 @@ public TextFormattingTags() { type = attribute.getContext(2); attribute.fulfill(1); } - return new ElementTag(ChatColor.COLOR_CHAR + "[click=" + type + ";" + FormattedTextHelper.escape(clickText) + "]"); + return new ElementTag(FormattedTextHelper.LEGACY_SECTION + "[click=" + type + ";" + FormattedTextHelper.escape(clickText) + "]", true); }); // <--[tag] // @attribute <&insertion[]> // @returns ElementTag + // @Plugin Paper // @description // Returns a special chat code that makes the following text insert the input message to chat when shift-clicked. // This tag must be followed by an <&end_insertion> tag. @@ -106,45 +116,49 @@ public TextFormattingTags() { return null; } String insertText = attribute.getParam(); - return new ElementTag(ChatColor.COLOR_CHAR + "[insertion=" + FormattedTextHelper.escape(insertText) + "]"); + return new ElementTag(FormattedTextHelper.LEGACY_SECTION + "[insertion=" + FormattedTextHelper.escape(insertText) + "]", true); }); // <--[tag] // @attribute <&end_click> // @returns ElementTag + // @Plugin Paper // @description // Returns a special chat code that ends a '&click' tag. // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. // --> TagManager.registerStaticTagBaseHandler(ElementTag.class, "&end_click", (attribute) -> { - return new ElementTag(ChatColor.COLOR_CHAR + "[/click]"); + return new ElementTag(FormattedTextHelper.LEGACY_SECTION + "[/click]", true); }); // <--[tag] // @attribute <&end_hover> // @returns ElementTag + // @Plugin Paper // @description // Returns a special chat code that ends a '&hover' tag. // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. // --> TagManager.registerStaticTagBaseHandler(ElementTag.class, "&end_hover", (attribute) -> { - return new ElementTag(ChatColor.COLOR_CHAR + "[/hover]"); + return new ElementTag(FormattedTextHelper.LEGACY_SECTION + "[/hover]", true); }); // <--[tag] // @attribute <&end_insertion> // @returns ElementTag + // @Plugin Paper // @description // Returns a special chat code that ends an '&insertion' tag. // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. // --> TagManager.registerStaticTagBaseHandler(ElementTag.class, "&end_insertion", (attribute) -> { - return new ElementTag(ChatColor.COLOR_CHAR + "[/insertion]"); + return new ElementTag(FormattedTextHelper.LEGACY_SECTION + "[/insertion]", true); }); // <--[tag] // @attribute <&keybind[]> // @returns ElementTag + // @Plugin Paper // @description // Returns a special chat code that displays a keybind. // For example: - narrate "Press your <&keybind[key.jump]> key!" @@ -155,12 +169,13 @@ public TextFormattingTags() { return null; } String keybindText = attribute.getParam(); - return new ElementTag(ChatColor.COLOR_CHAR + "[keybind=" + FormattedTextHelper.escape(keybindText) + "]"); + return new ElementTag(FormattedTextHelper.LEGACY_SECTION + "[keybind=" + FormattedTextHelper.escape(keybindText) + "]", true); }); // <--[tag] // @attribute <&selector[]> // @returns ElementTag + // @Plugin Paper // @description // Returns a special chat code that displays a vanilla selector. // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. @@ -170,12 +185,13 @@ public TextFormattingTags() { return null; } String selectorText = attribute.getParam(); - return new ElementTag(ChatColor.COLOR_CHAR + "[selector=" + FormattedTextHelper.escape(selectorText) + "]"); + return new ElementTag(FormattedTextHelper.LEGACY_SECTION + "[selector=" + FormattedTextHelper.escape(selectorText) + "]", true); }); // <--[tag] // @attribute <&translate[key=;(fallback=);(with=|...)]> // @returns ElementTag + // @Plugin Paper // @description // Returns a special chat code that is read by the client to display an auto-translated message. // "key" is the translation key. @@ -204,6 +220,7 @@ public TextFormattingTags() { // <--[tag] // @attribute <&translate[].with[|...]> // @returns ElementTag + // @Plugin Paper // @deprecated Use '<&translate[key=;with=|...]>'. // @description // Deprecated in favor of <@link tag &translate>. @@ -213,12 +230,13 @@ public TextFormattingTags() { attribute.fulfill(1); } } - return new ElementTag(ChatColor.COLOR_CHAR + "[translate=" + FormattedTextHelper.escape(translateMap.savable()) + ']', true); + return new ElementTag(FormattedTextHelper.LEGACY_SECTION + "[translate=" + FormattedTextHelper.escape(translateMap.savable()) + ']', true); }); // <--[tag] // @attribute <&score[|(|)]> // @returns ElementTag + // @Plugin Paper // @description // Returns a special chat code that displays a scoreboard entry. Input is an escaped list of: // Name of the relevant entity, name of the objective, then optionally a value (if unspecified, will use current scoreboard value). @@ -236,12 +254,13 @@ public TextFormattingTags() { String name = FormattedTextHelper.escape(EscapeTagUtil.unEscape(scoreList.get(0))); String objective = FormattedTextHelper.escape(EscapeTagUtil.unEscape(scoreList.get(1))); String value = scoreList.size() >= 3 ? FormattedTextHelper.escape(EscapeTagUtil.unEscape(scoreList.get(2))) : ""; - return new ElementTag(ChatColor.COLOR_CHAR + "[score=" + name + ";" + objective + ";" + value + "]"); + return new ElementTag(FormattedTextHelper.LEGACY_SECTION + "[score=" + name + ";" + objective + ";" + value + "]", true); }); // <--[tag] // @attribute <&color[]> // @returns ElementTag + // @Plugin Paper // @description // Returns a chat code that makes the following text be the specified color. // Color can be a color name, color code, hex, or ColorTag... that is: "&color[gold]", "&color[6]", and "&color[#AABB00]" are all valid. @@ -254,7 +273,7 @@ public TextFormattingTags() { String colorName = attribute.getParam(); String colorOut = null; if (colorName.length() == 1) { - ChatColor color = ChatColor.getByChar(colorName.charAt(0)); + LegacyColor color = LegacyColor.legacyFromChar(colorName.charAt(0)); if (color != null) { colorOut = color.toString(); } @@ -271,21 +290,20 @@ else if (colorName.startsWith("co@") || colorName.lastIndexOf(',') > colorName.i colorOut = FormattedTextHelper.stringifyRGBSpigot(hex); } if (colorOut == null) { - try { - ChatColor color = ChatColor.valueOf(CoreUtilities.toUpperCase(colorName)); - colorOut = color.toString(); - } - catch (IllegalArgumentException ex) { + NamedTextColor color = NamedTextColor.NAMES.value(CoreUtilities.toLowerCase(colorName)); + if (color == null) { attribute.echoError("Color '" + colorName + "' doesn't exist (for tag &color[...])."); return null; } + colorOut = LegacyColor.fromModern(color).toString(); } - return new ElementTag(colorOut); + return new ElementTag(colorOut, true); }); // <--[tag] // @attribute <&gradient[from=;to=;(style={RGB}/HSB)]> // @returns ElementTag + // @Plugin Paper // @description // Returns a chat code that makes the following text be the specified color. // Input works equivalently to <@link tag ElementTag.color_gradient>, return to that tag for more documentation detail and input examples. @@ -301,16 +319,17 @@ else if (colorName.startsWith("co@") || colorName.lastIndexOf(',') > colorName.i if (fromColor == null || toColor == null) { return null; } - if (!style.matchesEnum(BukkitElementExtensions.GradientStyle.class)) { + if (!style.matchesEnum(PaperElementExtensions.GradientStyle.class)) { attribute.echoError("Invalid gradient style '" + style + "'"); return null; } - return new ElementTag(ChatColor.COLOR_CHAR + "[gradient=" + fromColor + ";" + toColor + ";" + style + "]"); + return new ElementTag(FormattedTextHelper.LEGACY_SECTION + "[gradient=" + fromColor + ";" + toColor + ";" + style + "]", true); }); // <--[tag] // @attribute <&font[]> // @returns ElementTag + // @Plugin Paper // @description // Returns a chat code that makes the following text display with the specified font. // The default font is "minecraft:default". @@ -320,12 +339,13 @@ else if (colorName.startsWith("co@") || colorName.lastIndexOf(',') > colorName.i if (!attribute.hasParam()) { return null; } - return new ElementTag(ChatColor.COLOR_CHAR + "[font=" + attribute.getParam() + "]"); + return new ElementTag(FormattedTextHelper.LEGACY_SECTION + "[font=" + attribute.getParam() + "]", true); }); // <--[tag] // @attribute <&optimize> // @returns ElementTag + // @Plugin Paper // @description // Returns a chat code that tells the formatted text parser to try to produce mininalist JSON text. // This is useful in particular for very long text or where text is being sent rapidly/repeatedly. @@ -334,7 +354,7 @@ else if (colorName.startsWith("co@") || colorName.lastIndexOf(',') > colorName.i // Note that this is a magic Denizen tool - refer to <@link language Denizen Text Formatting>. // --> TagManager.registerStaticTagBaseHandler(ElementTag.class, "&optimize", (attribute) -> { - return new ElementTag(ChatColor.COLOR_CHAR + "[optimize=true]", true); + return new ElementTag(FormattedTextHelper.LEGACY_SECTION + "[optimize=true]", true); }); } } diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/FormattedTextHelper.java b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/FormattedTextHelper.java index 7058be4b36..28277fce16 100644 --- a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/FormattedTextHelper.java +++ b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/FormattedTextHelper.java @@ -98,6 +98,11 @@ else if (colorChar >= 'a' && colorChar <= 'f') { } public static NamedTextColor fromChar(char colorChar) { + int index = calculateIndex(colorChar); + return index != -1 ? FROM_LEGACY[index].color : null; + } + + public static LegacyColor legacyFromChar(char colorChar) { int index = calculateIndex(colorChar); return index != -1 ? FROM_LEGACY[index] : null; } @@ -107,12 +112,12 @@ public static LegacyColor fromModern(NamedTextColor textColor) { } private static final Map TO_LEGACY = new IdentityHashMap<>(16); - private static final NamedTextColor[] FROM_LEGACY = new NamedTextColor[16]; + private static final LegacyColor[] FROM_LEGACY = new LegacyColor[16]; static { for (LegacyColor legacyColor : values()) { TO_LEGACY.put(legacyColor.color, legacyColor); - FROM_LEGACY[calculateIndex(legacyColor.colorChar)] = legacyColor.color; + FROM_LEGACY[calculateIndex(legacyColor.colorChar)] = legacyColor; } } } From 843f083773d460295b64871a2b17bd7b51e2c463 Mon Sep 17 00:00:00 2001 From: Aya <31237389+tal5@users.noreply.github.com> Date: Mon, 8 Sep 2025 21:22:47 +0100 Subject: [PATCH 09/24] `FormattedTextHelper`: more immutability fixes --- .../denizen/paper/utilities/FormattedTextHelper.java | 6 +++--- .../denizenscript/denizen/utilities/HoverFormatHelper.java | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/FormattedTextHelper.java b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/FormattedTextHelper.java index 28277fce16..ea85328cfa 100644 --- a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/FormattedTextHelper.java +++ b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/FormattedTextHelper.java @@ -591,7 +591,7 @@ public static Component parseInternal(String str, TextColor baseColor, boolean c firstChar = 0; } else { - // This is for compat with how Spigot does parsing of plaintext. + // This is for compact with how Spigot does parsing of plaintext. return Component.textOfChildren(Component.text(str)); } } @@ -650,7 +650,6 @@ public static Component parseInternal(String str, TextColor baseColor, boolean c String innardType = CoreUtilities.toLowerCase(innardBase.get(0)); if (innardBase.size() == 2) { nextText.content(nextText.content() + str.substring(started, i)); - base.append(nextText); lastText = nextText; nextText = copyFormatToNewText(lastText, optimize); nextText.content(""); @@ -807,6 +806,7 @@ else if (innardType.equals("optimize")) { Debug.echoError("Text parse issue: cannot interpret type '" + innardType + "' with " + innardParts.size() + " parts."); } } + base.append(lastText); } i = endBracket; started = endBracket + 1; @@ -893,7 +893,6 @@ else if (i + "https://a.".length() < chars.length && chars[i] == 'h' && chars[i } String url = str.substring(i, nextSpace); nextText.content(nextText.content() + str.substring(started, i)); - base.append(nextText); lastText = nextText; // TODO builder copying nextText = lastText.build().toBuilder(); @@ -901,6 +900,7 @@ else if (i + "https://a.".length() < chars.length && chars[i] == 'h' && chars[i TextComponent.Builder clickableText = Component.text().content(url); clickableText.clickEvent(ClickEvent.openUrl(url)); lastText.append(clickableText); + base.append(lastText); i = nextSpace - 1; started = nextSpace; continue; diff --git a/plugin/src/main/java/com/denizenscript/denizen/utilities/HoverFormatHelper.java b/plugin/src/main/java/com/denizenscript/denizen/utilities/HoverFormatHelper.java index 3f71572930..3e29a12ae7 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/utilities/HoverFormatHelper.java +++ b/plugin/src/main/java/com/denizenscript/denizen/utilities/HoverFormatHelper.java @@ -62,7 +62,7 @@ else if (action == HoverEvent.Action.SHOW_ENTITY) { } ElementTag type = entityHoverData.getElement("type"); ElementTag rawName = entityHoverData.getElement("name"); - BaseComponent name = rawName != null ? new TextComponent(FormattedTextHelper.parse(rawName.asString(), ChatColor.WHITE)) : null; + BaseComponent name = rawName != null ? TextComponent.fromArray(FormattedTextHelper.parse(rawName.asString(), ChatColor.WHITE)) : null; content = new Entity(type != null ? type.asString() : null, uuid.asString(), name); } } From e229dd50e3913fd3236ce91e17dacac7bf63281b Mon Sep 17 00:00:00 2001 From: Aya <31237389+tal5@users.noreply.github.com> Date: Mon, 8 Sep 2025 23:48:52 +0100 Subject: [PATCH 10/24] `player receives message` event & related: update --- .../paper/utilities/PaperAPIToolsImpl.java | 22 ++++++++-------- .../PlayerReceivesMessageScriptEvent.java | 25 +++++-------------- .../denizen/utilities/PaperAPITools.java | 23 +++++++++++++++++ .../packets/DenizenPacketHandler.java | 4 +-- .../handlers/DenizenNetworkManagerImpl.java | 21 ++++++++-------- .../network/packets/PacketOutChatImpl.java | 7 +++--- .../handlers/DenizenNetworkManagerImpl.java | 13 +++++----- .../network/packets/PacketOutChatImpl.java | 7 +++--- .../handlers/DenizenNetworkManagerImpl.java | 12 ++++----- .../network/packets/PacketOutChatImpl.java | 6 ++--- .../packet/ActionBarEventPacketHandlers.java | 11 ++++---- .../DenizenPacketHandlerPacketHandlers.java | 3 ++- .../network/packets/PacketOutChatImpl.java | 6 ++--- .../packet/ActionBarEventPacketHandlers.java | 11 ++++---- .../DenizenPacketHandlerPacketHandlers.java | 3 ++- .../network/packets/PacketOutChatImpl.java | 6 ++--- 16 files changed, 94 insertions(+), 86 deletions(-) diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java index c468235626..8c1ab32fec 100644 --- a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java +++ b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java @@ -8,7 +8,6 @@ import com.denizenscript.denizen.scripts.commands.entity.TeleportCommand; import com.denizenscript.denizen.scripts.containers.core.ItemScriptContainer; import com.denizenscript.denizen.scripts.containers.core.ItemScriptHelper; -import com.denizenscript.denizen.utilities.FormattedTextHelper; import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizencore.DenizenCore; import com.denizenscript.denizencore.objects.core.ElementTag; @@ -21,9 +20,9 @@ import io.papermc.paper.entity.TeleportFlag; import io.papermc.paper.potion.PotionMix; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.minimessage.MiniMessage; import net.md_5.bungee.api.ChatColor; -import net.md_5.bungee.api.chat.BaseComponent; import org.bukkit.*; import org.bukkit.block.Sign; import org.bukkit.command.CommandSender; @@ -84,12 +83,6 @@ public String getCustomName(Entity entity) { return PaperModule.stringifyComponent(entity.customName()); } - @Override - public BaseComponent[] getCustomNameComponent(Entity entity) { - Component customName = entity.customName(); - return customName != null ? FormattedTextHelper.parseJson(PaperModule.componentToJson(customName)) : null; - } - @Override public void setPlayerListName(Player player, String name) { player.playerListName(PaperModule.parseFormattedText(name, ChatColor.WHITE)); @@ -361,8 +354,7 @@ public String convertTextToMiniMessage(String text, boolean splitNewlines) { List lines = CoreUtilities.split(text, '\n'); return lines.stream().map(l -> convertTextToMiniMessage(l, false)).collect(Collectors.joining("\n")); } - Component parsed = PaperModule.jsonToComponent(FormattedTextHelper.componentToJson(FormattedTextHelper.parse(text, ChatColor.WHITE, false))); - return MiniMessage.miniMessage().serialize(parsed); + return MiniMessage.miniMessage().serialize(FormattedTextHelper.parse(text, NamedTextColor.WHITE, false)); } @Override @@ -409,4 +401,14 @@ public void setMaterialTags(Material type, Set tags) { } BlockTagsSetter.INSTANCE.setTags(type, tags); } + + @Override + public String parseTextToJson(String formattedText, BaseColor baseColor) { + return PaperModule.componentToJson(FormattedTextHelper.parse(formattedText, baseColor == BaseColor.WHITE ? NamedTextColor.WHITE : NamedTextColor.BLACK)); + } + + @Override + public String parseJsonToText(String json) { + return FormattedTextHelper.stringify(PaperModule.jsonToComponent(json)); + } } diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/player/PlayerReceivesMessageScriptEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/player/PlayerReceivesMessageScriptEvent.java index 46efe9d46f..0779818494 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/events/player/PlayerReceivesMessageScriptEvent.java +++ b/plugin/src/main/java/com/denizenscript/denizen/events/player/PlayerReceivesMessageScriptEvent.java @@ -2,15 +2,13 @@ import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.PlayerTag; -import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizen.utilities.packets.NetworkInterceptHelper; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import com.denizenscript.denizencore.utilities.CoreUtilities; -import net.md_5.bungee.api.ChatColor; -import net.md_5.bungee.api.chat.BaseComponent; public class PlayerReceivesMessageScriptEvent extends BukkitScriptEvent { @@ -49,7 +47,6 @@ public PlayerReceivesMessageScriptEvent() { public ElementTag message; public ElementTag rawJson; public boolean didModify; - public BaseComponent[] altMessageDetermination; public ElementTag system; public boolean modified; public PlayerTag player; @@ -62,7 +59,6 @@ public void reset() { system = null; cancelled = false; modified = false; - altMessageDetermination = null; didModify = false; } @@ -89,14 +85,13 @@ public boolean applyDetermination(ScriptPath path, ObjectTag determinationObj) { String lower = CoreUtilities.toLowerCase(determination); if (lower.startsWith("message:")) { message = new ElementTag(determination.substring("message:".length()), true); - altMessageDetermination = FormattedTextHelper.parse(message.asString(), ChatColor.WHITE); + rawJson = new ElementTag(PaperAPITools.instance.parseTextToJson(message.asString(), PaperAPITools.BaseColor.WHITE), true); modified = true; return true; } if (lower.startsWith("raw_json:")) { - rawJson = new ElementTag(determination.substring("raw_json:".length())); - altMessageDetermination = null; - message = new ElementTag(FormattedTextHelper.stringify(FormattedTextHelper.parseJson(rawJson.asString())), true); + rawJson = new ElementTag(determination.substring("raw_json:".length()), true); + message = new ElementTag(PaperAPITools.instance.parseJsonToText(rawJson.asString()), true); modified = true; return true; } @@ -114,20 +109,12 @@ public ObjectTag getContext(String name) { switch (name) { case "message": return message; case "system_message": return system; - case "raw_json": - if (altMessageDetermination != null) { - return new ElementTag(FormattedTextHelper.componentToJson(altMessageDetermination), true); - } - return rawJson; + case "raw_json": return rawJson; } return super.getContext(name); } public PlayerReceivesMessageScriptEvent triggerNow() { - PlayerReceivesMessageScriptEvent event = (PlayerReceivesMessageScriptEvent) fire(); - if (event.modified && event.altMessageDetermination == null) { - event.altMessageDetermination = FormattedTextHelper.parseJson(event.rawJson.asString()); - } - return event; + return (PlayerReceivesMessageScriptEvent) fire(); } } diff --git a/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java b/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java index 2625cc5ced..7f18aca504 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java +++ b/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java @@ -7,7 +7,10 @@ import com.denizenscript.denizen.utilities.packets.NetworkInterceptHelper; import com.denizenscript.denizencore.utilities.ReflectionHelper; import com.denizenscript.denizencore.utilities.debugging.Debug; +import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.api.chat.TextComponent; +import net.md_5.bungee.chat.ComponentSerializer; import org.bukkit.*; import org.bukkit.block.Sign; import org.bukkit.command.CommandSender; @@ -233,4 +236,24 @@ public boolean hasCustomName(PotionMeta meta) { public void setMaterialTags(Material type, Set tags) { NMSHandler.blockHelper.setVanillaTags(type, tags); } + + public enum BaseColor { WHITE, BLACK } + + public String parseTextToJson(String formattedText, BaseColor baseColor) { + TextComponent textComponent = new TextComponent(formattedText); + textComponent.setBold(false); + textComponent.setItalic(false); + textComponent.setStrikethrough(false); + textComponent.setUnderlined(false); + textComponent.setObfuscated(false); + textComponent.setColor(baseColor == BaseColor.WHITE ? ChatColor.WHITE : ChatColor.BLACK); + TextComponent base = new TextComponent(); + base.addExtra(textComponent); + return ComponentSerializer.toString(base); + } + + public String parseJsonToText(String json) { + BaseComponent[] components = ComponentSerializer.parse(json); + return components.length == 1 ? components[0].toLegacyText() : new TextComponent(components).toLegacyText(); + } } diff --git a/plugin/src/main/java/com/denizenscript/denizen/utilities/packets/DenizenPacketHandler.java b/plugin/src/main/java/com/denizenscript/denizen/utilities/packets/DenizenPacketHandler.java index 04493160b0..dcf796c677 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/utilities/packets/DenizenPacketHandler.java +++ b/plugin/src/main/java/com/denizenscript/denizen/utilities/packets/DenizenPacketHandler.java @@ -113,8 +113,8 @@ public PlayerReceivesMessageScriptEvent sendPacket(final Player player, final Pa if (event.loaded) { Callable eventCall = () -> { event.reset(); - event.message = new ElementTag(chat.getMessage()); - event.rawJson = new ElementTag(chat.getRawJson()); + event.message = new ElementTag(chat.getMessage(), true); + event.rawJson = new ElementTag(chat.getRawJson(), true); event.system = new ElementTag(chat.isSystem()); event.player = PlayerTag.mirrorBukkitPlayer(player); return event.triggerNow(); diff --git a/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/impl/network/handlers/DenizenNetworkManagerImpl.java b/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/impl/network/handlers/DenizenNetworkManagerImpl.java index 4f948d0b87..04005b13f5 100644 --- a/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/impl/network/handlers/DenizenNetworkManagerImpl.java +++ b/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/impl/network/handlers/DenizenNetworkManagerImpl.java @@ -3,13 +3,14 @@ import com.denizenscript.denizen.events.player.PlayerHearsSoundScriptEvent; import com.denizenscript.denizen.events.player.PlayerReceivesActionbarScriptEvent; import com.denizenscript.denizen.events.player.PlayerReceivesMessageScriptEvent; +import com.denizenscript.denizen.nms.NMSHandler; import com.denizenscript.denizen.nms.abstracts.BlockLight; import com.denizenscript.denizen.nms.v1_17.Handler; import com.denizenscript.denizen.nms.v1_17.ReflectionMappingsInfo; import com.denizenscript.denizen.nms.v1_17.impl.ProfileEditorImpl; -import com.denizenscript.denizen.nms.v1_17.impl.network.packets.*; import com.denizenscript.denizen.nms.v1_17.impl.blocks.BlockLightImpl; import com.denizenscript.denizen.nms.v1_17.impl.entities.EntityFakePlayerImpl; +import com.denizenscript.denizen.nms.v1_17.impl.network.packets.PacketOutChatImpl; import com.denizenscript.denizen.objects.LocationTag; import com.denizenscript.denizen.objects.PlayerTag; import com.denizenscript.denizen.scripts.commands.entity.FakeEquipCommand; @@ -17,6 +18,7 @@ import com.denizenscript.denizen.scripts.commands.entity.SneakCommand; import com.denizenscript.denizen.scripts.commands.player.DisguiseCommand; import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizen.utilities.Settings; import com.denizenscript.denizen.utilities.blocks.ChunkCoordinate; import com.denizenscript.denizen.utilities.blocks.FakeBlock; @@ -26,16 +28,14 @@ import com.denizenscript.denizen.utilities.packets.HideParticles; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.utilities.CoreConfiguration; +import com.denizenscript.denizencore.utilities.ReflectionHelper; +import com.denizenscript.denizencore.utilities.debugging.Debug; import com.mojang.datafixers.util.Pair; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.util.concurrent.Future; import io.netty.util.concurrent.GenericFutureListener; -import com.denizenscript.denizen.nms.NMSHandler; -import com.denizenscript.denizencore.utilities.ReflectionHelper; -import com.denizenscript.denizencore.utilities.debugging.Debug; import net.md_5.bungee.api.ChatColor; -import net.md_5.bungee.chat.ComponentSerializer; import net.minecraft.core.BlockPos; import net.minecraft.core.NonNullList; import net.minecraft.core.SectionPos; @@ -271,10 +271,10 @@ public boolean processActionbarPacket(Packet packet, GenericFutureListener packet, GenericFutureListener packet) { return true; } if (result.modified) { - packetHelper.setRawJson(ComponentSerializer.toString(result.altMessageDetermination)); + packetHelper.setRawJson(result.rawJson.asString()); } } } diff --git a/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/impl/network/packets/PacketOutChatImpl.java b/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/impl/network/packets/PacketOutChatImpl.java index e4ff599738..3a0407168c 100644 --- a/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/impl/network/packets/PacketOutChatImpl.java +++ b/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/impl/network/packets/PacketOutChatImpl.java @@ -1,9 +1,8 @@ package com.denizenscript.denizen.nms.v1_17.impl.network.packets; import com.denizenscript.denizen.nms.interfaces.packets.PacketOutChat; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizencore.utilities.ReflectionHelper; -import com.denizenscript.denizen.nms.v1_17.Handler; -import com.denizenscript.denizen.utilities.FormattedTextHelper; import com.denizenscript.denizencore.utilities.debugging.Debug; import net.md_5.bungee.chat.ComponentSerializer; import net.minecraft.network.chat.ChatType; @@ -25,13 +24,13 @@ public PacketOutChatImpl(ClientboundChatPacket internal) { try { Component baseComponent = (Component) MESSAGE.get(internal); if (baseComponent != null) { - message = FormattedTextHelper.stringify(Handler.componentToSpigot(baseComponent)); rawJson = Component.Serializer.toJson(baseComponent); + message = PaperAPITools.instance.parseJsonToText(rawJson); } else { if (internal.components != null) { - message = FormattedTextHelper.stringify(internal.components); rawJson = ComponentSerializer.toString(internal.components); + message = PaperAPITools.instance.parseJsonToText(rawJson); } bungee = true; } diff --git a/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/impl/network/handlers/DenizenNetworkManagerImpl.java b/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/impl/network/handlers/DenizenNetworkManagerImpl.java index 4d830865e1..70b1f38e33 100644 --- a/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/impl/network/handlers/DenizenNetworkManagerImpl.java +++ b/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/impl/network/handlers/DenizenNetworkManagerImpl.java @@ -17,6 +17,7 @@ import com.denizenscript.denizen.scripts.commands.entity.*; import com.denizenscript.denizen.scripts.commands.player.DisguiseCommand; import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizen.utilities.Settings; import com.denizenscript.denizen.utilities.blocks.ChunkCoordinate; import com.denizenscript.denizen.utilities.blocks.FakeBlock; @@ -38,7 +39,6 @@ import io.netty.util.concurrent.Future; import io.netty.util.concurrent.GenericFutureListener; import net.md_5.bungee.api.ChatColor; -import net.md_5.bungee.chat.ComponentSerializer; import net.minecraft.core.BlockPos; import net.minecraft.core.NonNullList; import net.minecraft.core.SectionPos; @@ -395,10 +395,10 @@ public boolean processActionbarPacket(Packet packet, GenericFutureListener packet, GenericFutureListener packet) { return true; } if (result.modified) { - packetHelper.setRawJson(ComponentSerializer.toString(result.altMessageDetermination)); + packetHelper.setRawJson(result.rawJson.asString()); } } } diff --git a/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/impl/network/packets/PacketOutChatImpl.java b/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/impl/network/packets/PacketOutChatImpl.java index 2166ed8dac..e6076991a2 100644 --- a/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/impl/network/packets/PacketOutChatImpl.java +++ b/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/impl/network/packets/PacketOutChatImpl.java @@ -1,9 +1,8 @@ package com.denizenscript.denizen.nms.v1_18.impl.network.packets; import com.denizenscript.denizen.nms.interfaces.packets.PacketOutChat; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizencore.utilities.ReflectionHelper; -import com.denizenscript.denizen.nms.v1_18.Handler; -import com.denizenscript.denizen.utilities.FormattedTextHelper; import com.denizenscript.denizencore.utilities.debugging.Debug; import net.md_5.bungee.chat.ComponentSerializer; import net.minecraft.network.chat.ChatType; @@ -25,13 +24,13 @@ public PacketOutChatImpl(ClientboundChatPacket internal) { try { Component baseComponent = (Component) MESSAGE.get(internal); if (baseComponent != null) { - message = FormattedTextHelper.stringify(Handler.componentToSpigot(baseComponent)); rawJson = Component.Serializer.toJson(baseComponent); + message = PaperAPITools.instance.parseJsonToText(rawJson); } else { if (internal.components != null) { - message = FormattedTextHelper.stringify(internal.components); rawJson = ComponentSerializer.toString(internal.components); + message = PaperAPITools.instance.parseJsonToText(rawJson); } bungee = true; } diff --git a/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/impl/network/handlers/DenizenNetworkManagerImpl.java b/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/impl/network/handlers/DenizenNetworkManagerImpl.java index 60724c27f0..a6c2e78ba2 100644 --- a/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/impl/network/handlers/DenizenNetworkManagerImpl.java +++ b/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/impl/network/handlers/DenizenNetworkManagerImpl.java @@ -15,6 +15,7 @@ import com.denizenscript.denizen.scripts.commands.entity.*; import com.denizenscript.denizen.scripts.commands.player.DisguiseCommand; import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizen.utilities.Settings; import com.denizenscript.denizen.utilities.blocks.ChunkCoordinate; import com.denizenscript.denizen.utilities.blocks.FakeBlock; @@ -464,10 +465,10 @@ public boolean processActionbarPacket(Packet packet, PacketSendListener gener if (packet instanceof ClientboundSetActionBarTextPacket) { ClientboundSetActionBarTextPacket actionbarPacket = (ClientboundSetActionBarTextPacket) packet; PlayerReceivesActionbarScriptEvent event = PlayerReceivesActionbarScriptEvent.instance; - Component baseComponent = actionbarPacket.getText(); + String rawJson = Component.Serializer.toJson(actionbarPacket.getText()); event.reset(); - event.message = new ElementTag(FormattedTextHelper.stringify(Handler.componentToSpigot(baseComponent))); - event.rawJson = new ElementTag(Component.Serializer.toJson(baseComponent)); + event.message = new ElementTag(PaperAPITools.instance.parseJsonToText(rawJson), true); + event.rawJson = new ElementTag(rawJson, true); event.system = new ElementTag(false); event.player = PlayerTag.mirrorBukkitPlayer(player.getBukkitEntity()); event = (PlayerReceivesActionbarScriptEvent) event.triggerNow(); @@ -475,8 +476,7 @@ public boolean processActionbarPacket(Packet packet, PacketSendListener gener return true; } if (event.modified) { - Component component = Handler.componentToNMS(event.altMessageDetermination); - ClientboundSetActionBarTextPacket newPacket = new ClientboundSetActionBarTextPacket(component); + ClientboundSetActionBarTextPacket newPacket = new ClientboundSetActionBarTextPacket(Component.Serializer.fromJson(event.rawJson.asString())); oldManager.send(newPacket, genericfuturelistener); return true; } @@ -1237,7 +1237,7 @@ else if (packet instanceof ClientboundPlayerChatPacket playerChatPacket) { return true; } if (result.modified) { - oldManager.send(new ClientboundSystemChatPacket(result.altMessageDetermination, isActionbar), genericfuturelistener); + oldManager.send(new ClientboundSystemChatPacket(result.rawJson.asString(), isActionbar), genericfuturelistener); return true; } } diff --git a/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/impl/network/packets/PacketOutChatImpl.java b/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/impl/network/packets/PacketOutChatImpl.java index 1a7ed32da1..a06b378b8b 100644 --- a/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/impl/network/packets/PacketOutChatImpl.java +++ b/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/impl/network/packets/PacketOutChatImpl.java @@ -1,7 +1,7 @@ package com.denizenscript.denizen.nms.v1_19.impl.network.packets; import com.denizenscript.denizen.nms.interfaces.packets.PacketOutChat; -import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizencore.utilities.ReflectionHelper; import com.denizenscript.denizencore.utilities.debugging.Debug; import net.md_5.bungee.chat.ComponentSerializer; @@ -36,14 +36,14 @@ public PacketOutChatImpl(ClientboundSystemChatPacket internal) { Debug.echoError(ex); } } - message = FormattedTextHelper.stringify(ComponentSerializer.parse(rawJson)); + message = PaperAPITools.instance.parseJsonToText(rawJson); isOverlayActionbar = internal.overlay(); } public PacketOutChatImpl(ClientboundPlayerChatPacket internal) { playerPacket = internal; rawJson = ComponentSerializer.toString(internal.body().content()); - message = FormattedTextHelper.stringify(ComponentSerializer.parse(rawJson)); + message = PaperAPITools.instance.parseJsonToText(rawJson); } @Override diff --git a/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/impl/network/handlers/packet/ActionBarEventPacketHandlers.java b/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/impl/network/handlers/packet/ActionBarEventPacketHandlers.java index 7bb358a154..8479718a07 100644 --- a/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/impl/network/handlers/packet/ActionBarEventPacketHandlers.java +++ b/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/impl/network/handlers/packet/ActionBarEventPacketHandlers.java @@ -1,10 +1,9 @@ package com.denizenscript.denizen.nms.v1_20.impl.network.handlers.packet; import com.denizenscript.denizen.events.player.PlayerReceivesActionbarScriptEvent; -import com.denizenscript.denizen.nms.v1_20.Handler; import com.denizenscript.denizen.nms.v1_20.impl.network.handlers.DenizenNetworkManagerImpl; import com.denizenscript.denizen.objects.PlayerTag; -import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizencore.objects.core.ElementTag; import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.game.ClientboundSetActionBarTextPacket; @@ -22,9 +21,9 @@ public static ClientboundSetActionBarTextPacket processActionbarPacket(DenizenNe return actionbarPacket; } event.reset(); - Component actionbarText = actionbarPacket.text(); - event.message = new ElementTag(FormattedTextHelper.stringify(Handler.componentToSpigot(actionbarText)), true); - event.rawJson = new ElementTag(CraftChatMessage.toJSON(actionbarText), true); + String rawJson = CraftChatMessage.toJSON(actionbarPacket.text()); + event.message = new ElementTag(PaperAPITools.instance.parseJsonToText(rawJson), true); + event.rawJson = new ElementTag(rawJson, true); event.system = new ElementTag(false); event.player = PlayerTag.mirrorBukkitPlayer(networkManager.player.getBukkitEntity()); event = (PlayerReceivesActionbarScriptEvent) event.triggerNow(); @@ -32,7 +31,7 @@ public static ClientboundSetActionBarTextPacket processActionbarPacket(DenizenNe return null; } if (event.modified) { - return new ClientboundSetActionBarTextPacket(Handler.componentToNMS(event.altMessageDetermination)); + return new ClientboundSetActionBarTextPacket(CraftChatMessage.fromJSON(event.rawJson.asString())); } return actionbarPacket; } diff --git a/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/impl/network/handlers/packet/DenizenPacketHandlerPacketHandlers.java b/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/impl/network/handlers/packet/DenizenPacketHandlerPacketHandlers.java index bf1b80eb75..8ea4a50b65 100644 --- a/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/impl/network/handlers/packet/DenizenPacketHandlerPacketHandlers.java +++ b/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/impl/network/handlers/packet/DenizenPacketHandlerPacketHandlers.java @@ -8,6 +8,7 @@ import net.minecraft.network.protocol.game.ClientGamePacketListener; import net.minecraft.network.protocol.game.ClientboundPlayerChatPacket; import net.minecraft.network.protocol.game.ClientboundSystemChatPacket; +import org.bukkit.craftbukkit.v1_20_R4.util.CraftChatMessage; public class DenizenPacketHandlerPacketHandlers { @@ -37,7 +38,7 @@ else if (packet instanceof ClientboundPlayerChatPacket playerChatPacket) { return null; } if (result.modified) { - return new ClientboundSystemChatPacket(result.altMessageDetermination, isActionbar); + return new ClientboundSystemChatPacket(CraftChatMessage.fromJSON(result.rawJson.asString()), isActionbar); } } } diff --git a/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/impl/network/packets/PacketOutChatImpl.java b/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/impl/network/packets/PacketOutChatImpl.java index f8e82c3183..7bdc683926 100644 --- a/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/impl/network/packets/PacketOutChatImpl.java +++ b/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/impl/network/packets/PacketOutChatImpl.java @@ -1,7 +1,7 @@ package com.denizenscript.denizen.nms.v1_20.impl.network.packets; import com.denizenscript.denizen.nms.interfaces.packets.PacketOutChat; -import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.PaperAPITools; import net.md_5.bungee.chat.ComponentSerializer; import net.minecraft.network.protocol.game.ClientboundPlayerChatPacket; import net.minecraft.network.protocol.game.ClientboundSystemChatPacket; @@ -18,14 +18,14 @@ public class PacketOutChatImpl extends PacketOutChat { public PacketOutChatImpl(ClientboundSystemChatPacket internal) { systemPacket = internal; rawJson = CraftChatMessage.toJSON(internal.content()); - message = FormattedTextHelper.stringify(ComponentSerializer.parse(rawJson)); + message = PaperAPITools.instance.parseJsonToText(rawJson); isOverlayActionbar = internal.overlay(); } public PacketOutChatImpl(ClientboundPlayerChatPacket internal) { playerPacket = internal; rawJson = ComponentSerializer.toString(internal.body().content()); - message = FormattedTextHelper.stringify(ComponentSerializer.parse(rawJson)); + message = PaperAPITools.instance.parseJsonToText(rawJson); } @Override diff --git a/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/impl/network/handlers/packet/ActionBarEventPacketHandlers.java b/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/impl/network/handlers/packet/ActionBarEventPacketHandlers.java index 0f3ef55965..623e14bbbe 100644 --- a/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/impl/network/handlers/packet/ActionBarEventPacketHandlers.java +++ b/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/impl/network/handlers/packet/ActionBarEventPacketHandlers.java @@ -1,10 +1,9 @@ package com.denizenscript.denizen.nms.v1_21.impl.network.handlers.packet; import com.denizenscript.denizen.events.player.PlayerReceivesActionbarScriptEvent; -import com.denizenscript.denizen.nms.v1_21.Handler; import com.denizenscript.denizen.nms.v1_21.impl.network.handlers.DenizenNetworkManagerImpl; import com.denizenscript.denizen.objects.PlayerTag; -import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizencore.objects.core.ElementTag; import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.game.ClientboundSetActionBarTextPacket; @@ -22,9 +21,9 @@ public static ClientboundSetActionBarTextPacket processActionbarPacket(DenizenNe return actionbarPacket; } event.reset(); - Component actionbarText = actionbarPacket.text(); - event.message = new ElementTag(FormattedTextHelper.stringify(Handler.componentToSpigot(actionbarText)), true); - event.rawJson = new ElementTag(CraftChatMessage.toJSON(actionbarText), true); + String rawJson = CraftChatMessage.toJSON(actionbarPacket.text()); + event.message = new ElementTag(PaperAPITools.instance.parseJsonToText(rawJson), true); + event.rawJson = new ElementTag(rawJson, true); event.system = new ElementTag(false); event.player = PlayerTag.mirrorBukkitPlayer(networkManager.player.getBukkitEntity()); event = (PlayerReceivesActionbarScriptEvent) event.triggerNow(); @@ -32,7 +31,7 @@ public static ClientboundSetActionBarTextPacket processActionbarPacket(DenizenNe return null; } if (event.modified) { - return new ClientboundSetActionBarTextPacket(Handler.componentToNMS(event.altMessageDetermination)); + return new ClientboundSetActionBarTextPacket(CraftChatMessage.fromJSON(event.rawJson.asString())); } return actionbarPacket; } diff --git a/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/impl/network/handlers/packet/DenizenPacketHandlerPacketHandlers.java b/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/impl/network/handlers/packet/DenizenPacketHandlerPacketHandlers.java index cd8abd286c..f016edd476 100644 --- a/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/impl/network/handlers/packet/DenizenPacketHandlerPacketHandlers.java +++ b/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/impl/network/handlers/packet/DenizenPacketHandlerPacketHandlers.java @@ -8,6 +8,7 @@ import net.minecraft.network.protocol.game.ClientGamePacketListener; import net.minecraft.network.protocol.game.ClientboundPlayerChatPacket; import net.minecraft.network.protocol.game.ClientboundSystemChatPacket; +import org.bukkit.craftbukkit.v1_21_R5.util.CraftChatMessage; public class DenizenPacketHandlerPacketHandlers { @@ -37,7 +38,7 @@ else if (packet instanceof ClientboundPlayerChatPacket playerChatPacket) { return null; } if (result.modified) { - return new ClientboundSystemChatPacket(result.altMessageDetermination, isActionbar); + return new ClientboundSystemChatPacket(CraftChatMessage.fromJSON(result.rawJson.asString()), isActionbar); } } } diff --git a/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/impl/network/packets/PacketOutChatImpl.java b/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/impl/network/packets/PacketOutChatImpl.java index 56ec98bb64..8ec7c2b23e 100644 --- a/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/impl/network/packets/PacketOutChatImpl.java +++ b/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/impl/network/packets/PacketOutChatImpl.java @@ -1,7 +1,7 @@ package com.denizenscript.denizen.nms.v1_21.impl.network.packets; import com.denizenscript.denizen.nms.interfaces.packets.PacketOutChat; -import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.PaperAPITools; import net.md_5.bungee.chat.ComponentSerializer; import net.minecraft.network.protocol.game.ClientboundPlayerChatPacket; import net.minecraft.network.protocol.game.ClientboundSystemChatPacket; @@ -18,14 +18,14 @@ public class PacketOutChatImpl extends PacketOutChat { public PacketOutChatImpl(ClientboundSystemChatPacket internal) { systemPacket = internal; rawJson = CraftChatMessage.toJSON(internal.content()); - message = FormattedTextHelper.stringify(FormattedTextHelper.parseJson(rawJson)); + message = PaperAPITools.instance.parseJsonToText(rawJson); isOverlayActionbar = internal.overlay(); } public PacketOutChatImpl(ClientboundPlayerChatPacket internal) { playerPacket = internal; rawJson = ComponentSerializer.toString(internal.body().content()); - message = FormattedTextHelper.stringify(FormattedTextHelper.parseJson(rawJson)); + message = PaperAPITools.instance.parseJsonToText(rawJson); } @Override From 55268a99c5705e3eedc331efed43e028ecba08f2 Mon Sep 17 00:00:00 2001 From: Aya <31237389+tal5@users.noreply.github.com> Date: Tue, 9 Sep 2025 01:09:03 +0100 Subject: [PATCH 11/24] `ItemBook`: update --- .../paper/utilities/PaperAPIToolsImpl.java | 30 ++++++++++ .../objects/properties/item/ItemBook.java | 57 ++++--------------- .../denizen/utilities/PaperAPITools.java | 23 ++++++++ 3 files changed, 64 insertions(+), 46 deletions(-) diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java index 8c1ab32fec..b7f1e39b88 100644 --- a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java +++ b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java @@ -11,6 +11,7 @@ import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizencore.DenizenCore; import com.denizenscript.denizencore.objects.core.ElementTag; +import com.denizenscript.denizencore.objects.core.ListTag; import com.denizenscript.denizencore.tags.TagContext; import com.denizenscript.denizencore.utilities.CoreUtilities; import com.denizenscript.denizencore.utilities.ReflectionHelper; @@ -35,6 +36,7 @@ import org.bukkit.event.inventory.InventoryType; import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.inventory.*; +import org.bukkit.inventory.meta.BookMeta; import org.bukkit.inventory.meta.PotionMeta; import org.bukkit.potion.PotionBrewer; import org.bukkit.scoreboard.Team; @@ -402,6 +404,34 @@ public void setMaterialTags(Material type, Set tags) { BlockTagsSetter.INSTANCE.setTags(type, tags); } + @Override + public String getPage(BookMeta meta, int page) { + return FormattedTextHelper.stringify(meta.page(page)); + } + + @Override + public ListTag getPages(BookMeta meta) { + return new ListTag(meta.pages(), page -> new ElementTag(FormattedTextHelper.stringify(page), true)); + } + + @Override + public void setPages(BookMeta meta, List pages) { + List parsedPages = new ArrayList<>(pages.size()); + for (String page : pages) { + parsedPages.add(FormattedTextHelper.parse(page, NamedTextColor.BLACK)); + } + meta.pages(parsedPages); + } + + @Override + public void setJsonPages(BookMeta meta, List jsonPages) { + List parsedPages = new ArrayList<>(jsonPages.size()); + for (String jsonPage : jsonPages) { + parsedPages.add(PaperModule.jsonToComponent(jsonPage)); + } + meta.pages(parsedPages); + } + @Override public String parseTextToJson(String formattedText, BaseColor baseColor) { return PaperModule.componentToJson(FormattedTextHelper.parse(formattedText, baseColor == BaseColor.WHITE ? NamedTextColor.WHITE : NamedTextColor.BLACK)); diff --git a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/item/ItemBook.java b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/item/ItemBook.java index b428803ccf..4aacdb64f1 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/item/ItemBook.java +++ b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/item/ItemBook.java @@ -2,7 +2,7 @@ import com.denizenscript.denizen.objects.ItemTag; import com.denizenscript.denizen.utilities.BukkitImplDeprecations; -import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.objects.core.ListTag; @@ -10,14 +10,9 @@ import com.denizenscript.denizencore.objects.properties.Property; import com.denizenscript.denizencore.objects.properties.PropertyParser; import com.denizenscript.denizencore.tags.core.EscapeTagUtil; -import net.md_5.bungee.api.ChatColor; -import net.md_5.bungee.api.chat.BaseComponent; import org.bukkit.Material; import org.bukkit.inventory.meta.BookMeta; -import java.util.ArrayList; -import java.util.List; - public class ItemBook implements Property { public static boolean describes(ObjectTag item) { @@ -89,12 +84,7 @@ public static void register() { // Returns the plain-text pages of the book as a ListTag. // --> PropertyParser.registerTag(ItemBook.class, ListTag.class, "book_pages", (attribute, object) -> { - List pages = object.getBookMeta().spigot().getPages(); - ListTag pageList = new ListTag(pages.size()); - for (BaseComponent[] page : pages) { - pageList.addObject(new ElementTag(FormattedTextHelper.stringify(page), true)); - } - return pageList; + return PaperAPITools.instance.getPages(object.getBookMeta()); }); // <--[tag] @@ -129,15 +119,11 @@ public static void register() { } if ((attribute.startsWith("page", 2) || attribute.startsWith("get_page", 2)) && attribute.hasContext(2)) { attribute.fulfill(1); - return new ElementTag(FormattedTextHelper.stringify(bookMeta.spigot().getPage(attribute.getIntParam()))); + return new ElementTag(PaperAPITools.instance.getPage(bookMeta, attribute.getIntParam())); } if (attribute.startsWith("pages", 2)) { attribute.fulfill(1); - ListTag output = new ListTag(); - for (BaseComponent[] page : bookMeta.spigot().getPages()) { - output.add(FormattedTextHelper.stringify(page)); - } - return output; + return PaperAPITools.instance.getPages(bookMeta); } String output = object.getOutputString(); if (output == null) { @@ -157,11 +143,7 @@ public static void register() { // --> PropertyParser.registerMechanism(ItemBook.class, ListTag.class, "book_pages", (object, mechanism, input) -> { BookMeta bookMeta = object.getBookMeta(); - List newPages = new ArrayList<>(input.size()); - for (String page : input) { - newPages.add(FormattedTextHelper.parse(page, ChatColor.BLACK)); - } - bookMeta.spigot().setPages(newPages); + PaperAPITools.instance.setPages(bookMeta, input); object.item.setItemMeta(bookMeta); }); @@ -242,11 +224,7 @@ public static void register() { } ListTag pages = bookMap.getObjectAs("pages", ListTag.class, mechanism.context); if (pages != null) { - List newPages = new ArrayList<>(pages.size()); - for (String page : pages) { - newPages.add(FormattedTextHelper.parse(page, ChatColor.BLACK)); - } - bookMeta.spigot().setPages(newPages); + PaperAPITools.instance.setPages(bookMeta, pages); } object.item.setItemMeta(bookMeta); return; @@ -274,18 +252,10 @@ public static void register() { } } if (data.get(0).equalsIgnoreCase("raw_pages")) { - List newPages = new ArrayList<>(data.size()); - for (int i = 1; i < data.size(); i++) { - newPages.add(FormattedTextHelper.parseJson(EscapeTagUtil.unEscape(data.get(i)))); - } - bookMeta.spigot().setPages(newPages); + PaperAPITools.instance.setJsonPages(bookMeta, data.stream().skip(1).map(EscapeTagUtil::unEscape).toList()); } else if (data.get(0).equalsIgnoreCase("pages")) { - List newPages = new ArrayList<>(data.size()); - for (int i = 1; i < data.size(); i++) { - newPages.add(FormattedTextHelper.parse(EscapeTagUtil.unEscape(data.get(i)), ChatColor.BLACK)); - } - bookMeta.spigot().setPages(newPages); + PaperAPITools.instance.setPages(bookMeta, data.stream().skip(1).map(EscapeTagUtil::unEscape).toList()); } else { mechanism.echoError("Invalid book input!"); @@ -304,12 +274,7 @@ public MapTag getBookMap() { bookMap.putObject("title", new ElementTag(bookMeta.getTitle(), true)); } if (bookMeta.hasPages()) { - List pages = bookMeta.spigot().getPages(); - ListTag pageList = new ListTag(pages.size()); - for (BaseComponent[] page : pages) { - pageList.addObject(new ElementTag(FormattedTextHelper.stringify(page), true)); - } - bookMap.putObject("pages", pageList); + bookMap.putObject("pages", PaperAPITools.instance.getPages(bookMeta)); } return bookMap; } @@ -332,8 +297,8 @@ public String getOutputString() { } output.append("pages|"); if (bookMeta.hasPages()) { - for (BaseComponent[] page : bookMeta.spigot().getPages()) { - output.append(EscapeTagUtil.escape(FormattedTextHelper.stringify(page))).append("|"); + for (String page : PaperAPITools.instance.getPages(bookMeta)) { + output.append(EscapeTagUtil.escape(page)).append("|"); } } return output.substring(0, output.length() - 1); diff --git a/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java b/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java index 7f18aca504..d3984e8077 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java +++ b/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java @@ -5,6 +5,7 @@ import com.denizenscript.denizen.scripts.commands.entity.TeleportCommand; import com.denizenscript.denizen.scripts.containers.core.ItemScriptContainer; import com.denizenscript.denizen.utilities.packets.NetworkInterceptHelper; +import com.denizenscript.denizencore.objects.core.ListTag; import com.denizenscript.denizencore.utilities.ReflectionHelper; import com.denizenscript.denizencore.utilities.debugging.Debug; import net.md_5.bungee.api.ChatColor; @@ -23,11 +24,13 @@ import org.bukkit.event.inventory.InventoryType; import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.inventory.*; +import org.bukkit.inventory.meta.BookMeta; import org.bukkit.inventory.meta.PotionMeta; import org.bukkit.scoreboard.Team; import org.bukkit.util.Consumer; import java.lang.invoke.MethodHandle; +import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.function.Predicate; @@ -237,6 +240,26 @@ public void setMaterialTags(Material type, Set tags) { NMSHandler.blockHelper.setVanillaTags(type, tags); } + public String getPage(BookMeta meta, int page) { + return meta.getPage(page); + } + + public ListTag getPages(BookMeta meta) { + return new ListTag(meta.getPages()); + } + + public void setPages(BookMeta meta, List pages) { + meta.setPages(pages); + } + + public void setJsonPages(BookMeta meta, List jsonPages) { + List parsedPages = new ArrayList<>(jsonPages.size()); + for (String jsonPage : jsonPages) { + parsedPages.add(ComponentSerializer.parse(jsonPage)); + } + meta.spigot().setPages(parsedPages); + } + public enum BaseColor { WHITE, BLACK } public String parseTextToJson(String formattedText, BaseColor baseColor) { From faf5f45c98210d7dac1716d40447f8f8f98c1c85 Mon Sep 17 00:00:00 2001 From: Aya <31237389+tal5@users.noreply.github.com> Date: Wed, 10 Sep 2025 01:04:03 +0100 Subject: [PATCH 12/24] `FormattedTextHelper`: minor parsing fixes --- .../paper/utilities/FormattedTextHelper.java | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/FormattedTextHelper.java b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/FormattedTextHelper.java index ea85328cfa..85bf98ad5b 100644 --- a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/FormattedTextHelper.java +++ b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/FormattedTextHelper.java @@ -176,12 +176,11 @@ public static boolean hasRootFormat(Component component) { return hasRootFormat(children.get(0)); } - // TODO stringification methods? public static String stringify(Component component) { if (component == null) { return null; } - String output = stringifySub(component, null); + String output = stringifySub(component); if (hasRootFormat(component)) { output = RESET + output; } @@ -209,10 +208,9 @@ public static String stringifyRGBSpigot(String hex) { return outColor.toString(); } - // TODO stringification methods? -// public static String stringify(Component component) { -// return stringifySub(component, null); -// } + public static String stringifySub(Component component) { + return stringifySub(component, null); + } public static String stringifySub(Component component, TextColor parentColor) { if (component == null) { @@ -275,7 +273,7 @@ else if (component instanceof TranslatableComponent translatableComponent) { map.putObject("fallback", new ElementTag(translatableComponent.fallback(), true)); } if (!translatableComponent.arguments().isEmpty()) { - map.putObject("with", new ListTag(translatableComponent.arguments(), argument -> new ElementTag(stringify(argument.asComponent()), true))); + map.putObject("with", new ListTag(translatableComponent.arguments(), argument -> new ElementTag(stringifySub(argument.asComponent()), true))); } builder.append(LEGACY_SECTION).append("[translate=").append(escape(map.savable())).append(']'); } @@ -604,11 +602,10 @@ public static Component parseInternal(String str, TextColor baseColor, boolean c if (str.startsWith(LEGACY_SECTION + "[translate=") && str.indexOf(']') == str.length() - 1) { return parseTranslatable(str.substring("&[translate=".length(), str.length() - 1), baseColor, optimize); } - if (str.length() > 3 && str.startsWith((LEGACY_SECTION + "")) && hexMatcher.isMatch(str.charAt(1)) + if (str.length() > 3 && str.startsWith(LEGACY_SECTION + "") && hexMatcher.isMatch(str.charAt(1)) && str.startsWith(LEGACY_SECTION + "[translate=", 2) && str.indexOf(']') == str.length() - 1) { // eg "&6&[translate=block.minecraft.ominous_banner]" Component component = parseTranslatable(str.substring("&[translate=".length() + 2, str.length() - 1), baseColor, optimize); - component.color(LegacyColor.fromChar(str.charAt(1))); - return component; + return component.color(LegacyColor.fromChar(str.charAt(1))); } } if (!optimize) { From c879115a778f01b38f5e1b5128bb90102e817125 Mon Sep 17 00:00:00 2001 From: Aya <31237389+tal5@users.noreply.github.com> Date: Wed, 10 Sep 2025 01:08:37 +0100 Subject: [PATCH 13/24] `ActionBarCommand`: update --- .../denizen/paper/utilities/PaperAPIToolsImpl.java | 5 +++++ .../denizen/scripts/commands/player/ActionBarCommand.java | 6 ++---- .../com/denizenscript/denizen/utilities/PaperAPITools.java | 5 +++++ 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java index b7f1e39b88..d431b4a267 100644 --- a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java +++ b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java @@ -432,6 +432,11 @@ public void setJsonPages(BookMeta meta, List jsonPages) { meta.pages(parsedPages); } + @Override + public void sendActionBar(Player player, String text) { + player.sendActionBar(FormattedTextHelper.parse(text, NamedTextColor.WHITE)); + } + @Override public String parseTextToJson(String formattedText, BaseColor baseColor) { return PaperModule.componentToJson(FormattedTextHelper.parse(formattedText, baseColor == BaseColor.WHITE ? NamedTextColor.WHITE : NamedTextColor.BLACK)); diff --git a/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/player/ActionBarCommand.java b/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/player/ActionBarCommand.java index 46c26002d2..7e06cf300c 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/player/ActionBarCommand.java +++ b/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/player/ActionBarCommand.java @@ -2,7 +2,7 @@ import com.denizenscript.denizen.objects.PlayerTag; import com.denizenscript.denizen.tags.BukkitTagContext; -import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizen.utilities.Utilities; import com.denizenscript.denizencore.exceptions.InvalidArgumentsException; import com.denizenscript.denizencore.objects.Argument; @@ -16,8 +16,6 @@ import com.denizenscript.denizencore.scripts.containers.core.FormatScriptContainer; import com.denizenscript.denizencore.tags.TagManager; import com.denizenscript.denizencore.utilities.debugging.Debug; -import net.md_5.bungee.api.ChatColor; -import net.md_5.bungee.api.ChatMessageType; import java.util.Collections; import java.util.List; @@ -135,7 +133,7 @@ public void execute(ScriptEntry scriptEntry) { context.player = player; personalText = TagManager.tag(personalText, context); } - player.getPlayerEntity().spigot().sendMessage(ChatMessageType.ACTION_BAR, FormattedTextHelper.parse(format != null ? format.getFormattedText(personalText, scriptEntry) : personalText, ChatColor.WHITE)); + PaperAPITools.instance.sendActionBar(player.getPlayerEntity(), format != null ? format.getFormattedText(personalText, scriptEntry) : personalText); } else { Debug.echoError("Sent actionbar to non-existent player!?"); diff --git a/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java b/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java index d3984e8077..b7d31d17a9 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java +++ b/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java @@ -9,6 +9,7 @@ import com.denizenscript.denizencore.utilities.ReflectionHelper; import com.denizenscript.denizencore.utilities.debugging.Debug; import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.ChatMessageType; import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.chat.TextComponent; import net.md_5.bungee.chat.ComponentSerializer; @@ -260,6 +261,10 @@ public void setJsonPages(BookMeta meta, List jsonPages) { meta.spigot().setPages(parsedPages); } + public void sendActionBar(Player player, String text) { + player.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacy(text)); + } + public enum BaseColor { WHITE, BLACK } public String parseTextToJson(String formattedText, BaseColor baseColor) { From 2854d59834c1f96165fc11ae3e324431a4b68f79 Mon Sep 17 00:00:00 2001 From: Aya <31237389+tal5@users.noreply.github.com> Date: Wed, 10 Sep 2025 10:04:07 +0100 Subject: [PATCH 14/24] `NarrateCommand`: update --- .../denizen/paper/utilities/PaperAPIToolsImpl.java | 11 +++++++++++ .../scripts/commands/player/NarrateCommand.java | 14 ++++++-------- .../denizen/utilities/PaperAPITools.java | 9 +++++++++ 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java index d431b4a267..4403ce9204 100644 --- a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java +++ b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java @@ -20,6 +20,7 @@ import com.destroystokyo.paper.profile.ProfileProperty; import io.papermc.paper.entity.TeleportFlag; import io.papermc.paper.potion.PotionMix; +import net.kyori.adventure.identity.Identity; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.minimessage.MiniMessage; @@ -432,6 +433,16 @@ public void setJsonPages(BookMeta meta, List jsonPages) { meta.pages(parsedPages); } + @Override + public void sendMessage(CommandSender sender, String text) { + sender.sendMessage(FormattedTextHelper.parse(text, NamedTextColor.WHITE)); + } + + @Override + public void sendMessage(CommandSender sender, String text, UUID senderId) { + sender.sendMessage(Identity.identity(senderId), FormattedTextHelper.parse(text, NamedTextColor.WHITE)); + } + @Override public void sendActionBar(Player player, String text) { player.sendActionBar(FormattedTextHelper.parse(text, NamedTextColor.WHITE)); diff --git a/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/player/NarrateCommand.java b/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/player/NarrateCommand.java index eca26b3eee..38d33f46d0 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/player/NarrateCommand.java +++ b/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/player/NarrateCommand.java @@ -2,7 +2,7 @@ import com.denizenscript.denizen.objects.PlayerTag; import com.denizenscript.denizen.tags.BukkitTagContext; -import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizen.utilities.Utilities; import com.denizenscript.denizencore.exceptions.InvalidArgumentsException; import com.denizenscript.denizencore.objects.Argument; @@ -18,9 +18,6 @@ import com.denizenscript.denizencore.scripts.containers.core.FormatScriptContainer; import com.denizenscript.denizencore.tags.TagManager; import com.denizenscript.denizencore.utilities.debugging.Debug; -import net.md_5.bungee.api.ChatColor; -import net.md_5.bungee.api.ChatMessageType; -import net.md_5.bungee.api.chat.BaseComponent; import org.bukkit.Bukkit; import java.util.Collections; @@ -133,6 +130,7 @@ public void execute(ScriptEntry scriptEntry) { if (scriptEntry.dbCallShouldDebug()) { Debug.report(scriptEntry, getName(), db("Narrating", text), db("Targets", targets), formatObj, perPlayerObj, from); } + // TODO: as of signed chat, this has no effect. Either add proper signed chat support or deprecate. UUID fromId = null; if (from != null) { if (from.asString().startsWith("p@")) { @@ -151,7 +149,7 @@ public void execute(ScriptEntry scriptEntry) { formattingContext = scriptContainer != null ? scriptContainer.getFormattingContext() : null; } if (targets == null) { - Bukkit.getServer().getConsoleSender().spigot().sendMessage(FormattedTextHelper.parse(formattingContext != null ? formattingContext.format(NARRATE_FORMAT_TYPE, text, scriptEntry) : text, ChatColor.WHITE)); + PaperAPITools.instance.sendMessage(Bukkit.getServer().getConsoleSender(), formattingContext != null ? formattingContext.format(NARRATE_FORMAT_TYPE, text, scriptEntry) : text); return; } for (PlayerTag player : targets) { @@ -165,12 +163,12 @@ public void execute(ScriptEntry scriptEntry) { context.player = player; personalText = TagManager.tag(personalText, context); } - BaseComponent[] component = FormattedTextHelper.parse(formattingContext != null ? formattingContext.format(NARRATE_FORMAT_TYPE, personalText, scriptEntry) : personalText, ChatColor.WHITE); + String formattedText = formattingContext != null ? formattingContext.format(NARRATE_FORMAT_TYPE, personalText, scriptEntry) : personalText; if (fromId == null) { - player.getPlayerEntity().spigot().sendMessage(component); + PaperAPITools.instance.sendMessage(player.getPlayerEntity(), formattedText); } else { - player.getPlayerEntity().spigot().sendMessage(ChatMessageType.CHAT, fromId, component); + PaperAPITools.instance.sendMessage(player.getPlayerEntity(), formattedText, fromId); } } else { diff --git a/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java b/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java index b7d31d17a9..8c9817f237 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java +++ b/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java @@ -34,6 +34,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Set; +import java.util.UUID; import java.util.function.Predicate; public class PaperAPITools { @@ -261,6 +262,14 @@ public void setJsonPages(BookMeta meta, List jsonPages) { meta.spigot().setPages(parsedPages); } + public void sendMessage(CommandSender sender, String text) { + sender.sendMessage(text); + } + + public void sendMessage(CommandSender sender, String text, UUID senderId) { + sender.sendMessage(senderId, text); + } + public void sendActionBar(Player player, String text) { player.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacy(text)); } From b3adfda681b4092bd7a48e1059ccf6da81b78f53 Mon Sep 17 00:00:00 2001 From: Aya <31237389+tal5@users.noreply.github.com> Date: Wed, 10 Sep 2025 11:03:06 +0100 Subject: [PATCH 15/24] `AnnounceCommand`: update --- .../paper/utilities/PaperAPIToolsImpl.java | 13 ++++++++++ .../commands/server/AnnounceCommand.java | 26 +++++-------------- .../denizen/utilities/PaperAPITools.java | 8 ++++++ 3 files changed, 27 insertions(+), 20 deletions(-) diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java index 4403ce9204..71d3a25b5b 100644 --- a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java +++ b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java @@ -443,6 +443,19 @@ public void sendMessage(CommandSender sender, String text, UUID senderId) { sender.sendMessage(Identity.identity(senderId), FormattedTextHelper.parse(text, NamedTextColor.WHITE)); } + @Override + public void broadcast(String text, Predicate filter) { + Component message = null; + for (Player player : Bukkit.getOnlinePlayers()) { + if (filter == null || filter.test(player)) { + if (message == null) { + message = FormattedTextHelper.parse(text, NamedTextColor.WHITE); + } + player.sendMessage(message); + } + } + } + @Override public void sendActionBar(Player player, String text) { player.sendActionBar(FormattedTextHelper.parse(text, NamedTextColor.WHITE)); diff --git a/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/server/AnnounceCommand.java b/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/server/AnnounceCommand.java index 7d9f0ca4e5..d5aa13fcac 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/server/AnnounceCommand.java +++ b/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/server/AnnounceCommand.java @@ -1,8 +1,7 @@ package com.denizenscript.denizen.scripts.commands.server; -import com.denizenscript.denizen.Denizen; import com.denizenscript.denizen.objects.PlayerTag; -import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizencore.exceptions.InvalidArgumentsException; import com.denizenscript.denizencore.objects.Argument; import com.denizenscript.denizencore.objects.core.ElementTag; @@ -13,7 +12,6 @@ import com.denizenscript.denizencore.scripts.containers.ScriptContainer; import com.denizenscript.denizencore.scripts.containers.core.FormatScriptContainer; import com.denizenscript.denizencore.utilities.debugging.Debug; -import net.md_5.bungee.api.ChatColor; import org.bukkit.Bukkit; import org.bukkit.entity.Player; @@ -137,30 +135,18 @@ public void execute(ScriptEntry scriptEntry) { // Use Bukkit to broadcast the message to everybody in the server. switch (type) { case ALL: - Denizen.getInstance().getServer().spigot().broadcast(FormattedTextHelper.parse(message, ChatColor.WHITE)); + PaperAPITools.instance.broadcast(message, null); break; case TO_OPS: - for (Player player : Bukkit.getOnlinePlayers()) { - if (player.isOp()) { - player.spigot().sendMessage(FormattedTextHelper.parse(message, ChatColor.WHITE)); - } - } + PaperAPITools.instance.broadcast(message, Player::isOp); break; case TO_PERMISSION: - for (Player player : Bukkit.getOnlinePlayers()) { - if (player.hasPermission(flag.asString())) { - player.spigot().sendMessage(FormattedTextHelper.parse(message, ChatColor.WHITE)); - } - } + PaperAPITools.instance.broadcast(message, player -> player.hasPermission(flag.asString())); case TO_FLAGGED: - for (Player player : Bukkit.getOnlinePlayers()) { - if (new PlayerTag(player).getFlagTracker().hasFlag(flag.asString())) { - player.spigot().sendMessage(FormattedTextHelper.parse(message, ChatColor.WHITE)); - } - } + PaperAPITools.instance.broadcast(message, player -> new PlayerTag(player).getFlagTracker().hasFlag(flag.asString())); break; case TO_CONSOLE: - Bukkit.getServer().getConsoleSender().spigot().sendMessage(FormattedTextHelper.parse(message, ChatColor.WHITE)); + PaperAPITools.instance.sendMessage(Bukkit.getServer().getConsoleSender(), message); break; } } diff --git a/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java b/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java index 8c9817f237..b71eeb3ffe 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java +++ b/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java @@ -270,6 +270,14 @@ public void sendMessage(CommandSender sender, String text, UUID senderId) { sender.sendMessage(senderId, text); } + public void broadcast(String text, Predicate filter) { + for (Player player : Bukkit.getOnlinePlayers()) { + if (filter == null || filter.test(player)) { + player.sendMessage(text); + } + } + } + public void sendActionBar(Player player, String text) { player.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacy(text)); } From 1d9a84df4d43c5a434b809dfc30b5215b7c12a33 Mon Sep 17 00:00:00 2001 From: Aya <31237389+tal5@users.noreply.github.com> Date: Wed, 10 Sep 2025 11:12:44 +0100 Subject: [PATCH 16/24] `BookScriptContainer`: update --- .../denizen/paper/utilities/PaperAPIToolsImpl.java | 5 +++++ .../scripts/containers/core/BookScriptContainer.java | 6 ++---- .../com/denizenscript/denizen/utilities/PaperAPITools.java | 4 ++++ 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java index 71d3a25b5b..994e8e1ce5 100644 --- a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java +++ b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java @@ -415,6 +415,11 @@ public ListTag getPages(BookMeta meta) { return new ListTag(meta.pages(), page -> new ElementTag(FormattedTextHelper.stringify(page), true)); } + @Override + public void addPage(BookMeta meta, String page) { + meta.addPages(FormattedTextHelper.parse(page, NamedTextColor.BLACK)); + } + @Override public void setPages(BookMeta meta, List pages) { List parsedPages = new ArrayList<>(pages.size()); diff --git a/plugin/src/main/java/com/denizenscript/denizen/scripts/containers/core/BookScriptContainer.java b/plugin/src/main/java/com/denizenscript/denizen/scripts/containers/core/BookScriptContainer.java index f2ab0280f1..32811c1769 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/scripts/containers/core/BookScriptContainer.java +++ b/plugin/src/main/java/com/denizenscript/denizen/scripts/containers/core/BookScriptContainer.java @@ -2,13 +2,12 @@ import com.denizenscript.denizen.objects.ItemTag; import com.denizenscript.denizen.tags.BukkitTagContext; -import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizencore.objects.core.ScriptTag; import com.denizenscript.denizencore.scripts.containers.ScriptContainer; import com.denizenscript.denizencore.tags.TagContext; import com.denizenscript.denizencore.tags.TagManager; import com.denizenscript.denizencore.utilities.YamlConfiguration; -import net.md_5.bungee.api.ChatColor; import org.bukkit.Material; import org.bukkit.inventory.meta.BookMeta; @@ -94,8 +93,7 @@ public ItemTag writeBookTo(ItemTag book, TagContext context) { if (contains("text", List.class)) { List pages = getStringList("text"); for (String page : pages) { - page = TagManager.tag(page, context); - bookInfo.spigot().addPage(FormattedTextHelper.parse(page, ChatColor.BLACK)); + PaperAPITools.instance.addPage(bookInfo, TagManager.tag(page, context)); } } book.setItemMeta(bookInfo); diff --git a/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java b/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java index b71eeb3ffe..b1e51f3b6d 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java +++ b/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java @@ -250,6 +250,10 @@ public ListTag getPages(BookMeta meta) { return new ListTag(meta.getPages()); } + public void addPage(BookMeta meta, String page) { + meta.addPage(page); + } + public void setPages(BookMeta meta, List pages) { meta.setPages(pages); } From ad83ef1d1aacbae1fc406bd0b027ae3a9bd9356a Mon Sep 17 00:00:00 2001 From: Aya <31237389+tal5@users.noreply.github.com> Date: Wed, 10 Sep 2025 14:16:27 +0100 Subject: [PATCH 17/24] `EnchantmentScriptContainer`: update --- .../denizen/paper/utilities/PaperAPIToolsImpl.java | 6 +++++- .../core/EnchantmentScriptContainer.java | 14 ++++++-------- .../denizen/utilities/PaperAPITools.java | 8 ++++++-- .../nms/v1_17/helpers/EnchantmentHelperImpl.java | 4 ++-- .../nms/v1_18/helpers/EnchantmentHelperImpl.java | 4 ++-- .../nms/v1_19/helpers/EnchantmentHelperImpl.java | 4 ++-- .../nms/v1_20/helpers/EnchantmentHelperImpl.java | 3 ++- 7 files changed, 25 insertions(+), 18 deletions(-) diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java index 994e8e1ce5..8f977f388a 100644 --- a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java +++ b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java @@ -468,7 +468,11 @@ public void sendActionBar(Player player, String text) { @Override public String parseTextToJson(String formattedText, BaseColor baseColor) { - return PaperModule.componentToJson(FormattedTextHelper.parse(formattedText, baseColor == BaseColor.WHITE ? NamedTextColor.WHITE : NamedTextColor.BLACK)); + return PaperModule.componentToJson(FormattedTextHelper.parse(formattedText, switch (baseColor) { + case WHITE -> NamedTextColor.WHITE; + case BLACK -> NamedTextColor.BLACK; + case GRAY -> NamedTextColor.GRAY; + })); } @Override diff --git a/plugin/src/main/java/com/denizenscript/denizen/scripts/containers/core/EnchantmentScriptContainer.java b/plugin/src/main/java/com/denizenscript/denizen/scripts/containers/core/EnchantmentScriptContainer.java index 29c080c550..3752675dff 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/scripts/containers/core/EnchantmentScriptContainer.java +++ b/plugin/src/main/java/com/denizenscript/denizen/scripts/containers/core/EnchantmentScriptContainer.java @@ -4,8 +4,7 @@ import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.objects.ItemTag; import com.denizenscript.denizen.tags.BukkitTagContext; -import com.denizenscript.denizen.utilities.FormattedTextHelper; -import com.denizenscript.denizencore.utilities.debugging.Debug; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.objects.core.ScriptTag; @@ -18,8 +17,7 @@ import com.denizenscript.denizencore.utilities.AsciiMatcher; import com.denizenscript.denizencore.utilities.CoreUtilities; import com.denizenscript.denizencore.utilities.YamlConfiguration; -import net.md_5.bungee.api.ChatColor; -import net.md_5.bungee.api.chat.BaseComponent; +import com.denizenscript.denizencore.utilities.debugging.Debug; import org.bukkit.Bukkit; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Entity; @@ -225,7 +223,7 @@ public EnchantmentScriptContainer(YamlConfiguration configurationSection, String public List slots; - public HashMap fullNamePerLevel = new HashMap<>(); + public HashMap fullNamePerLevel = new HashMap<>(); public Enchantment enchantment; @@ -280,13 +278,13 @@ public boolean isCompatible(Enchantment enchantment) { return CoreUtilities.toLowerCase(res).equals("true"); } - public BaseComponent[] getFullName(int level) { - BaseComponent[] result = fullNamePerLevel.get(level); + public String getFullName(int level) { + String result = fullNamePerLevel.get(level); if (result != null) { return result; } String tagged = autoTagForLevel(fullNameTaggable, level); - result = FormattedTextHelper.parse(tagged, ChatColor.GRAY); + result = PaperAPITools.instance.parseTextToJson(tagged, PaperAPITools.BaseColor.GRAY); fullNamePerLevel.put(level, result); return result; } diff --git a/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java b/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java index b1e51f3b6d..a1455e6894 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java +++ b/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java @@ -286,7 +286,7 @@ public void sendActionBar(Player player, String text) { player.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacy(text)); } - public enum BaseColor { WHITE, BLACK } + public enum BaseColor { WHITE, BLACK, GRAY } public String parseTextToJson(String formattedText, BaseColor baseColor) { TextComponent textComponent = new TextComponent(formattedText); @@ -295,7 +295,11 @@ public String parseTextToJson(String formattedText, BaseColor baseColor) { textComponent.setStrikethrough(false); textComponent.setUnderlined(false); textComponent.setObfuscated(false); - textComponent.setColor(baseColor == BaseColor.WHITE ? ChatColor.WHITE : ChatColor.BLACK); + textComponent.setColor(switch (baseColor) { + case WHITE -> ChatColor.WHITE; + case BLACK -> ChatColor.BLACK; + case GRAY -> ChatColor.GRAY; + }); TextComponent base = new TextComponent(); base.addExtra(textComponent); return ComponentSerializer.toString(base); diff --git a/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/helpers/EnchantmentHelperImpl.java b/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/helpers/EnchantmentHelperImpl.java index be378e2c3d..9c6c545d45 100644 --- a/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/helpers/EnchantmentHelperImpl.java +++ b/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/helpers/EnchantmentHelperImpl.java @@ -4,8 +4,8 @@ import com.denizenscript.denizen.nms.v1_17.Handler; import com.denizenscript.denizen.scripts.containers.core.EnchantmentScriptContainer; import com.denizenscript.denizen.utilities.FormattedTextHelper; -import com.denizenscript.denizencore.utilities.debugging.Debug; import com.denizenscript.denizencore.utilities.ReflectionHelper; +import com.denizenscript.denizencore.utilities.debugging.Debug; import net.minecraft.core.Registry; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; @@ -92,7 +92,7 @@ public String getDescriptionId() { } @Override public Component getFullname(int level) { - return Handler.componentToNMS(script.script.getFullName(level)); + return Component.Serializer.fromJson(script.script.getFullName(level)); } @Override public boolean canEnchant(net.minecraft.world.item.ItemStack var0) { diff --git a/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/helpers/EnchantmentHelperImpl.java b/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/helpers/EnchantmentHelperImpl.java index 6fa2f7d5f2..78336e7645 100644 --- a/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/helpers/EnchantmentHelperImpl.java +++ b/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/helpers/EnchantmentHelperImpl.java @@ -5,8 +5,8 @@ import com.denizenscript.denizen.nms.v1_18.ReflectionMappingsInfo; import com.denizenscript.denizen.scripts.containers.core.EnchantmentScriptContainer; import com.denizenscript.denizen.utilities.FormattedTextHelper; -import com.denizenscript.denizencore.utilities.debugging.Debug; import com.denizenscript.denizencore.utilities.ReflectionHelper; +import com.denizenscript.denizencore.utilities.debugging.Debug; import net.minecraft.core.MappedRegistry; import net.minecraft.core.Registry; import net.minecraft.network.chat.Component; @@ -96,7 +96,7 @@ public String getDescriptionId() { } @Override public Component getFullname(int level) { - return Handler.componentToNMS(script.script.getFullName(level)); + return Component.Serializer.fromJson(script.script.getFullName(level)); } @Override public boolean canEnchant(net.minecraft.world.item.ItemStack var0) { diff --git a/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/helpers/EnchantmentHelperImpl.java b/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/helpers/EnchantmentHelperImpl.java index 395b31fb0a..4fbdff5cb4 100644 --- a/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/helpers/EnchantmentHelperImpl.java +++ b/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/helpers/EnchantmentHelperImpl.java @@ -6,8 +6,8 @@ import com.denizenscript.denizen.scripts.containers.core.EnchantmentScriptContainer; import com.denizenscript.denizen.utilities.FormattedTextHelper; import com.denizenscript.denizencore.utilities.CoreUtilities; -import com.denizenscript.denizencore.utilities.debugging.Debug; import com.denizenscript.denizencore.utilities.ReflectionHelper; +import com.denizenscript.denizencore.utilities.debugging.Debug; import net.minecraft.core.MappedRegistry; import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; @@ -98,7 +98,7 @@ public String getDescriptionId() { } @Override public Component getFullname(int level) { - return Handler.componentToNMS(script.script.getFullName(level)); + return Component.Serializer.fromJson(script.script.getFullName(level)); } @Override public boolean canEnchant(net.minecraft.world.item.ItemStack var0) { diff --git a/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/helpers/EnchantmentHelperImpl.java b/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/helpers/EnchantmentHelperImpl.java index c8b1400c6a..92adb49cc0 100644 --- a/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/helpers/EnchantmentHelperImpl.java +++ b/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/helpers/EnchantmentHelperImpl.java @@ -22,6 +22,7 @@ import org.bukkit.craftbukkit.v1_20_R4.enchantments.CraftEnchantment; import org.bukkit.craftbukkit.v1_20_R4.entity.CraftEntity; import org.bukkit.craftbukkit.v1_20_R4.inventory.CraftItemStack; +import org.bukkit.craftbukkit.v1_20_R4.util.CraftChatMessage; import org.bukkit.craftbukkit.v1_20_R4.util.CraftNamespacedKey; import org.bukkit.enchantments.Enchantment; import org.bukkit.event.entity.EntityDamageEvent; @@ -106,7 +107,7 @@ public String getDescriptionId() { } @Override public Component getFullname(int level) { - return Handler.componentToNMS(script.script.getFullName(level)); + return CraftChatMessage.fromJSON(script.script.getFullName(level)); } @Override public boolean canEnchant(net.minecraft.world.item.ItemStack var0) { From ff0a829d872860901b212405ee779c4a06486c4d Mon Sep 17 00:00:00 2001 From: Aya <31237389+tal5@users.noreply.github.com> Date: Wed, 10 Sep 2025 14:37:12 +0100 Subject: [PATCH 18/24] `/ex(s)` commands: update --- .../denizen/utilities/command/ExCommandHandler.java | 4 ++-- .../denizen/utilities/command/ExSustainedCommandHandler.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugin/src/main/java/com/denizenscript/denizen/utilities/command/ExCommandHandler.java b/plugin/src/main/java/com/denizenscript/denizen/utilities/command/ExCommandHandler.java index 2714009df1..9dcee43564 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/utilities/command/ExCommandHandler.java +++ b/plugin/src/main/java/com/denizenscript/denizen/utilities/command/ExCommandHandler.java @@ -3,7 +3,7 @@ import com.denizenscript.denizen.objects.NPCTag; import com.denizenscript.denizen.objects.PlayerTag; import com.denizenscript.denizen.tags.BukkitTagContext; -import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizen.utilities.Settings; import com.denizenscript.denizen.utilities.depends.Depends; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; @@ -94,7 +94,7 @@ public boolean onCommand(CommandSender sender, Command cmd, String alias, String List scriptEntries = ScriptBuilder.buildScriptEntries(entries, null, new BukkitScriptEntryData(sender instanceof Player player ? new PlayerTag(player) : null, npc)); queue.addEntries(scriptEntries); if (!quiet && sender instanceof Player) { - queue.debugOutput = s -> sender.spigot().sendMessage(FormattedTextHelper.parse(s.replace("", ""), net.md_5.bungee.api.ChatColor.WHITE)); + queue.debugOutput = s -> PaperAPITools.instance.sendMessage(sender, s.replace("", "")); } queue.start(); return true; diff --git a/plugin/src/main/java/com/denizenscript/denizen/utilities/command/ExSustainedCommandHandler.java b/plugin/src/main/java/com/denizenscript/denizen/utilities/command/ExSustainedCommandHandler.java index bf5bdf8c60..b9aed1c7c6 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/utilities/command/ExSustainedCommandHandler.java +++ b/plugin/src/main/java/com/denizenscript/denizen/utilities/command/ExSustainedCommandHandler.java @@ -3,7 +3,7 @@ import com.denizenscript.denizen.Denizen; import com.denizenscript.denizen.objects.NPCTag; import com.denizenscript.denizen.objects.PlayerTag; -import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizen.utilities.Settings; import com.denizenscript.denizen.utilities.depends.Depends; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; @@ -72,7 +72,7 @@ public boolean onCommand(CommandSender sender, Command cmd, String alias, String } TimedQueue queue = getOrMakeQueue(sender instanceof Player player ? player : null, quiet); if (!quiet && sender instanceof Player) { - queue.debugOutput = s -> sender.spigot().sendMessage(FormattedTextHelper.parse(s.replace("", ""), net.md_5.bungee.api.ChatColor.WHITE)); + queue.debugOutput = s -> PaperAPITools.instance.sendMessage(sender, s.replace("", "")); } else { queue.debugOutput = null; From 68347131c1ed9a7231ee3efebf30625889681a5e Mon Sep 17 00:00:00 2001 From: Aya <31237389+tal5@users.noreply.github.com> Date: Thu, 11 Sep 2025 11:24:58 +0100 Subject: [PATCH 19/24] `PaperAPITools`: update --- .../paper/utilities/HoverFormatHelper.java | 4 +- .../paper/utilities/PaperAPIToolsImpl.java | 62 ++++++++++--------- .../denizen/utilities/PaperAPITools.java | 43 +++++++------ .../debugging/DebugConsoleSender.java | 2 +- 4 files changed, 60 insertions(+), 51 deletions(-) diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/HoverFormatHelper.java b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/HoverFormatHelper.java index 9fae8cd356..7ff3e505c3 100644 --- a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/HoverFormatHelper.java +++ b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/HoverFormatHelper.java @@ -27,14 +27,14 @@ public class HoverFormatHelper { public static boolean processHoverInput(HoverEvent.Action action, TextComponent.Builder hoverableText, String input) { HoverEventSource content; if (action == HoverEvent.Action.SHOW_ITEM) { - ItemTag item = ItemTag.valueOf(com.denizenscript.denizen.utilities.FormattedTextHelper.unescape(input), CoreUtilities.noDebugContext); + ItemTag item = ItemTag.valueOf(FormattedTextHelper.unescape(input), CoreUtilities.noDebugContext); if (item == null) { return true; } content = item.getItemStack(); } else if (action == HoverEvent.Action.SHOW_ENTITY) { - String rawInput = com.denizenscript.denizen.utilities.FormattedTextHelper.unescape(input); + String rawInput = FormattedTextHelper.unescape(input); if (!rawInput.startsWith("map@")) { content = parseLegacyEntityHover(rawInput); if (content == null) { diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java index 8f977f388a..0274c47a20 100644 --- a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java +++ b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java @@ -24,7 +24,8 @@ import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.minimessage.MiniMessage; -import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.api.chat.TextComponent; import org.bukkit.*; import org.bukkit.block.Sign; import org.bukkit.command.CommandSender; @@ -51,12 +52,12 @@ public class PaperAPIToolsImpl extends PaperAPITools { @Override public Inventory createInventory(InventoryHolder holder, int slots, String title) { - return Bukkit.getServer().createInventory(holder, slots, PaperModule.parseFormattedText(title, ChatColor.BLACK)); + return Bukkit.getServer().createInventory(holder, slots, FormattedTextHelper.parse(title, NamedTextColor.BLACK)); } @Override public Inventory createInventory(InventoryHolder holder, InventoryType type, String title) { - return Bukkit.getServer().createInventory(holder, type, PaperModule.parseFormattedText(title, ChatColor.BLACK)); + return Bukkit.getServer().createInventory(holder, type, FormattedTextHelper.parse(title, NamedTextColor.BLACK)); } @Override @@ -64,8 +65,14 @@ public String parseComponent(Object input) { if (input == null) { return null; } - if (input instanceof Component) { - return PaperModule.stringifyComponent((Component) input); + if (input instanceof Component component) { + return FormattedTextHelper.stringify(component); + } + else if (input instanceof BaseComponent[] components) { + return FormattedTextHelper.stringify(PaperModule.jsonToComponent(bungeeToJson(components.length == 1 ? components[0] : new TextComponent(components)))); + } + else if (input instanceof BaseComponent component) { + return FormattedTextHelper.stringify(PaperModule.jsonToComponent(bungeeToJson(component))); } return super.parseComponent(input); } @@ -78,22 +85,22 @@ public String getTitle(Inventory inventory) { @Override public void setCustomName(Entity entity, String name) { - entity.customName(PaperModule.parseFormattedText(name, ChatColor.WHITE)); + entity.customName(FormattedTextHelper.parse(name, NamedTextColor.WHITE)); } @Override public String getCustomName(Entity entity) { - return PaperModule.stringifyComponent(entity.customName()); + return FormattedTextHelper.stringify(entity.customName()); } @Override public void setPlayerListName(Player player, String name) { - player.playerListName(PaperModule.parseFormattedText(name, ChatColor.WHITE)); + player.playerListName(FormattedTextHelper.parse(name, NamedTextColor.WHITE)); } @Override public String getPlayerListName(Player player) { - return PaperModule.stringifyComponent(player.playerListName()); + return FormattedTextHelper.stringify(player.playerListName()); } @Override @@ -101,14 +108,14 @@ public String[] getSignLines(Sign sign) { String[] output = new String[4]; int i = 0; for (Component component : sign.lines()) { - output[i++] = PaperModule.stringifyComponent(component); + output[i++] = FormattedTextHelper.stringify(component); } return output; } @Override public void setSignLine(Sign sign, int line, String text) { - sign.line(line, PaperModule.parseFormattedText(text == null ? "" : text, ChatColor.BLACK)); + sign.line(line, FormattedTextHelper.parse(text == null ? "" : text, NamedTextColor.BLACK)); } @Override @@ -117,7 +124,7 @@ public void sendResourcePack(Player player, String url, String hash, boolean for super.sendResourcePack(player, url, hash, false, null); } else { - player.setResourcePack(url, CoreUtilities.toLowerCase(hash), forced, PaperModule.parseFormattedText(prompt, ChatColor.WHITE)); + player.setResourcePack(url, CoreUtilities.toLowerCase(hash), forced, FormattedTextHelper.parse(prompt, NamedTextColor.WHITE)); } } @@ -125,24 +132,19 @@ public void sendResourcePack(Player player, String url, String hash, boolean for public void sendSignUpdate(Player player, Location loc, String[] text) { List components = new ArrayList<>(); for (String line : text) { - components.add(PaperModule.parseFormattedText(line, ChatColor.BLACK)); + components.add(FormattedTextHelper.parse(line, NamedTextColor.BLACK)); } player.sendSignChange(loc, components); } @Override public String getCustomName(Nameable object) { - return PaperModule.stringifyComponent(object.customName()); + return FormattedTextHelper.stringify(object.customName()); } @Override public void setCustomName(Nameable object, String name) { - object.customName(PaperModule.parseFormattedText(name, ChatColor.BLACK)); - } - - @Override - public void sendConsoleMessage(CommandSender sender, String text) { - sender.sendMessage(PaperModule.parseFormattedText(text, ChatColor.WHITE)); + object.customName(FormattedTextHelper.parse(name, NamedTextColor.BLACK)); } @Override @@ -245,12 +247,12 @@ public RecipeChoice createPredicateRecipeChoice(Predicate predicate) @Override public String getDeathMessage(PlayerDeathEvent event) { - return PaperModule.stringifyComponent(event.deathMessage()); + return FormattedTextHelper.stringify(event.deathMessage()); } @Override public void setDeathMessage(PlayerDeathEvent event, String message) { - event.deathMessage(PaperModule.parseFormattedText(message, ChatColor.WHITE)); + event.deathMessage(FormattedTextHelper.parse(message, NamedTextColor.WHITE)); } public Set modifiedTextures = new HashSet<>(); @@ -333,22 +335,22 @@ public T spawnEntity(Location location, Class type, Consum @Override public void setTeamPrefix(Team team, String prefix) { - team.prefix(PaperModule.parseFormattedText(prefix, ChatColor.WHITE)); + team.prefix(FormattedTextHelper.parse(prefix, NamedTextColor.WHITE)); } @Override public void setTeamSuffix(Team team, String suffix) { - team.suffix(PaperModule.parseFormattedText(suffix, ChatColor.WHITE)); + team.suffix(FormattedTextHelper.parse(suffix, NamedTextColor.WHITE)); } @Override public String getTeamPrefix(Team team) { - return PaperModule.stringifyComponent(team.prefix()); + return FormattedTextHelper.stringify(team.prefix()); } @Override public String getTeamSuffix(Team team) { - return PaperModule.stringifyComponent(team.suffix()); + return FormattedTextHelper.stringify(team.suffix()); } @Override @@ -362,22 +364,22 @@ public String convertTextToMiniMessage(String text, boolean splitNewlines) { @Override public Merchant createMerchant(String title) { - return Bukkit.createMerchant(PaperModule.parseFormattedText(title, ChatColor.BLACK)); + return Bukkit.createMerchant(FormattedTextHelper.parse(title, NamedTextColor.BLACK)); } @Override public String getText(TextDisplay textDisplay) { - return PaperModule.stringifyComponent(textDisplay.text()); + return FormattedTextHelper.stringify(textDisplay.text()); } @Override public void setText(TextDisplay textDisplay, String text) { - textDisplay.text(PaperModule.parseFormattedText(text, ChatColor.WHITE)); + textDisplay.text(FormattedTextHelper.parse(text, NamedTextColor.WHITE)); } @Override public void kickPlayer(Player player, String message) { - player.kick(PaperModule.parseFormattedText(message, ChatColor.WHITE)); + player.kick(FormattedTextHelper.parse(message, NamedTextColor.WHITE)); } @Override diff --git a/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java b/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java index a1455e6894..d2ad2e03bf 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java +++ b/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java @@ -12,7 +12,9 @@ import net.md_5.bungee.api.ChatMessageType; import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.chat.TextComponent; +import net.md_5.bungee.chat.ChatVersion; import net.md_5.bungee.chat.ComponentSerializer; +import net.md_5.bungee.chat.VersionedComponentSerializer; import org.bukkit.*; import org.bukkit.block.Sign; import org.bukkit.command.CommandSender; @@ -53,14 +55,14 @@ public String parseComponent(Object input) { if (input == null) { return null; } - if (input instanceof String) { - return (String) input; + if (input instanceof String str) { + return str; } - else if (input instanceof BaseComponent[]) { - return FormattedTextHelper.stringify((BaseComponent[]) input); + else if (input instanceof BaseComponent[] components) { + return components.length == 1 ? components[0].toLegacyText() : new TextComponent(components).toLegacyText(); } - else if (input instanceof BaseComponent) { - return FormattedTextHelper.stringify((BaseComponent) input); + else if (input instanceof BaseComponent component) { + return component.toLegacyText(); } else { return input.toString(); @@ -79,11 +81,6 @@ public String getCustomName(Entity entity) { return entity.getCustomName(); } - public BaseComponent[] getCustomNameComponent(Entity entity) { - String customName = entity.getCustomName(); - return customName != null ? FormattedTextHelper.parseSimpleColorsOnly(customName) : null; - } - public void setPlayerListName(Player player, String name) { player.setPlayerListName(name); } @@ -120,10 +117,6 @@ public void setCustomName(Nameable object, String name) { object.setCustomName(name); } - public void sendConsoleMessage(CommandSender sender, String text) { - sender.spigot().sendMessage(FormattedTextHelper.parse(text, net.md_5.bungee.api.ChatColor.WHITE)); - } - public InventoryView openAnvil(Player player, Location loc) { throw new UnsupportedOperationException(); } @@ -261,7 +254,7 @@ public void setPages(BookMeta meta, List pages) { public void setJsonPages(BookMeta meta, List jsonPages) { List parsedPages = new ArrayList<>(jsonPages.size()); for (String jsonPage : jsonPages) { - parsedPages.add(ComponentSerializer.parse(jsonPage)); + parsedPages.add(jsonToBungee(jsonPage)); } meta.spigot().setPages(parsedPages); } @@ -302,11 +295,25 @@ public String parseTextToJson(String formattedText, BaseColor baseColor) { }); TextComponent base = new TextComponent(); base.addExtra(textComponent); - return ComponentSerializer.toString(base); + return bungeeToJson(base); } public String parseJsonToText(String json) { - BaseComponent[] components = ComponentSerializer.parse(json); + BaseComponent[] components = jsonToBungee(json); return components.length == 1 ? components[0].toLegacyText() : new TextComponent(components).toLegacyText(); } + + protected String bungeeToJson(BaseComponent component) { + if (NMSHandler.getVersion().isAtMost(NMSVersion.v1_20)) { + return ComponentSerializer.toString(component); + } + return VersionedComponentSerializer.forVersion(ChatVersion.V1_21_5).toString(component); + } + + protected BaseComponent[] jsonToBungee(String json) { + if (NMSHandler.getVersion().isAtMost(NMSVersion.v1_20)) { + return ComponentSerializer.parse(json); + } + return VersionedComponentSerializer.forVersion(ChatVersion.V1_21_5).parse(json); + } } diff --git a/plugin/src/main/java/com/denizenscript/denizen/utilities/debugging/DebugConsoleSender.java b/plugin/src/main/java/com/denizenscript/denizen/utilities/debugging/DebugConsoleSender.java index 236119899f..b36d238a48 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/utilities/debugging/DebugConsoleSender.java +++ b/plugin/src/main/java/com/denizenscript/denizen/utilities/debugging/DebugConsoleSender.java @@ -19,7 +19,7 @@ public static void sendMessage(String string) { // "[HH:mm:ss INFO]: " string = CoreConfiguration.debugPrefix + string.replace("", " "); if (showColor) { - PaperAPITools.instance.sendConsoleMessage(commandSender, string); + PaperAPITools.instance.sendMessage(commandSender, string); } else { commandSender.sendMessage(ChatColor.stripColor(string)); From dba5685451450d6723fc7d6c7b3af63d4eb1b56a Mon Sep 17 00:00:00 2001 From: Aya <31237389+tal5@users.noreply.github.com> Date: Thu, 11 Sep 2025 11:45:45 +0100 Subject: [PATCH 20/24] `PaperModule`: cleanup parsing methods --- .../denizen/paper/PaperModule.java | 22 ------------------- ...pletesAdvancementScriptEventPaperImpl.java | 10 ++++----- .../events/PlayerNameEntityScriptEvent.java | 8 +++---- .../PlayerQuitsScriptEventPaperImpl.java | 8 +++---- .../events/PlayerSetSpawnScriptEvent.java | 8 +++---- .../ServerListPingScriptEventPaperImpl.java | 8 +++---- .../events/UnknownCommandScriptEvent.java | 8 +++---- .../properties/PaperElementExtensions.java | 2 +- 8 files changed, 26 insertions(+), 48 deletions(-) diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/PaperModule.java b/paper/src/main/java/com/denizenscript/denizen/paper/PaperModule.java index fa4da24c82..1f96ee702a 100644 --- a/paper/src/main/java/com/denizenscript/denizen/paper/PaperModule.java +++ b/paper/src/main/java/com/denizenscript/denizen/paper/PaperModule.java @@ -11,14 +11,12 @@ import com.denizenscript.denizen.paper.tags.PaperTagBase; import com.denizenscript.denizen.paper.tags.TextFormattingTags; import com.denizenscript.denizen.paper.utilities.PaperAPIToolsImpl; -import com.denizenscript.denizen.utilities.FormattedTextHelper; import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizencore.events.ScriptEvent; import com.denizenscript.denizencore.objects.properties.PropertyParser; import com.denizenscript.denizencore.utilities.debugging.Debug; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; -import net.md_5.bungee.api.ChatColor; import org.bukkit.Bukkit; public class PaperModule { @@ -144,26 +142,6 @@ public static void init() { PacketOutChat.convertComponentToJsonString = (o) -> componentToJson((Component) o); } - public static Component parseFormattedText(String text, ChatColor baseColor) { - if (text == null) { - return null; - } - try { - return jsonToComponent(FormattedTextHelper.componentToJson(FormattedTextHelper.parse(text, baseColor))); - } - catch (Exception ex) { - Debug.verboseLog("Failed to parse formatted text: " + text.replace(ChatColor.COLOR_CHAR, '&')); - throw ex; - } - } - - public static String stringifyComponent(Component component) { - if (component == null) { - return null; - } - return FormattedTextHelper.stringify(FormattedTextHelper.parseJson(componentToJson(component))); - } - public static Component jsonToComponent(String json) { if (json == null) { return null; diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerCompletesAdvancementScriptEventPaperImpl.java b/paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerCompletesAdvancementScriptEventPaperImpl.java index 58d0daf4d3..f341f1f171 100644 --- a/paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerCompletesAdvancementScriptEventPaperImpl.java +++ b/paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerCompletesAdvancementScriptEventPaperImpl.java @@ -1,18 +1,18 @@ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.player.PlayerCompletesAdvancementScriptEvent; -import com.denizenscript.denizen.paper.PaperModule; -import com.denizenscript.denizencore.objects.core.ElementTag; +import com.denizenscript.denizen.paper.utilities.FormattedTextHelper; import com.denizenscript.denizencore.objects.ObjectTag; +import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.utilities.CoreUtilities; -import net.md_5.bungee.api.ChatColor; +import net.kyori.adventure.text.format.NamedTextColor; public class PlayerCompletesAdvancementScriptEventPaperImpl extends PlayerCompletesAdvancementScriptEvent { @Override public ObjectTag getContext(String name) { switch (name) { - case "message": return new ElementTag(PaperModule.stringifyComponent(event.message())); + case "message": return new ElementTag(FormattedTextHelper.stringify(event.message()), true); } return super.getContext(name); } @@ -26,7 +26,7 @@ public boolean applyDetermination(ScriptPath path, ObjectTag determinationObj) { event.message(null); return true; } - event.message(PaperModule.parseFormattedText(determination, ChatColor.WHITE)); + event.message(FormattedTextHelper.parse(determination, NamedTextColor.WHITE)); return true; } else { diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerNameEntityScriptEvent.java b/paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerNameEntityScriptEvent.java index 41d421bd78..83a93394a5 100644 --- a/paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerNameEntityScriptEvent.java +++ b/paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerNameEntityScriptEvent.java @@ -2,14 +2,14 @@ import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.EntityTag; -import com.denizenscript.denizen.paper.PaperModule; +import com.denizenscript.denizen.paper.utilities.FormattedTextHelper; import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import io.papermc.paper.event.player.PlayerNameEntityEvent; -import net.md_5.bungee.api.ChatColor; +import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; @@ -53,7 +53,7 @@ public PlayerNameEntityScriptEvent() { return false; }); this.registerDetermination("name", ElementTag.class, (evt, context, determination) -> { - evt.event.setName(PaperModule.parseFormattedText(determination.toString(), ChatColor.WHITE)); + evt.event.setName(FormattedTextHelper.parse(determination.asString(), NamedTextColor.WHITE)); }); } @@ -81,7 +81,7 @@ public ScriptEntryData getScriptEntryData() { public ObjectTag getContext(String name) { return switch (name) { case "entity" -> entity.getDenizenObject(); - case "name" -> new ElementTag(PaperModule.stringifyComponent(event.getName()), true); + case "name" -> new ElementTag(FormattedTextHelper.stringify(event.getName()), true); case "old_name" -> oldName; case "persistent" -> new ElementTag(event.isPersistent()); default -> super.getContext(name); diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerQuitsScriptEventPaperImpl.java b/paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerQuitsScriptEventPaperImpl.java index a899af3781..224e93ed28 100644 --- a/paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerQuitsScriptEventPaperImpl.java +++ b/paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerQuitsScriptEventPaperImpl.java @@ -1,10 +1,10 @@ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.player.PlayerQuitsScriptEvent; -import com.denizenscript.denizen.paper.PaperModule; +import com.denizenscript.denizen.paper.utilities.FormattedTextHelper; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; -import net.md_5.bungee.api.ChatColor; +import net.kyori.adventure.text.format.NamedTextColor; public class PlayerQuitsScriptEventPaperImpl extends PlayerQuitsScriptEvent { @@ -15,7 +15,7 @@ public PlayerQuitsScriptEventPaperImpl() { event.quitMessage(null); }); this.registerDetermination(null, ElementTag.class, (evt, context, determination) -> { - event.quitMessage(PaperModule.parseFormattedText(determination.toString(), ChatColor.WHITE)); + event.quitMessage(FormattedTextHelper.parse(determination.asString(), NamedTextColor.WHITE)); }); } @@ -30,7 +30,7 @@ public boolean matches(ScriptPath path) { @Override public ObjectTag getContext(String name) { return switch (name) { - case "message" -> new ElementTag(PaperModule.stringifyComponent(event.quitMessage())); + case "message" -> new ElementTag(FormattedTextHelper.stringify(event.quitMessage()), true); case "cause" -> new ElementTag(event.getReason()); default -> super.getContext(name); }; diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerSetSpawnScriptEvent.java b/paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerSetSpawnScriptEvent.java index 7f68012369..54f73a07a9 100644 --- a/paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerSetSpawnScriptEvent.java +++ b/paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerSetSpawnScriptEvent.java @@ -2,13 +2,13 @@ import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.LocationTag; -import com.denizenscript.denizen.paper.PaperModule; +import com.denizenscript.denizen.paper.utilities.FormattedTextHelper; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import com.destroystokyo.paper.event.player.PlayerSetSpawnEvent; -import net.md_5.bungee.api.ChatColor; +import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; @@ -58,7 +58,7 @@ public PlayerSetSpawnScriptEvent() { return false; }); this.registerDetermination("message", ElementTag.class, (evt, context, message) -> { - evt.event.setNotification(PaperModule.parseFormattedText(message.toString(), ChatColor.WHITE)); + evt.event.setNotification(FormattedTextHelper.parse(message.asString(), NamedTextColor.WHITE)); }); this.registerOptionalDetermination("notify", ElementTag.class, (evt, context, value) -> { if (value.isBoolean()) { @@ -97,7 +97,7 @@ public ObjectTag getContext(String name) { case "cause" -> new ElementTag(event.getCause()); case "forced" -> new ElementTag(event.isForced()); case "location" -> event.getLocation() != null ? new LocationTag(event.getLocation()) : null; - case "message" -> event.getNotification() != null ? new ElementTag(PaperModule.stringifyComponent(event.getNotification()), true) : null; + case "message" -> event.getNotification() != null ? new ElementTag(FormattedTextHelper.stringify(event.getNotification()), true) : null; case "notify" -> new ElementTag(event.willNotifyPlayer()); default -> super.getContext(name); }; diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/events/ServerListPingScriptEventPaperImpl.java b/paper/src/main/java/com/denizenscript/denizen/paper/events/ServerListPingScriptEventPaperImpl.java index 6ea097a13d..84a2f17f30 100644 --- a/paper/src/main/java/com/denizenscript/denizen/paper/events/ServerListPingScriptEventPaperImpl.java +++ b/paper/src/main/java/com/denizenscript/denizen/paper/events/ServerListPingScriptEventPaperImpl.java @@ -5,7 +5,7 @@ import com.denizenscript.denizen.nms.NMSVersion; import com.denizenscript.denizen.nms.abstracts.ProfileEditor; import com.denizenscript.denizen.objects.PlayerTag; -import com.denizenscript.denizen.paper.PaperModule; +import com.denizenscript.denizen.paper.utilities.FormattedTextHelper; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.objects.core.ListTag; @@ -14,7 +14,7 @@ import com.destroystokyo.paper.event.server.PaperServerListPingEvent; import com.destroystokyo.paper.profile.PlayerProfile; import com.destroystokyo.paper.profile.ProfileProperty; -import net.md_5.bungee.api.ChatColor; +import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.profile.PlayerTextures; @@ -124,13 +124,13 @@ public static class FakeProfile implements PlayerProfile { @Override public void setMotd(String text) { - event.motd(PaperModule.parseFormattedText(text, ChatColor.WHITE)); + event.motd(FormattedTextHelper.parse(text, NamedTextColor.WHITE)); } @Override public ObjectTag getContext(String name) { return switch (name) { - case "motd" -> new ElementTag(PaperModule.stringifyComponent(event.motd()), true); + case "motd" -> new ElementTag(FormattedTextHelper.stringify(event.motd()), true); case "protocol_version" -> new ElementTag(getEvent().getProtocolVersion()); case "version_name" -> new ElementTag(getEvent().getVersion(), true); case "client_protocol_version" -> new ElementTag(getEvent().getClient().getProtocolVersion()); diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/events/UnknownCommandScriptEvent.java b/paper/src/main/java/com/denizenscript/denizen/paper/events/UnknownCommandScriptEvent.java index c800cf62e0..09d8c2c2fb 100644 --- a/paper/src/main/java/com/denizenscript/denizen/paper/events/UnknownCommandScriptEvent.java +++ b/paper/src/main/java/com/denizenscript/denizen/paper/events/UnknownCommandScriptEvent.java @@ -4,14 +4,14 @@ import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.objects.LocationTag; import com.denizenscript.denizen.objects.PlayerTag; -import com.denizenscript.denizen.paper.PaperModule; +import com.denizenscript.denizen.paper.utilities.FormattedTextHelper; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.objects.ArgumentHelper; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.objects.core.ListTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; -import net.md_5.bungee.api.ChatColor; +import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.command.BlockCommandSender; import org.bukkit.entity.Player; import org.bukkit.entity.minecart.CommandMinecart; @@ -55,7 +55,7 @@ public class UnknownCommandScriptEvent extends BukkitScriptEvent implements List public UnknownCommandScriptEvent() { registerCouldMatcher("command unknown"); this.registerDetermination(null, ElementTag.class, (evt, context, text) -> { - evt.event.message(PaperModule.parseFormattedText(text.toString(), ChatColor.WHITE)); + evt.event.message(FormattedTextHelper.parse(text.asString(), NamedTextColor.WHITE)); }); this.registerTextDetermination("none", (evt) -> { evt.event.message(null); @@ -82,7 +82,7 @@ public ObjectTag getContext(String name) { case "source_type" -> new ElementTag(sourceType, true); case "command_block_location" -> sourceType.equals("command_block") ? new LocationTag(((BlockCommandSender) event.getSender()).getBlock().getLocation()) : null; case "command_minecart" -> sourceType.equals("command_minecart") ? new EntityTag((CommandMinecart) event.getSender()) : null; - case "message" -> new ElementTag(PaperModule.stringifyComponent(event.message()), true); + case "message" -> new ElementTag(FormattedTextHelper.stringify(event.message()), true); default -> super.getContext(name); }; } diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/properties/PaperElementExtensions.java b/paper/src/main/java/com/denizenscript/denizen/paper/properties/PaperElementExtensions.java index 7ed2426398..95603e891a 100644 --- a/paper/src/main/java/com/denizenscript/denizen/paper/properties/PaperElementExtensions.java +++ b/paper/src/main/java/com/denizenscript/denizen/paper/properties/PaperElementExtensions.java @@ -577,7 +577,7 @@ else if (colorName.startsWith("co@")) { // This may be useful for reading data from external plugins, but should not be used in normal scripts. // --> ElementTag.tagProcessor.registerTag(ElementTag.class, "parse_minimessage", (attribute, object) -> { - return new ElementTag(PaperModule.stringifyComponent(MiniMessage.miniMessage().deserialize(object.asString()))); + return new ElementTag(FormattedTextHelper.stringify(MiniMessage.miniMessage().deserialize(object.asString()))); }); // <--[tag] From 0805f32a07b402bd78e214aafdbbdd6f582ffc3d Mon Sep 17 00:00:00 2001 From: Aya <31237389+tal5@users.noreply.github.com> Date: Thu, 11 Sep 2025 14:15:36 +0100 Subject: [PATCH 21/24] NMS modules: transition to `PaperAPITools` methods --- .../paper/utilities/PaperAPIToolsImpl.java | 1 + .../denizen/utilities/PaperAPITools.java | 3 +- .../denizen/nms/v1_17/Handler.java | 19 +++++----- .../v1_17/helpers/AdvancementHelperImpl.java | 7 ++-- .../v1_17/helpers/EnchantmentHelperImpl.java | 3 +- .../nms/v1_17/helpers/ItemHelperImpl.java | 16 +++------ .../nms/v1_17/helpers/PacketHelperImpl.java | 13 ++++--- .../nms/v1_17/helpers/PlayerHelperImpl.java | 5 ++- .../nms/v1_17/impl/ProfileEditorImpl.java | 15 ++++---- .../denizen/nms/v1_17/impl/SidebarImpl.java | 11 +++--- .../handlers/DenizenNetworkManagerImpl.java | 4 +-- .../denizen/nms/v1_18/Handler.java | 18 ++++------ .../v1_18/helpers/AdvancementHelperImpl.java | 7 ++-- .../v1_18/helpers/EnchantmentHelperImpl.java | 3 +- .../nms/v1_18/helpers/ItemHelperImpl.java | 16 +++------ .../nms/v1_18/helpers/PacketHelperImpl.java | 13 ++++--- .../nms/v1_18/helpers/PlayerHelperImpl.java | 7 ++-- .../nms/v1_18/impl/ProfileEditorImpl.java | 15 ++++---- .../denizen/nms/v1_18/impl/SidebarImpl.java | 11 +++--- .../handlers/DenizenNetworkManagerImpl.java | 8 ++--- .../denizen/nms/v1_19/Handler.java | 18 ++++------ .../v1_19/helpers/AdvancementHelperImpl.java | 7 ++-- .../v1_19/helpers/EnchantmentHelperImpl.java | 3 +- .../nms/v1_19/helpers/ItemHelperImpl.java | 16 +++------ .../nms/v1_19/helpers/PacketHelperImpl.java | 13 ++++--- .../nms/v1_19/helpers/PlayerHelperImpl.java | 7 ++-- .../nms/v1_19/impl/ProfileEditorImpl.java | 5 ++- .../denizen/nms/v1_19/impl/SidebarImpl.java | 11 +++--- .../handlers/DenizenNetworkManagerImpl.java | 8 ++--- .../denizen/nms/v1_20/Handler.java | 28 +++++++-------- .../v1_20/helpers/AdvancementHelperImpl.java | 5 ++- .../v1_20/helpers/EnchantmentHelperImpl.java | 3 +- .../nms/v1_20/helpers/ItemHelperImpl.java | 10 +++--- .../nms/v1_20/helpers/PacketHelperImpl.java | 13 ++++--- .../nms/v1_20/helpers/PlayerHelperImpl.java | 7 ++-- .../nms/v1_20/impl/ProfileEditorImpl.java | 5 ++- .../denizen/nms/v1_20/impl/SidebarImpl.java | 9 +++-- .../packet/EntityMetadataPacketHandlers.java | 5 ++- .../TablistUpdateEventPacketHandlers.java | 7 ++-- .../denizen/nms/v1_21/Handler.java | 35 +++++++++---------- .../v1_21/helpers/AdvancementHelperImpl.java | 5 ++- .../nms/v1_21/helpers/ItemHelperImpl.java | 10 +++--- .../nms/v1_21/helpers/PacketHelperImpl.java | 13 ++++--- .../nms/v1_21/helpers/PlayerHelperImpl.java | 8 ++--- .../nms/v1_21/impl/ProfileEditorImpl.java | 5 ++- .../denizen/nms/v1_21/impl/SidebarImpl.java | 9 +++-- .../packet/EntityMetadataPacketHandlers.java | 5 ++- .../TablistUpdateEventPacketHandlers.java | 7 ++-- 48 files changed, 198 insertions(+), 274 deletions(-) diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java index 0274c47a20..ffb1c9374d 100644 --- a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java +++ b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java @@ -474,6 +474,7 @@ public String parseTextToJson(String formattedText, BaseColor baseColor) { case WHITE -> NamedTextColor.WHITE; case BLACK -> NamedTextColor.BLACK; case GRAY -> NamedTextColor.GRAY; + case DARK_GRAY -> NamedTextColor.DARK_GRAY; })); } diff --git a/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java b/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java index d2ad2e03bf..13206b05f7 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java +++ b/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java @@ -279,7 +279,7 @@ public void sendActionBar(Player player, String text) { player.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacy(text)); } - public enum BaseColor { WHITE, BLACK, GRAY } + public enum BaseColor { WHITE, BLACK, GRAY, DARK_GRAY } public String parseTextToJson(String formattedText, BaseColor baseColor) { TextComponent textComponent = new TextComponent(formattedText); @@ -292,6 +292,7 @@ public String parseTextToJson(String formattedText, BaseColor baseColor) { case WHITE -> ChatColor.WHITE; case BLACK -> ChatColor.BLACK; case GRAY -> ChatColor.GRAY; + case DARK_GRAY -> ChatColor.DARK_GRAY; }); TextComponent base = new TextComponent(); base.addExtra(textComponent); diff --git a/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/Handler.java b/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/Handler.java index de970ac638..e2df45a86c 100644 --- a/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/Handler.java +++ b/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/Handler.java @@ -11,6 +11,7 @@ import com.denizenscript.denizen.nms.v1_17.impl.ProfileEditorImpl; import com.denizenscript.denizen.nms.v1_17.impl.SidebarImpl; import com.denizenscript.denizen.nms.v1_17.impl.blocks.BlockLightImpl; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizencore.utilities.CoreConfiguration; import com.denizenscript.denizencore.utilities.CoreUtilities; import com.denizenscript.denizencore.utilities.ReflectionHelper; @@ -18,8 +19,6 @@ import com.google.common.collect.Iterables; import com.mojang.authlib.GameProfile; import com.mojang.authlib.properties.Property; -import net.md_5.bungee.api.chat.BaseComponent; -import net.md_5.bungee.chat.ComponentSerializer; import net.minecraft.core.Registry; import net.minecraft.nbt.ByteArrayTag; import net.minecraft.nbt.StringTag; @@ -271,13 +270,17 @@ else if (base instanceof ByteArrayTag) { return null; } - public static BaseComponent[] componentToSpigot(Component nms) { - String json = Component.Serializer.toJson(nms); - return ComponentSerializer.parse(json); + public static String stringifyNMSComponent(Component nms) { + if (nms == null) { + return null; + } + return PaperAPITools.instance.parseJsonToText(Component.Serializer.toJson(nms)); } - public static MutableComponent componentToNMS(BaseComponent[] spigot) { - String json = ComponentSerializer.toString(spigot); - return Component.Serializer.fromJson(json); + public static MutableComponent parseNMSComponent(String formattedText, PaperAPITools.BaseColor baseColor) { + if (formattedText == null) { + return null; + } + return Component.Serializer.fromJson(PaperAPITools.instance.parseTextToJson(formattedText, baseColor)); } } diff --git a/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/helpers/AdvancementHelperImpl.java b/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/helpers/AdvancementHelperImpl.java index b717f9db6c..bd3a7fe51b 100644 --- a/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/helpers/AdvancementHelperImpl.java +++ b/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/helpers/AdvancementHelperImpl.java @@ -1,11 +1,10 @@ package com.denizenscript.denizen.nms.v1_17.helpers; import com.denizenscript.denizen.nms.interfaces.AdvancementHelper; +import com.denizenscript.denizen.nms.v1_17.Handler; import com.denizenscript.denizen.nms.v1_17.ReflectionMappingsInfo; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizencore.utilities.ReflectionHelper; -import com.denizenscript.denizen.nms.v1_17.Handler; -import com.denizenscript.denizen.utilities.FormattedTextHelper; -import net.md_5.bungee.api.ChatColor; import net.minecraft.advancements.*; import net.minecraft.advancements.critereon.ImpossibleTrigger; import net.minecraft.network.protocol.game.ClientboundUpdateAdvancementsPacket; @@ -178,7 +177,7 @@ private static Advancement asNMSCopy(com.denizenscript.denizen.nms.util.Advancem ? getAdvancementDataWorld().advancements.advancements.get(asResourceLocation(advancement.parent)) : null; DisplayInfo display = new DisplayInfo(CraftItemStack.asNMSCopy(advancement.icon), - Handler.componentToNMS(FormattedTextHelper.parse(advancement.title, ChatColor.WHITE)), Handler.componentToNMS(FormattedTextHelper.parse(advancement.description, ChatColor.WHITE)), + Handler.parseNMSComponent(advancement.title, PaperAPITools.BaseColor.WHITE), Handler.parseNMSComponent(advancement.description, PaperAPITools.BaseColor.WHITE), asResourceLocation(advancement.background), FrameType.valueOf(advancement.frame.name()), advancement.toast, advancement.announceToChat, advancement.hidden); display.setLocation(advancement.xOffset, advancement.yOffset); diff --git a/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/helpers/EnchantmentHelperImpl.java b/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/helpers/EnchantmentHelperImpl.java index 9c6c545d45..76edb98920 100644 --- a/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/helpers/EnchantmentHelperImpl.java +++ b/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/helpers/EnchantmentHelperImpl.java @@ -3,7 +3,6 @@ import com.denizenscript.denizen.nms.interfaces.EnchantmentHelper; import com.denizenscript.denizen.nms.v1_17.Handler; import com.denizenscript.denizen.scripts.containers.core.EnchantmentScriptContainer; -import com.denizenscript.denizen.utilities.FormattedTextHelper; import com.denizenscript.denizencore.utilities.ReflectionHelper; import com.denizenscript.denizencore.utilities.debugging.Debug; import net.minecraft.core.Registry; @@ -174,7 +173,7 @@ public int getMaxCost(Enchantment enchantment, int level) { @Override public String getFullName(Enchantment enchantment, int level) { - return FormattedTextHelper.stringify(Handler.componentToSpigot(((CraftEnchantment) enchantment).getHandle().getFullname(level))); + return Handler.stringifyNMSComponent(((CraftEnchantment) enchantment).getHandle().getFullname(level)); } @Override diff --git a/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/helpers/ItemHelperImpl.java b/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/helpers/ItemHelperImpl.java index b5aa9388e6..8fd5ea1590 100644 --- a/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/helpers/ItemHelperImpl.java +++ b/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/helpers/ItemHelperImpl.java @@ -4,7 +4,7 @@ import com.denizenscript.denizen.nms.util.PlayerProfile; import com.denizenscript.denizen.nms.v1_17.ReflectionMappingsInfo; import com.denizenscript.denizen.objects.ItemTag; -import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizencore.utilities.ReflectionHelper; import com.denizenscript.denizencore.utilities.debugging.Debug; import com.google.common.collect.Iterables; @@ -15,9 +15,6 @@ import com.mojang.authlib.properties.Property; import net.kyori.adventure.nbt.BinaryTag; import net.kyori.adventure.nbt.CompoundBinaryTag; -import net.md_5.bungee.api.ChatColor; -import net.md_5.bungee.api.chat.BaseComponent; -import net.md_5.bungee.chat.ComponentSerializer; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.NonNullList; @@ -250,8 +247,7 @@ public String getDisplayName(ItemTag item) { } net.minecraft.world.item.ItemStack nmsItemStack = CraftItemStack.asNMSCopy(item.getItemStack()); String jsonText = ((net.minecraft.nbt.CompoundTag) nmsItemStack.getTag().get("display")).getString("Name"); - BaseComponent[] nameComponent = ComponentSerializer.parse(jsonText); - return FormattedTextHelper.stringify(nameComponent); + return PaperAPITools.instance.parseJsonToText(jsonText); } @Override @@ -263,8 +259,7 @@ public List getLore(ItemTag item) { ListTag list = ((net.minecraft.nbt.CompoundTag) nmsItemStack.getTag().get("display")).getList("Lore", 8); List outList = new ArrayList<>(); for (int i = 0; i < list.size(); i++) { - BaseComponent[] lineComponent = ComponentSerializer.parse(list.getString(i)); - outList.add(FormattedTextHelper.stringify(lineComponent)); + outList.add(PaperAPITools.instance.parseJsonToText(list.getString(i))); } return outList; } @@ -281,8 +276,7 @@ public void setDisplayName(ItemTag item, String name) { display.put("Name", null); return; } - BaseComponent[] components = FormattedTextHelper.parse(name, ChatColor.WHITE); - display.put("Name", net.minecraft.nbt.StringTag.valueOf(ComponentSerializer.toString(components))); + display.put("Name", net.minecraft.nbt.StringTag.valueOf(PaperAPITools.instance.parseTextToJson(name, PaperAPITools.BaseColor.WHITE))); item.setItemStack(CraftItemStack.asBukkitCopy(nmsItemStack)); } @@ -300,7 +294,7 @@ public void setLore(ItemTag item, List lore) { else { ListTag tagList = new ListTag(); for (String line : lore) { - tagList.add(net.minecraft.nbt.StringTag.valueOf(ComponentSerializer.toString(FormattedTextHelper.parse(line, ChatColor.WHITE)))); + tagList.add(net.minecraft.nbt.StringTag.valueOf(PaperAPITools.instance.parseTextToJson(line, PaperAPITools.BaseColor.WHITE))); } display.put("Lore", tagList); } diff --git a/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/helpers/PacketHelperImpl.java b/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/helpers/PacketHelperImpl.java index d4e4143485..7b71d68a56 100644 --- a/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/helpers/PacketHelperImpl.java +++ b/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/helpers/PacketHelperImpl.java @@ -9,7 +9,7 @@ import com.denizenscript.denizen.objects.LocationTag; import com.denizenscript.denizen.objects.MaterialTag; import com.denizenscript.denizen.objects.PlayerTag; -import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizen.utilities.Utilities; import com.denizenscript.denizen.utilities.blocks.FakeBlock; import com.denizenscript.denizen.utilities.maps.MapImage; @@ -22,7 +22,6 @@ import net.kyori.adventure.nbt.BinaryTagTypes; import net.kyori.adventure.nbt.CompoundBinaryTag; import net.kyori.adventure.nbt.ListBinaryTag; -import net.md_5.bungee.api.ChatColor; import net.minecraft.core.BlockPos; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.chat.Component; @@ -224,8 +223,8 @@ public void showBannerUpdate(Player player, Location location, List pat @Override public void showTabListHeaderFooter(Player player, String header, String footer) { - Component cHeader = Handler.componentToNMS(FormattedTextHelper.parse(header, ChatColor.WHITE)); - Component cFooter = Handler.componentToNMS(FormattedTextHelper.parse(footer, ChatColor.WHITE)); + Component cHeader = Handler.parseNMSComponent(header, PaperAPITools.BaseColor.WHITE); + Component cFooter = Handler.parseNMSComponent(footer, PaperAPITools.BaseColor.WHITE); ClientboundTabListPacket packet = new ClientboundTabListPacket(cHeader, cFooter); send(player, packet); } @@ -234,10 +233,10 @@ public void showTabListHeaderFooter(Player player, String header, String footer) public void showTitle(Player player, String title, String subtitle, int fadeInTicks, int stayTicks, int fadeOutTicks) { send(player, new ClientboundSetTitlesAnimationPacket(fadeInTicks, stayTicks, fadeOutTicks)); if (title != null) { - send(player, new ClientboundSetTitleTextPacket(Handler.componentToNMS(FormattedTextHelper.parse(title, ChatColor.WHITE)))); + send(player, new ClientboundSetTitleTextPacket(Handler.parseNMSComponent(title, PaperAPITools.BaseColor.WHITE))); } if (subtitle != null) { - send(player, new ClientboundSetSubtitleTextPacket(Handler.componentToNMS(FormattedTextHelper.parse(subtitle, ChatColor.WHITE)))); + send(player, new ClientboundSetSubtitleTextPacket(Handler.parseNMSComponent(subtitle, PaperAPITools.BaseColor.WHITE))); } } @@ -342,7 +341,7 @@ public void sendRename(Player player, Entity entity, String name, boolean listMo SynchedEntityData fakeData = new SynchedEntityData(((CraftEntity) entity).getHandle()); ClientboundSetEntityDataPacket packet = new ClientboundSetEntityDataPacket(entity.getEntityId(), fakeData, false); List> list = new ArrayList<>(); - list.add(new SynchedEntityData.DataItem<>(ENTITY_CUSTOM_NAME_METADATA, Optional.of(Handler.componentToNMS(FormattedTextHelper.parse(name, ChatColor.WHITE))))); + list.add(new SynchedEntityData.DataItem<>(ENTITY_CUSTOM_NAME_METADATA, Optional.of(Handler.parseNMSComponent(name, PaperAPITools.BaseColor.WHITE)))); list.add(new SynchedEntityData.DataItem<>(ENTITY_CUSTOM_NAME_VISIBLE_METADATA, true)); ENTITY_METADATA_LIST_SETTER.invoke(packet, list); send(player, packet); diff --git a/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/helpers/PlayerHelperImpl.java b/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/helpers/PlayerHelperImpl.java index 5ff8967e98..1255f9ad3c 100644 --- a/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/helpers/PlayerHelperImpl.java +++ b/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/helpers/PlayerHelperImpl.java @@ -15,14 +15,13 @@ import com.denizenscript.denizen.objects.ItemTag; import com.denizenscript.denizen.objects.LocationTag; import com.denizenscript.denizen.objects.PlayerTag; -import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizen.utilities.entity.DenizenEntityType; import com.denizenscript.denizen.utilities.entity.FakeEntity; import com.denizenscript.denizencore.objects.Mechanism; import com.denizenscript.denizencore.utilities.ReflectionHelper; import com.denizenscript.denizencore.utilities.debugging.Debug; import com.mojang.authlib.GameProfile; -import net.md_5.bungee.api.ChatColor; import net.minecraft.core.BlockPos; import net.minecraft.network.protocol.game.*; import net.minecraft.network.syncher.EntityDataAccessor; @@ -348,7 +347,7 @@ public void setSkinLayers(Player player, byte flags) { @Override public void setBossBarTitle(BossBar bar, String title) { - ((CraftBossBar) bar).getHandle().name = Handler.componentToNMS(FormattedTextHelper.parse(title, ChatColor.WHITE)); + ((CraftBossBar) bar).getHandle().name = Handler.parseNMSComponent(title, PaperAPITools.BaseColor.WHITE); ((CraftBossBar) bar).getHandle().broadcast(ClientboundBossEventPacket::createUpdateNamePacket); } diff --git a/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/impl/ProfileEditorImpl.java b/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/impl/ProfileEditorImpl.java index f0438b1c45..6ba0bbdc4d 100644 --- a/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/impl/ProfileEditorImpl.java +++ b/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/impl/ProfileEditorImpl.java @@ -1,24 +1,23 @@ package com.denizenscript.denizen.nms.v1_17.impl; +import com.denizenscript.denizen.nms.NMSHandler; import com.denizenscript.denizen.nms.abstracts.ProfileEditor; +import com.denizenscript.denizen.nms.util.PlayerProfile; import com.denizenscript.denizen.nms.v1_17.Handler; import com.denizenscript.denizen.nms.v1_17.helpers.PacketHelperImpl; import com.denizenscript.denizen.nms.v1_17.impl.network.handlers.DenizenNetworkManagerImpl; import com.denizenscript.denizen.scripts.commands.entity.RenameCommand; -import com.denizenscript.denizen.utilities.FormattedTextHelper; -import com.mojang.authlib.GameProfile; -import com.mojang.authlib.properties.Property; -import com.denizenscript.denizen.nms.NMSHandler; -import com.denizenscript.denizen.nms.util.PlayerProfile; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizencore.utilities.ReflectionHelper; import com.denizenscript.denizencore.utilities.debugging.Debug; -import net.md_5.bungee.api.ChatColor; +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.properties.Property; import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.game.ClientboundAddPlayerPacket; import net.minecraft.network.protocol.game.ClientboundPlayerInfoPacket; import net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket; -import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v1_17_R1.CraftServer; import org.bukkit.craftbukkit.v1_17_R1.entity.CraftPlayer; @@ -104,7 +103,7 @@ public static boolean handleAlteredProfiles(ClientboundPlayerInfoPacket packet, patchedProfile.getProperties().putAll(data.getProfile().getProperties()); } String listRename = RenameCommand.getCustomNameFor(data.getProfile().getId(), manager.player.getBukkitEntity(), true); - Component displayName = listRename != null ? Handler.componentToNMS(FormattedTextHelper.parse(listRename, ChatColor.WHITE)) : data.getDisplayName(); + Component displayName = listRename != null ? Handler.parseNMSComponent(listRename, PaperAPITools.BaseColor.WHITE) : data.getDisplayName(); ClientboundPlayerInfoPacket.PlayerUpdate newData = new ClientboundPlayerInfoPacket.PlayerUpdate(patchedProfile, data.getLatency(), data.getGameMode(), displayName); newPacketDataList.add(newData); manager.oldManager.send(newPacket); diff --git a/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/impl/SidebarImpl.java b/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/impl/SidebarImpl.java index 8c0dc6356a..c4fadc7aca 100644 --- a/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/impl/SidebarImpl.java +++ b/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/impl/SidebarImpl.java @@ -1,12 +1,11 @@ package com.denizenscript.denizen.nms.v1_17.impl; +import com.denizenscript.denizen.nms.abstracts.Sidebar; import com.denizenscript.denizen.nms.v1_17.Handler; import com.denizenscript.denizen.nms.v1_17.helpers.PacketHelperImpl; -import com.denizenscript.denizen.nms.abstracts.Sidebar; -import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizen.utilities.Utilities; import com.denizenscript.denizencore.utilities.debugging.Debug; -import net.md_5.bungee.api.ChatColor; import net.minecraft.network.chat.MutableComponent; import net.minecraft.network.protocol.game.ClientboundSetDisplayObjectivePacket; import net.minecraft.network.protocol.game.ClientboundSetObjectivePacket; @@ -44,7 +43,7 @@ public class SidebarImpl extends Sidebar { public SidebarImpl(Player player) { super(player); - MutableComponent chatComponentTitle = Handler.componentToNMS(FormattedTextHelper.parse(title, ChatColor.WHITE)); + MutableComponent chatComponentTitle = Handler.parseNMSComponent(title, PaperAPITools.BaseColor.WHITE); this.obj1 = new Objective(dummyScoreboard, "dummy_1", dummyCriteria, chatComponentTitle, ObjectiveCriteria.RenderType.INTEGER); this.obj2 = new Objective(dummyScoreboard, "dummy_2", dummyCriteria, chatComponentTitle, ObjectiveCriteria.RenderType.INTEGER); } @@ -52,7 +51,7 @@ public SidebarImpl(Player player) { @Override protected void setDisplayName(String title) { if (this.obj1 != null) { - MutableComponent chatComponentTitle = Handler.componentToNMS(FormattedTextHelper.parse(title, ChatColor.WHITE)); + MutableComponent chatComponentTitle = Handler.parseNMSComponent(title, PaperAPITools.BaseColor.WHITE); this.obj1.setDisplayName(chatComponentTitle); this.obj2.setDisplayName(chatComponentTitle); } @@ -73,7 +72,7 @@ public void sendUpdate() { String lineId = Utilities.generateRandomColors(8); PlayerTeam team = new PlayerTeam(dummyScoreboard, lineId); team.getPlayers().add(lineId); - team.setPlayerPrefix(Handler.componentToNMS(FormattedTextHelper.parse(line, ChatColor.WHITE))); + team.setPlayerPrefix(Handler.parseNMSComponent(line, PaperAPITools.BaseColor.WHITE)); generatedTeams.add(team); PacketHelperImpl.send(player, ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(team, true)); PacketHelperImpl.send(player, new ClientboundSetScorePacket(ServerScoreboard.Method.CHANGE, obj1.getName(), lineId, this.scores[i])); diff --git a/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/impl/network/handlers/DenizenNetworkManagerImpl.java b/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/impl/network/handlers/DenizenNetworkManagerImpl.java index 04005b13f5..bbb1fe1a41 100644 --- a/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/impl/network/handlers/DenizenNetworkManagerImpl.java +++ b/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/impl/network/handlers/DenizenNetworkManagerImpl.java @@ -17,7 +17,6 @@ import com.denizenscript.denizen.scripts.commands.entity.RenameCommand; import com.denizenscript.denizen.scripts.commands.entity.SneakCommand; import com.denizenscript.denizen.scripts.commands.player.DisguiseCommand; -import com.denizenscript.denizen.utilities.FormattedTextHelper; import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizen.utilities.Settings; import com.denizenscript.denizen.utilities.blocks.ChunkCoordinate; @@ -35,7 +34,6 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.util.concurrent.Future; import io.netty.util.concurrent.GenericFutureListener; -import net.md_5.bungee.api.ChatColor; import net.minecraft.core.BlockPos; import net.minecraft.core.NonNullList; import net.minecraft.core.SectionPos; @@ -608,7 +606,7 @@ public ClientboundSetEntityDataPacket getModifiedMetadataFor(ClientboundSetEntit any = true; } else if (watcherId == 2 && nameToApply != null) { // 2: Custom name metadata - Optional name = Optional.of(Handler.componentToNMS(FormattedTextHelper.parse(nameToApply, ChatColor.WHITE))); + Optional name = Optional.of(Handler.parseNMSComponent(nameToApply, PaperAPITools.BaseColor.WHITE)); data.set(i, new SynchedEntityData.DataItem(watcherObject, name)); any = true; } diff --git a/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/Handler.java b/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/Handler.java index 8d45840736..ff22d85099 100644 --- a/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/Handler.java +++ b/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/Handler.java @@ -12,7 +12,6 @@ import com.denizenscript.denizen.nms.v1_18.impl.ProfileEditorImpl; import com.denizenscript.denizen.nms.v1_18.impl.SidebarImpl; import com.denizenscript.denizen.nms.v1_18.impl.blocks.BlockLightImpl; -import com.denizenscript.denizen.utilities.FormattedTextHelper; import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizencore.utilities.CoreConfiguration; import com.denizenscript.denizencore.utilities.CoreUtilities; @@ -21,9 +20,6 @@ import com.google.common.collect.Iterables; import com.mojang.authlib.GameProfile; import com.mojang.authlib.properties.Property; -import net.md_5.bungee.api.ChatColor; -import net.md_5.bungee.api.chat.BaseComponent; -import net.md_5.bungee.chat.ComponentSerializer; import net.minecraft.core.Holder; import net.minecraft.core.Registry; import net.minecraft.nbt.ByteArrayTag; @@ -193,7 +189,7 @@ else if (MINECRAFT_INVENTORY.isInstance(nms)) { public void setInventoryTitle(InventoryView view, String title) { AbstractContainerMenu menu = ((CraftInventoryView) view).getHandle(); try { - AbstractContainerMenu_title_SETTER.invoke(menu, componentToNMS(FormattedTextHelper.parse(title, ChatColor.DARK_GRAY))); + AbstractContainerMenu_title_SETTER.invoke(menu, parseNMSComponent(title, PaperAPITools.BaseColor.DARK_GRAY)); } catch (Throwable ex) { Debug.echoError(ex); @@ -295,19 +291,17 @@ else if (base instanceof ByteArrayTag) { return null; } - public static BaseComponent[] componentToSpigot(Component nms) { + public static String stringifyNMSComponent(Component nms) { if (nms == null) { return null; } - String json = Component.Serializer.toJson(nms); - return ComponentSerializer.parse(json); + return PaperAPITools.instance.parseJsonToText(Component.Serializer.toJson(nms)); } - public static MutableComponent componentToNMS(BaseComponent[] spigot) { - if (spigot == null) { + public static MutableComponent parseNMSComponent(String formattedText, PaperAPITools.BaseColor baseColor) { + if (formattedText == null) { return null; } - String json = ComponentSerializer.toString(spigot); - return Component.Serializer.fromJson(json); + return Component.Serializer.fromJson(PaperAPITools.instance.parseTextToJson(formattedText, baseColor)); } } diff --git a/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/helpers/AdvancementHelperImpl.java b/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/helpers/AdvancementHelperImpl.java index 2b312a5912..71d83c16d4 100644 --- a/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/helpers/AdvancementHelperImpl.java +++ b/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/helpers/AdvancementHelperImpl.java @@ -1,11 +1,10 @@ package com.denizenscript.denizen.nms.v1_18.helpers; import com.denizenscript.denizen.nms.interfaces.AdvancementHelper; +import com.denizenscript.denizen.nms.v1_18.Handler; import com.denizenscript.denizen.nms.v1_18.ReflectionMappingsInfo; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizencore.utilities.ReflectionHelper; -import com.denizenscript.denizen.nms.v1_18.Handler; -import com.denizenscript.denizen.utilities.FormattedTextHelper; -import net.md_5.bungee.api.ChatColor; import net.minecraft.advancements.*; import net.minecraft.advancements.critereon.ImpossibleTrigger; import net.minecraft.network.protocol.game.ClientboundUpdateAdvancementsPacket; @@ -178,7 +177,7 @@ private static Advancement asNMSCopy(com.denizenscript.denizen.nms.util.Advancem ? getAdvancementDataWorld().advancements.advancements.get(asResourceLocation(advancement.parent)) : null; DisplayInfo display = new DisplayInfo(CraftItemStack.asNMSCopy(advancement.icon), - Handler.componentToNMS(FormattedTextHelper.parse(advancement.title, ChatColor.WHITE)), Handler.componentToNMS(FormattedTextHelper.parse(advancement.description, ChatColor.WHITE)), + Handler.parseNMSComponent(advancement.title, PaperAPITools.BaseColor.WHITE), Handler.parseNMSComponent(advancement.description, PaperAPITools.BaseColor.WHITE), asResourceLocation(advancement.background), FrameType.valueOf(advancement.frame.name()), advancement.toast, advancement.announceToChat, advancement.hidden); display.setLocation(advancement.xOffset, advancement.yOffset); diff --git a/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/helpers/EnchantmentHelperImpl.java b/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/helpers/EnchantmentHelperImpl.java index 78336e7645..30d0039d4d 100644 --- a/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/helpers/EnchantmentHelperImpl.java +++ b/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/helpers/EnchantmentHelperImpl.java @@ -4,7 +4,6 @@ import com.denizenscript.denizen.nms.v1_18.Handler; import com.denizenscript.denizen.nms.v1_18.ReflectionMappingsInfo; import com.denizenscript.denizen.scripts.containers.core.EnchantmentScriptContainer; -import com.denizenscript.denizen.utilities.FormattedTextHelper; import com.denizenscript.denizencore.utilities.ReflectionHelper; import com.denizenscript.denizencore.utilities.debugging.Debug; import net.minecraft.core.MappedRegistry; @@ -183,7 +182,7 @@ public int getMaxCost(Enchantment enchantment, int level) { @Override public String getFullName(Enchantment enchantment, int level) { - return FormattedTextHelper.stringify(Handler.componentToSpigot(((CraftEnchantment) enchantment).getHandle().getFullname(level))); + return Handler.stringifyNMSComponent(((CraftEnchantment) enchantment).getHandle().getFullname(level)); } @Override diff --git a/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/helpers/ItemHelperImpl.java b/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/helpers/ItemHelperImpl.java index 86470a16c0..6c21ebbab9 100644 --- a/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/helpers/ItemHelperImpl.java +++ b/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/helpers/ItemHelperImpl.java @@ -4,7 +4,7 @@ import com.denizenscript.denizen.nms.util.PlayerProfile; import com.denizenscript.denizen.nms.v1_18.ReflectionMappingsInfo; import com.denizenscript.denizen.objects.ItemTag; -import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizencore.utilities.ReflectionHelper; import com.denizenscript.denizencore.utilities.debugging.Debug; import com.google.common.collect.*; @@ -13,9 +13,6 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; import net.kyori.adventure.nbt.BinaryTag; import net.kyori.adventure.nbt.CompoundBinaryTag; -import net.md_5.bungee.api.ChatColor; -import net.md_5.bungee.api.chat.BaseComponent; -import net.md_5.bungee.chat.ComponentSerializer; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.NonNullList; @@ -248,8 +245,7 @@ public String getDisplayName(ItemTag item) { } net.minecraft.world.item.ItemStack nmsItemStack = CraftItemStack.asNMSCopy(item.getItemStack()); String jsonText = ((net.minecraft.nbt.CompoundTag) nmsItemStack.getTag().get("display")).getString("Name"); - BaseComponent[] nameComponent = ComponentSerializer.parse(jsonText); - return FormattedTextHelper.stringify(nameComponent); + return PaperAPITools.instance.parseJsonToText(jsonText); } @Override @@ -261,8 +257,7 @@ public List getLore(ItemTag item) { ListTag list = ((net.minecraft.nbt.CompoundTag) nmsItemStack.getTag().get("display")).getList("Lore", 8); List outList = new ArrayList<>(); for (int i = 0; i < list.size(); i++) { - BaseComponent[] lineComponent = ComponentSerializer.parse(list.getString(i)); - outList.add(FormattedTextHelper.stringify(lineComponent)); + outList.add(PaperAPITools.instance.parseJsonToText(list.getString(i))); } return outList; } @@ -279,8 +274,7 @@ public void setDisplayName(ItemTag item, String name) { display.put("Name", null); return; } - BaseComponent[] components = FormattedTextHelper.parse(name, ChatColor.WHITE); - display.put("Name", net.minecraft.nbt.StringTag.valueOf(ComponentSerializer.toString(components))); + display.put("Name", net.minecraft.nbt.StringTag.valueOf(PaperAPITools.instance.parseTextToJson(name, PaperAPITools.BaseColor.WHITE))); item.setItemStack(CraftItemStack.asBukkitCopy(nmsItemStack)); } @@ -298,7 +292,7 @@ public void setLore(ItemTag item, List lore) { else { ListTag tagList = new ListTag(); for (String line : lore) { - tagList.add(net.minecraft.nbt.StringTag.valueOf(ComponentSerializer.toString(FormattedTextHelper.parse(line, ChatColor.WHITE)))); + tagList.add(net.minecraft.nbt.StringTag.valueOf(PaperAPITools.instance.parseTextToJson(line, PaperAPITools.BaseColor.WHITE))); } display.put("Lore", tagList); } diff --git a/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/helpers/PacketHelperImpl.java b/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/helpers/PacketHelperImpl.java index eb2c1f71c3..7b828f249b 100644 --- a/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/helpers/PacketHelperImpl.java +++ b/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/helpers/PacketHelperImpl.java @@ -9,7 +9,7 @@ import com.denizenscript.denizen.objects.LocationTag; import com.denizenscript.denizen.objects.MaterialTag; import com.denizenscript.denizen.objects.PlayerTag; -import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizen.utilities.Utilities; import com.denizenscript.denizen.utilities.blocks.FakeBlock; import com.denizenscript.denizen.utilities.maps.MapImage; @@ -22,7 +22,6 @@ import net.kyori.adventure.nbt.BinaryTagTypes; import net.kyori.adventure.nbt.CompoundBinaryTag; import net.kyori.adventure.nbt.ListBinaryTag; -import net.md_5.bungee.api.ChatColor; import net.minecraft.core.BlockPos; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.chat.Component; @@ -203,8 +202,8 @@ public void showBannerUpdate(Player player, Location location, List pat @Override public void showTabListHeaderFooter(Player player, String header, String footer) { - Component cHeader = Handler.componentToNMS(FormattedTextHelper.parse(header, ChatColor.WHITE)); - Component cFooter = Handler.componentToNMS(FormattedTextHelper.parse(footer, ChatColor.WHITE)); + Component cHeader = Handler.parseNMSComponent(header, PaperAPITools.BaseColor.WHITE); + Component cFooter = Handler.parseNMSComponent(footer, PaperAPITools.BaseColor.WHITE); ClientboundTabListPacket packet = new ClientboundTabListPacket(cHeader, cFooter); send(player, packet); } @@ -213,10 +212,10 @@ public void showTabListHeaderFooter(Player player, String header, String footer) public void showTitle(Player player, String title, String subtitle, int fadeInTicks, int stayTicks, int fadeOutTicks) { send(player, new ClientboundSetTitlesAnimationPacket(fadeInTicks, stayTicks, fadeOutTicks)); if (title != null) { - send(player, new ClientboundSetTitleTextPacket(Handler.componentToNMS(FormattedTextHelper.parse(title, ChatColor.WHITE)))); + send(player, new ClientboundSetTitleTextPacket(Handler.parseNMSComponent(title, PaperAPITools.BaseColor.WHITE))); } if (subtitle != null) { - send(player, new ClientboundSetSubtitleTextPacket(Handler.componentToNMS(FormattedTextHelper.parse(subtitle, ChatColor.WHITE)))); + send(player, new ClientboundSetSubtitleTextPacket(Handler.parseNMSComponent(subtitle, PaperAPITools.BaseColor.WHITE))); } } @@ -305,7 +304,7 @@ public void sendRename(Player player, Entity entity, String name, boolean listMo SynchedEntityData fakeData = new SynchedEntityData(((CraftEntity) entity).getHandle()); ClientboundSetEntityDataPacket packet = new ClientboundSetEntityDataPacket(entity.getEntityId(), fakeData, false); List> list = new ArrayList<>(); - list.add(new SynchedEntityData.DataItem<>(ENTITY_CUSTOM_NAME_METADATA, Optional.of(Handler.componentToNMS(FormattedTextHelper.parse(name, ChatColor.WHITE))))); + list.add(new SynchedEntityData.DataItem<>(ENTITY_CUSTOM_NAME_METADATA, Optional.of(Handler.parseNMSComponent(name, PaperAPITools.BaseColor.WHITE)))); list.add(new SynchedEntityData.DataItem<>(ENTITY_CUSTOM_NAME_VISIBLE_METADATA, true)); ENTITY_METADATA_LIST_SETTER.invoke(packet, list); send(player, packet); diff --git a/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/helpers/PlayerHelperImpl.java b/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/helpers/PlayerHelperImpl.java index 566afc4032..f1e4e99ee5 100644 --- a/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/helpers/PlayerHelperImpl.java +++ b/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/helpers/PlayerHelperImpl.java @@ -16,7 +16,7 @@ import com.denizenscript.denizen.objects.ItemTag; import com.denizenscript.denizen.objects.LocationTag; import com.denizenscript.denizen.objects.PlayerTag; -import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizen.utilities.entity.DenizenEntityType; import com.denizenscript.denizen.utilities.entity.FakeEntity; import com.denizenscript.denizencore.objects.Mechanism; @@ -25,7 +25,6 @@ import com.mojang.authlib.GameProfile; import com.mojang.authlib.properties.Property; import it.unimi.dsi.fastutil.ints.IntList; -import net.md_5.bungee.api.ChatColor; import net.minecraft.core.BlockPos; import net.minecraft.core.Registry; import net.minecraft.network.protocol.game.*; @@ -365,7 +364,7 @@ public void setSkinLayers(Player player, byte flags) { @Override public void setBossBarTitle(BossBar bar, String title) { - ((CraftBossBar) bar).getHandle().name = Handler.componentToNMS(FormattedTextHelper.parse(title, ChatColor.WHITE)); + ((CraftBossBar) bar).getHandle().name = Handler.parseNMSComponent(title, PaperAPITools.BaseColor.WHITE); ((CraftBossBar) bar).getHandle().broadcast(ClientboundBossEventPacket::createUpdateNamePacket); } @@ -414,7 +413,7 @@ public void sendPlayerInfoAddPacket(Player player, EnumSet edit if (texture != null) { profile.getProperties().put("textures", new Property("textures", texture, signature)); } - packet.getEntries().add(new ClientboundPlayerInfoPacket.PlayerUpdate(profile, latency, gameMode == null ? null : GameType.byId(gameMode.getValue()), display == null ? null : Handler.componentToNMS(FormattedTextHelper.parse(display, ChatColor.WHITE)))); + packet.getEntries().add(new ClientboundPlayerInfoPacket.PlayerUpdate(profile, latency, gameMode == null ? null : GameType.byId(gameMode.getValue()), display == null ? null : Handler.parseNMSComponent(display, PaperAPITools.BaseColor.WHITE))); PacketHelperImpl.send(player, packet); } diff --git a/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/impl/ProfileEditorImpl.java b/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/impl/ProfileEditorImpl.java index edbc58e63e..7e6eecdb37 100644 --- a/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/impl/ProfileEditorImpl.java +++ b/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/impl/ProfileEditorImpl.java @@ -1,22 +1,21 @@ package com.denizenscript.denizen.nms.v1_18.impl; +import com.denizenscript.denizen.nms.NMSHandler; import com.denizenscript.denizen.nms.abstracts.ProfileEditor; +import com.denizenscript.denizen.nms.util.PlayerProfile; import com.denizenscript.denizen.nms.v1_18.Handler; import com.denizenscript.denizen.nms.v1_18.helpers.PacketHelperImpl; import com.denizenscript.denizen.nms.v1_18.impl.network.handlers.DenizenNetworkManagerImpl; import com.denizenscript.denizen.scripts.commands.entity.RenameCommand; -import com.denizenscript.denizen.utilities.FormattedTextHelper; -import com.mojang.authlib.GameProfile; -import com.mojang.authlib.properties.Property; -import com.denizenscript.denizen.nms.NMSHandler; -import com.denizenscript.denizen.nms.util.PlayerProfile; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizencore.utilities.ReflectionHelper; import com.denizenscript.denizencore.utilities.debugging.Debug; -import net.md_5.bungee.api.ChatColor; +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.properties.Property; import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.game.ClientboundPlayerInfoPacket; -import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v1_18_R2.CraftServer; import org.bukkit.craftbukkit.v1_18_R2.entity.CraftPlayer; @@ -89,7 +88,7 @@ public static boolean handleAlteredProfiles(ClientboundPlayerInfoPacket packet, patchedProfile.getProperties().putAll(data.getProfile().getProperties()); } String listRename = RenameCommand.getCustomNameFor(data.getProfile().getId(), manager.player.getBukkitEntity(), true); - Component displayName = listRename != null ? Handler.componentToNMS(FormattedTextHelper.parse(listRename, ChatColor.WHITE)) : data.getDisplayName(); + Component displayName = listRename != null ? Handler.parseNMSComponent(listRename, PaperAPITools.BaseColor.WHITE) : data.getDisplayName(); ClientboundPlayerInfoPacket.PlayerUpdate newData = new ClientboundPlayerInfoPacket.PlayerUpdate(patchedProfile, data.getLatency(), data.getGameMode(), displayName); newPacketDataList.add(newData); manager.oldManager.send(newPacket); diff --git a/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/impl/SidebarImpl.java b/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/impl/SidebarImpl.java index 767842eae6..b6d26ebf70 100644 --- a/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/impl/SidebarImpl.java +++ b/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/impl/SidebarImpl.java @@ -1,12 +1,11 @@ package com.denizenscript.denizen.nms.v1_18.impl; +import com.denizenscript.denizen.nms.abstracts.Sidebar; import com.denizenscript.denizen.nms.v1_18.Handler; import com.denizenscript.denizen.nms.v1_18.helpers.PacketHelperImpl; -import com.denizenscript.denizen.nms.abstracts.Sidebar; -import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizen.utilities.Utilities; import com.denizenscript.denizencore.utilities.debugging.Debug; -import net.md_5.bungee.api.ChatColor; import net.minecraft.network.chat.MutableComponent; import net.minecraft.network.protocol.game.ClientboundSetDisplayObjectivePacket; import net.minecraft.network.protocol.game.ClientboundSetObjectivePacket; @@ -44,7 +43,7 @@ public class SidebarImpl extends Sidebar { public SidebarImpl(Player player) { super(player); - MutableComponent chatComponentTitle = Handler.componentToNMS(FormattedTextHelper.parse(title, ChatColor.WHITE)); + MutableComponent chatComponentTitle = Handler.parseNMSComponent(title, PaperAPITools.BaseColor.WHITE); this.obj1 = new Objective(dummyScoreboard, "dummy_1", dummyCriteria, chatComponentTitle, ObjectiveCriteria.RenderType.INTEGER); this.obj2 = new Objective(dummyScoreboard, "dummy_2", dummyCriteria, chatComponentTitle, ObjectiveCriteria.RenderType.INTEGER); } @@ -52,7 +51,7 @@ public SidebarImpl(Player player) { @Override protected void setDisplayName(String title) { if (this.obj1 != null) { - MutableComponent chatComponentTitle = Handler.componentToNMS(FormattedTextHelper.parse(title, ChatColor.WHITE)); + MutableComponent chatComponentTitle = Handler.parseNMSComponent(title, PaperAPITools.BaseColor.WHITE); this.obj1.setDisplayName(chatComponentTitle); this.obj2.setDisplayName(chatComponentTitle); } @@ -73,7 +72,7 @@ public void sendUpdate() { String lineId = Utilities.generateRandomColors(8); PlayerTeam team = new PlayerTeam(dummyScoreboard, lineId); team.getPlayers().add(lineId); - team.setPlayerPrefix(Handler.componentToNMS(FormattedTextHelper.parse(line, ChatColor.WHITE))); + team.setPlayerPrefix(Handler.parseNMSComponent(line, PaperAPITools.BaseColor.WHITE)); generatedTeams.add(team); PacketHelperImpl.send(player, ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(team, true)); PacketHelperImpl.send(player, new ClientboundSetScorePacket(ServerScoreboard.Method.CHANGE, obj1.getName(), lineId, this.scores[i])); diff --git a/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/impl/network/handlers/DenizenNetworkManagerImpl.java b/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/impl/network/handlers/DenizenNetworkManagerImpl.java index 70b1f38e33..9e1ea84a79 100644 --- a/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/impl/network/handlers/DenizenNetworkManagerImpl.java +++ b/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/impl/network/handlers/DenizenNetworkManagerImpl.java @@ -16,7 +16,6 @@ import com.denizenscript.denizen.objects.PlayerTag; import com.denizenscript.denizen.scripts.commands.entity.*; import com.denizenscript.denizen.scripts.commands.player.DisguiseCommand; -import com.denizenscript.denizen.utilities.FormattedTextHelper; import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizen.utilities.Settings; import com.denizenscript.denizen.utilities.blocks.ChunkCoordinate; @@ -38,7 +37,6 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.util.concurrent.Future; import io.netty.util.concurrent.GenericFutureListener; -import net.md_5.bungee.api.ChatColor; import net.minecraft.core.BlockPos; import net.minecraft.core.NonNullList; import net.minecraft.core.SectionPos; @@ -350,7 +348,7 @@ public boolean processTablistPacket(Packet packet, GenericFutureListener packet, GenericFutureListener name = Optional.of(Handler.componentToNMS(FormattedTextHelper.parse(nameToApply, ChatColor.WHITE))); + Optional name = Optional.of(Handler.parseNMSComponent(nameToApply, PaperAPITools.BaseColor.WHITE)); data.set(i, new SynchedEntityData.DataItem(watcherObject, name)); any = true; } diff --git a/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/Handler.java b/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/Handler.java index 09913ac081..99bd8cf5c8 100644 --- a/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/Handler.java +++ b/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/Handler.java @@ -12,7 +12,6 @@ import com.denizenscript.denizen.nms.v1_19.impl.ProfileEditorImpl; import com.denizenscript.denizen.nms.v1_19.impl.SidebarImpl; import com.denizenscript.denizen.nms.v1_19.impl.blocks.BlockLightImpl; -import com.denizenscript.denizen.utilities.FormattedTextHelper; import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizencore.utilities.CoreConfiguration; import com.denizenscript.denizencore.utilities.CoreUtilities; @@ -21,9 +20,6 @@ import com.google.common.collect.Iterables; import com.mojang.authlib.GameProfile; import com.mojang.authlib.properties.Property; -import net.md_5.bungee.api.ChatColor; -import net.md_5.bungee.api.chat.BaseComponent; -import net.md_5.bungee.chat.ComponentSerializer; import net.minecraft.core.Holder; import net.minecraft.core.registries.Registries; import net.minecraft.nbt.ByteArrayTag; @@ -197,7 +193,7 @@ else if (MINECRAFT_INVENTORY.isInstance(nms)) { public void setInventoryTitle(InventoryView view, String title) { AbstractContainerMenu menu = ((CraftInventoryView) view).getHandle(); try { - AbstractContainerMenu_title_SETTER.invoke(menu, componentToNMS(FormattedTextHelper.parse(title, ChatColor.DARK_GRAY))); + AbstractContainerMenu_title_SETTER.invoke(menu, parseNMSComponent(title, PaperAPITools.BaseColor.DARK_GRAY)); } catch (Throwable ex) { Debug.echoError(ex); @@ -316,19 +312,17 @@ public void setBossbarUUID(BossBar bar, UUID id) { } } - public static BaseComponent[] componentToSpigot(Component nms) { + public static String stringifyNMSComponent(Component nms) { if (nms == null) { return null; } - String json = Component.Serializer.toJson(nms); - return ComponentSerializer.parse(json); + return PaperAPITools.instance.parseJsonToText(Component.Serializer.toJson(nms)); } - public static MutableComponent componentToNMS(BaseComponent[] spigot) { - if (spigot == null) { + public static MutableComponent parseNMSComponent(String formattedText, PaperAPITools.BaseColor baseColor) { + if (formattedText == null) { return null; } - String json = FormattedTextHelper.componentToJson(spigot); - return Component.Serializer.fromJson(json); + return Component.Serializer.fromJson(PaperAPITools.instance.parseTextToJson(formattedText, baseColor)); } } diff --git a/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/helpers/AdvancementHelperImpl.java b/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/helpers/AdvancementHelperImpl.java index 24dbf20f06..bbce83bf07 100644 --- a/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/helpers/AdvancementHelperImpl.java +++ b/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/helpers/AdvancementHelperImpl.java @@ -1,11 +1,10 @@ package com.denizenscript.denizen.nms.v1_19.helpers; import com.denizenscript.denizen.nms.interfaces.AdvancementHelper; +import com.denizenscript.denizen.nms.v1_19.Handler; import com.denizenscript.denizen.nms.v1_19.ReflectionMappingsInfo; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizencore.utilities.ReflectionHelper; -import com.denizenscript.denizen.nms.v1_19.Handler; -import com.denizenscript.denizen.utilities.FormattedTextHelper; -import net.md_5.bungee.api.ChatColor; import net.minecraft.advancements.*; import net.minecraft.advancements.critereon.ImpossibleTrigger; import net.minecraft.network.protocol.game.ClientboundUpdateAdvancementsPacket; @@ -178,7 +177,7 @@ private static Advancement asNMSCopy(com.denizenscript.denizen.nms.util.Advancem ? getAdvancementDataWorld().advancements.advancements.get(asResourceLocation(advancement.parent)) : null; DisplayInfo display = new DisplayInfo(CraftItemStack.asNMSCopy(advancement.icon), - Handler.componentToNMS(FormattedTextHelper.parse(advancement.title, ChatColor.WHITE)), Handler.componentToNMS(FormattedTextHelper.parse(advancement.description, ChatColor.WHITE)), + Handler.parseNMSComponent(advancement.title, PaperAPITools.BaseColor.WHITE), Handler.parseNMSComponent(advancement.description, PaperAPITools.BaseColor.WHITE), asResourceLocation(advancement.background), FrameType.valueOf(advancement.frame.name()), advancement.toast, advancement.announceToChat, advancement.hidden); display.setLocation(advancement.xOffset, advancement.yOffset); diff --git a/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/helpers/EnchantmentHelperImpl.java b/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/helpers/EnchantmentHelperImpl.java index 4fbdff5cb4..79a7c616f0 100644 --- a/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/helpers/EnchantmentHelperImpl.java +++ b/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/helpers/EnchantmentHelperImpl.java @@ -4,7 +4,6 @@ import com.denizenscript.denizen.nms.v1_19.Handler; import com.denizenscript.denizen.nms.v1_19.ReflectionMappingsInfo; import com.denizenscript.denizen.scripts.containers.core.EnchantmentScriptContainer; -import com.denizenscript.denizen.utilities.FormattedTextHelper; import com.denizenscript.denizencore.utilities.CoreUtilities; import com.denizenscript.denizencore.utilities.ReflectionHelper; import com.denizenscript.denizencore.utilities.debugging.Debug; @@ -185,7 +184,7 @@ public int getMaxCost(Enchantment enchantment, int level) { @Override public String getFullName(Enchantment enchantment, int level) { - return FormattedTextHelper.stringify(Handler.componentToSpigot(((CraftEnchantment) enchantment).getHandle().getFullname(level))); + return Handler.stringifyNMSComponent(((CraftEnchantment) enchantment).getHandle().getFullname(level)); } @Override diff --git a/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/helpers/ItemHelperImpl.java b/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/helpers/ItemHelperImpl.java index e4bcbbb22b..501a24cf54 100644 --- a/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/helpers/ItemHelperImpl.java +++ b/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/helpers/ItemHelperImpl.java @@ -4,7 +4,7 @@ import com.denizenscript.denizen.nms.util.PlayerProfile; import com.denizenscript.denizen.nms.v1_19.ReflectionMappingsInfo; import com.denizenscript.denizen.objects.ItemTag; -import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizencore.utilities.CoreUtilities; import com.denizenscript.denizencore.utilities.ReflectionHelper; import com.denizenscript.denizencore.utilities.debugging.Debug; @@ -14,9 +14,6 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; import net.kyori.adventure.nbt.BinaryTag; import net.kyori.adventure.nbt.CompoundBinaryTag; -import net.md_5.bungee.api.ChatColor; -import net.md_5.bungee.api.chat.BaseComponent; -import net.md_5.bungee.chat.ComponentSerializer; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.NonNullList; @@ -252,8 +249,7 @@ public String getDisplayName(ItemTag item) { } net.minecraft.world.item.ItemStack nmsItemStack = CraftItemStack.asNMSCopy(item.getItemStack()); String jsonText = ((net.minecraft.nbt.CompoundTag) nmsItemStack.getTag().get("display")).getString("Name"); - BaseComponent[] nameComponent = ComponentSerializer.parse(jsonText); - return FormattedTextHelper.stringify(nameComponent); + return PaperAPITools.instance.parseJsonToText(jsonText); } @Override @@ -265,8 +261,7 @@ public List getLore(ItemTag item) { ListTag list = ((net.minecraft.nbt.CompoundTag) nmsItemStack.getTag().get("display")).getList("Lore", 8); List outList = new ArrayList<>(); for (int i = 0; i < list.size(); i++) { - BaseComponent[] lineComponent = ComponentSerializer.parse(list.getString(i)); - outList.add(FormattedTextHelper.stringify(lineComponent)); + outList.add(PaperAPITools.instance.parseJsonToText(list.getString(i))); } return outList; } @@ -283,8 +278,7 @@ public void setDisplayName(ItemTag item, String name) { display.put("Name", null); return; } - BaseComponent[] components = FormattedTextHelper.parse(name, ChatColor.WHITE); - display.put("Name", net.minecraft.nbt.StringTag.valueOf(FormattedTextHelper.componentToJson(components))); + display.put("Name", net.minecraft.nbt.StringTag.valueOf(PaperAPITools.instance.parseTextToJson(name, PaperAPITools.BaseColor.WHITE))); item.setItemStack(CraftItemStack.asBukkitCopy(nmsItemStack)); } @@ -305,7 +299,7 @@ public void setLore(ItemTag item, List lore) { else { ListTag tagList = new ListTag(); for (String line : lore) { - tagList.add(net.minecraft.nbt.StringTag.valueOf(FormattedTextHelper.componentToJson(FormattedTextHelper.parse(line, ChatColor.WHITE)))); + tagList.add(net.minecraft.nbt.StringTag.valueOf(PaperAPITools.instance.parseTextToJson(line, PaperAPITools.BaseColor.WHITE))); } display.put("Lore", tagList); } diff --git a/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/helpers/PacketHelperImpl.java b/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/helpers/PacketHelperImpl.java index 2cefae3d5e..5750ce0db2 100644 --- a/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/helpers/PacketHelperImpl.java +++ b/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/helpers/PacketHelperImpl.java @@ -9,7 +9,7 @@ import com.denizenscript.denizen.objects.LocationTag; import com.denizenscript.denizen.objects.MaterialTag; import com.denizenscript.denizen.objects.PlayerTag; -import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizen.utilities.Utilities; import com.denizenscript.denizen.utilities.blocks.FakeBlock; import com.denizenscript.denizen.utilities.maps.MapImage; @@ -21,7 +21,6 @@ import net.kyori.adventure.nbt.BinaryTagTypes; import net.kyori.adventure.nbt.CompoundBinaryTag; import net.kyori.adventure.nbt.ListBinaryTag; -import net.md_5.bungee.api.ChatColor; import net.minecraft.core.BlockPos; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.chat.Component; @@ -190,8 +189,8 @@ public void showBannerUpdate(Player player, Location location, List pat @Override public void showTabListHeaderFooter(Player player, String header, String footer) { - Component cHeader = Handler.componentToNMS(FormattedTextHelper.parse(header, ChatColor.WHITE)); - Component cFooter = Handler.componentToNMS(FormattedTextHelper.parse(footer, ChatColor.WHITE)); + Component cHeader = Handler.parseNMSComponent(header, PaperAPITools.BaseColor.WHITE); + Component cFooter = Handler.parseNMSComponent(footer, PaperAPITools.BaseColor.WHITE); ClientboundTabListPacket packet = new ClientboundTabListPacket(cHeader, cFooter); send(player, packet); } @@ -200,10 +199,10 @@ public void showTabListHeaderFooter(Player player, String header, String footer) public void showTitle(Player player, String title, String subtitle, int fadeInTicks, int stayTicks, int fadeOutTicks) { send(player, new ClientboundSetTitlesAnimationPacket(fadeInTicks, stayTicks, fadeOutTicks)); if (title != null) { - send(player, new ClientboundSetTitleTextPacket(Handler.componentToNMS(FormattedTextHelper.parse(title, ChatColor.WHITE)))); + send(player, new ClientboundSetTitleTextPacket(Handler.parseNMSComponent(title, PaperAPITools.BaseColor.WHITE))); } if (subtitle != null) { - send(player, new ClientboundSetSubtitleTextPacket(Handler.componentToNMS(FormattedTextHelper.parse(subtitle, ChatColor.WHITE)))); + send(player, new ClientboundSetSubtitleTextPacket(Handler.parseNMSComponent(subtitle, PaperAPITools.BaseColor.WHITE))); } } @@ -278,7 +277,7 @@ public void sendRename(Player player, Entity entity, String name, boolean listMo } SynchedEntityData fakeData = new SynchedEntityData(((CraftEntity) entity).getHandle()); List> list = new ArrayList<>(); - list.add(new SynchedEntityData.DataValue<>(ENTITY_DATA_ACCESSOR_CUSTOM_NAME.getId(), ENTITY_DATA_ACCESSOR_CUSTOM_NAME.getSerializer(), Optional.of(Handler.componentToNMS(FormattedTextHelper.parse(name, ChatColor.WHITE))))); + list.add(new SynchedEntityData.DataValue<>(ENTITY_DATA_ACCESSOR_CUSTOM_NAME.getId(), ENTITY_DATA_ACCESSOR_CUSTOM_NAME.getSerializer(), Optional.of(Handler.parseNMSComponent(name, PaperAPITools.BaseColor.WHITE)))); list.add(new SynchedEntityData.DataValue<>(ENTITY_DATA_ACCESSOR_CUSTOM_NAME_VISIBLE.getId(), ENTITY_DATA_ACCESSOR_CUSTOM_NAME_VISIBLE.getSerializer(), true)); send(player, new ClientboundSetEntityDataPacket(entity.getEntityId(), list)); } diff --git a/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/helpers/PlayerHelperImpl.java b/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/helpers/PlayerHelperImpl.java index 59927a9144..b9f9d3216e 100644 --- a/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/helpers/PlayerHelperImpl.java +++ b/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/helpers/PlayerHelperImpl.java @@ -17,7 +17,7 @@ import com.denizenscript.denizen.objects.ItemTag; import com.denizenscript.denizen.objects.LocationTag; import com.denizenscript.denizen.objects.PlayerTag; -import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizen.utilities.entity.DenizenEntityType; import com.denizenscript.denizen.utilities.entity.FakeEntity; import com.denizenscript.denizencore.objects.Mechanism; @@ -26,7 +26,6 @@ import com.mojang.authlib.GameProfile; import com.mojang.authlib.properties.Property; import it.unimi.dsi.fastutil.ints.IntList; -import net.md_5.bungee.api.ChatColor; import net.minecraft.core.BlockPos; import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; @@ -370,7 +369,7 @@ public void setSkinLayers(Player player, byte flags) { @Override public void setBossBarTitle(BossBar bar, String title) { - ((CraftBossBar) bar).getHandle().name = Handler.componentToNMS(FormattedTextHelper.parse(title, ChatColor.WHITE)); + ((CraftBossBar) bar).getHandle().name = Handler.parseNMSComponent(title, PaperAPITools.BaseColor.WHITE); ((CraftBossBar) bar).getHandle().broadcast(ClientboundBossEventPacket::createUpdateNamePacket); } @@ -425,7 +424,7 @@ public void sendPlayerInfoAddPacket(Player player, EnumSet edit if (texture != null) { profile.getProperties().put("textures", new Property("textures", texture, signature)); } - ClientboundPlayerInfoUpdatePacket.Entry entry = new ClientboundPlayerInfoUpdatePacket.Entry(id, profile, listed, latency, gameMode == null ? null : GameType.byId(gameMode.getValue()), display == null ? null : Handler.componentToNMS(FormattedTextHelper.parse(display, ChatColor.WHITE)), null); + ClientboundPlayerInfoUpdatePacket.Entry entry = new ClientboundPlayerInfoUpdatePacket.Entry(id, profile, listed, latency, gameMode == null ? null : GameType.byId(gameMode.getValue()), display == null ? null : Handler.parseNMSComponent(display, PaperAPITools.BaseColor.WHITE), null); PacketHelperImpl.send(player, ProfileEditorImpl.createInfoPacket(actions, List.of(entry))); } diff --git a/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/impl/ProfileEditorImpl.java b/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/impl/ProfileEditorImpl.java index 04b7b8d42a..6987e04506 100644 --- a/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/impl/ProfileEditorImpl.java +++ b/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/impl/ProfileEditorImpl.java @@ -8,12 +8,11 @@ import com.denizenscript.denizen.nms.v1_19.helpers.PacketHelperImpl; import com.denizenscript.denizen.nms.v1_19.impl.network.handlers.DenizenNetworkManagerImpl; import com.denizenscript.denizen.scripts.commands.entity.RenameCommand; -import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizencore.utilities.ReflectionHelper; import com.denizenscript.denizencore.utilities.debugging.Debug; import com.mojang.authlib.GameProfile; import com.mojang.authlib.properties.Property; -import net.md_5.bungee.api.ChatColor; import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket; import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket; @@ -89,7 +88,7 @@ public static boolean handleAlteredProfiles(ClientboundPlayerInfoUpdatePacket pa patchedProfile.getProperties().putAll(Denizen.supportsPaper ? data.profile().getProperties() : baseProfile.getProperties()); } String listRename = RenameCommand.getCustomNameFor(data.profileId(), manager.player.getBukkitEntity(), true); - Component displayName = listRename != null ? Handler.componentToNMS(FormattedTextHelper.parse(listRename, ChatColor.WHITE)) : data.displayName(); + Component displayName = listRename != null ? Handler.parseNMSComponent(listRename, PaperAPITools.BaseColor.WHITE) : data.displayName(); ClientboundPlayerInfoUpdatePacket.Entry newData = new ClientboundPlayerInfoUpdatePacket.Entry(data.profileId(), patchedProfile, data.listed(), data.latency(), data.gameMode(), displayName, data.chatSession()); manager.oldManager.send(createInfoPacket(actions, List.of(newData))); } diff --git a/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/impl/SidebarImpl.java b/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/impl/SidebarImpl.java index c56298727c..3efd9d9e45 100644 --- a/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/impl/SidebarImpl.java +++ b/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/impl/SidebarImpl.java @@ -1,12 +1,11 @@ package com.denizenscript.denizen.nms.v1_19.impl; +import com.denizenscript.denizen.nms.abstracts.Sidebar; import com.denizenscript.denizen.nms.v1_19.Handler; import com.denizenscript.denizen.nms.v1_19.helpers.PacketHelperImpl; -import com.denizenscript.denizen.nms.abstracts.Sidebar; -import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizen.utilities.Utilities; import com.denizenscript.denizencore.utilities.debugging.Debug; -import net.md_5.bungee.api.ChatColor; import net.minecraft.network.chat.MutableComponent; import net.minecraft.network.protocol.game.ClientboundSetDisplayObjectivePacket; import net.minecraft.network.protocol.game.ClientboundSetObjectivePacket; @@ -44,7 +43,7 @@ public class SidebarImpl extends Sidebar { public SidebarImpl(Player player) { super(player); - MutableComponent chatComponentTitle = Handler.componentToNMS(FormattedTextHelper.parse(title, ChatColor.WHITE)); + MutableComponent chatComponentTitle = Handler.parseNMSComponent(title, PaperAPITools.BaseColor.WHITE); this.obj1 = new Objective(dummyScoreboard, "dummy_1", dummyCriteria, chatComponentTitle, ObjectiveCriteria.RenderType.INTEGER); this.obj2 = new Objective(dummyScoreboard, "dummy_2", dummyCriteria, chatComponentTitle, ObjectiveCriteria.RenderType.INTEGER); } @@ -52,7 +51,7 @@ public SidebarImpl(Player player) { @Override protected void setDisplayName(String title) { if (this.obj1 != null) { - MutableComponent chatComponentTitle = Handler.componentToNMS(FormattedTextHelper.parse(title, ChatColor.WHITE)); + MutableComponent chatComponentTitle = Handler.parseNMSComponent(title, PaperAPITools.BaseColor.WHITE); this.obj1.setDisplayName(chatComponentTitle); this.obj2.setDisplayName(chatComponentTitle); } @@ -73,7 +72,7 @@ public void sendUpdate() { String lineId = Utilities.generateRandomColors(8); PlayerTeam team = new PlayerTeam(dummyScoreboard, lineId); team.getPlayers().add(lineId); - team.setPlayerPrefix(Handler.componentToNMS(FormattedTextHelper.parse(line, ChatColor.WHITE))); + team.setPlayerPrefix(Handler.parseNMSComponent(line, PaperAPITools.BaseColor.WHITE)); generatedTeams.add(team); PacketHelperImpl.send(player, ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(team, true)); PacketHelperImpl.send(player, new ClientboundSetScorePacket(ServerScoreboard.Method.CHANGE, obj1.getName(), lineId, this.scores[i])); diff --git a/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/impl/network/handlers/DenizenNetworkManagerImpl.java b/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/impl/network/handlers/DenizenNetworkManagerImpl.java index a6c2e78ba2..5261101266 100644 --- a/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/impl/network/handlers/DenizenNetworkManagerImpl.java +++ b/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/impl/network/handlers/DenizenNetworkManagerImpl.java @@ -14,7 +14,6 @@ import com.denizenscript.denizen.objects.PlayerTag; import com.denizenscript.denizen.scripts.commands.entity.*; import com.denizenscript.denizen.scripts.commands.player.DisguiseCommand; -import com.denizenscript.denizen.utilities.FormattedTextHelper; import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizen.utilities.Settings; import com.denizenscript.denizen.utilities.blocks.ChunkCoordinate; @@ -36,7 +35,6 @@ import com.mojang.datafixers.util.Pair; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; -import net.md_5.bungee.api.ChatColor; import net.minecraft.core.BlockPos; import net.minecraft.core.NonNullList; import net.minecraft.core.SectionPos; @@ -410,7 +408,7 @@ public boolean processTablistPacket(Packet packet, PacketSendListener generic } String modeText = update.gameMode() == null ? null : update.gameMode().name(); PlayerReceivesTablistUpdateScriptEvent.TabPacketData data = new PlayerReceivesTablistUpdateScriptEvent.TabPacketData(mode, profile.getId(), update.listed(), profile.getName(), - update.displayName() == null ? null : FormattedTextHelper.stringify(Handler.componentToSpigot(update.displayName())), modeText, texture, signature, update.latency()); + update.displayName() == null ? null : Handler.stringifyNMSComponent(update.displayName()), modeText, texture, signature, update.latency()); PlayerReceivesTablistUpdateScriptEvent.fire(player.getBukkitEntity(), data); if (data.modified) { if (!isOverriding) { @@ -428,7 +426,7 @@ public boolean processTablistPacket(Packet packet, PacketSendListener generic newProfile.getProperties().put("textures", new Property("textures", data.texture, data.signature)); } ClientboundPlayerInfoUpdatePacket.Entry entry = new ClientboundPlayerInfoUpdatePacket.Entry(newProfile.getId(), newProfile, data.isListed, data.latency, data.gamemode == null ? null : GameType.byName(CoreUtilities.toLowerCase(data.gamemode)), - data.display == null ? null : Handler.componentToNMS(FormattedTextHelper.parse(data.display, ChatColor.WHITE)), update.chatSession()); + data.display == null ? null : Handler.parseNMSComponent(data.display, PaperAPITools.BaseColor.WHITE), update.chatSession()); oldManager.send(ProfileEditorImpl.createInfoPacket(infoPacket.actions(), Collections.singletonList(entry)), genericfuturelistener); } } @@ -840,7 +838,7 @@ else if (nameToApply == null || (dataValue.id() != 2 && dataValue.id() != 3)) { data.add(SynchedEntityData.DataValue.create(PacketHelperImpl.ENTITY_DATA_ACCESSOR_FLAGS, flags)); } if (nameToApply != null) { - data.add(SynchedEntityData.DataValue.create(PacketHelperImpl.ENTITY_DATA_ACCESSOR_CUSTOM_NAME, Optional.of(Handler.componentToNMS(FormattedTextHelper.parse(nameToApply, ChatColor.WHITE))))); + data.add(SynchedEntityData.DataValue.create(PacketHelperImpl.ENTITY_DATA_ACCESSOR_CUSTOM_NAME, Optional.of(Handler.parseNMSComponent(nameToApply, PaperAPITools.BaseColor.WHITE)))); data.add(SynchedEntityData.DataValue.create(PacketHelperImpl.ENTITY_DATA_ACCESSOR_CUSTOM_NAME_VISIBLE, true)); } return new ClientboundSetEntityDataPacket(metadataPacket.id(), data); diff --git a/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/Handler.java b/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/Handler.java index f162d44efd..66fa5509ac 100644 --- a/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/Handler.java +++ b/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/Handler.java @@ -16,7 +16,6 @@ import com.denizenscript.denizen.objects.LocationTag; import com.denizenscript.denizen.objects.MaterialTag; import com.denizenscript.denizen.objects.properties.item.ItemRawNBT; -import com.denizenscript.denizen.utilities.FormattedTextHelper; import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; @@ -33,9 +32,6 @@ import com.mojang.authlib.properties.Property; import com.mojang.authlib.yggdrasil.ProfileResult; import net.kyori.adventure.nbt.CompoundBinaryTag; -import net.md_5.bungee.api.ChatColor; -import net.md_5.bungee.api.chat.BaseComponent; -import net.md_5.bungee.chat.ComponentSerializer; import net.minecraft.core.BlockPos; import net.minecraft.core.Holder; import net.minecraft.core.Rotations; @@ -108,7 +104,7 @@ public Handler() { enchantmentHelper = new EnchantmentHelperImpl(); registerConversion(ItemTag.class, ItemStack.class, item -> CraftItemStack.asNMSCopy(item.getItemStack())); - registerConversion(ElementTag.class, Component.class, element -> componentToNMS(FormattedTextHelper.parse(element.asString(), ChatColor.WHITE))); + registerConversion(ElementTag.class, Component.class, element -> parseNMSComponent(element.asString(), PaperAPITools.BaseColor.WHITE)); registerConversion(MaterialTag.class, BlockState.class, material -> ((CraftBlockData) material.getModernData()).getState()); registerConversion(LocationTag.class, Rotations.class, location -> new Rotations((float) location.getX(), (float) location.getY(), (float) location.getZ())); registerConversion(LocationTag.class, BlockPos.class, CraftLocation::toBlockPosition); @@ -240,7 +236,7 @@ else if (MINECRAFT_INVENTORY.isInstance(nms)) { public void setInventoryTitle(InventoryView view, String title) { AbstractContainerMenu menu = ((CraftInventoryView) view).getHandle(); try { - AbstractContainerMenu_title_SETTER.invoke(menu, componentToNMS(FormattedTextHelper.parse(title, ChatColor.DARK_GRAY))); + AbstractContainerMenu_title_SETTER.invoke(menu, parseNMSComponent(title, PaperAPITools.BaseColor.DARK_GRAY)); } catch (Throwable ex) { Debug.echoError(ex); @@ -359,22 +355,22 @@ public void setBossbarUUID(BossBar bar, UUID id) { } } - public static BaseComponent[] componentToSpigot(Component nms) { + @Override + public String updateLegacyName(Class type, String legacyName) { + return FieldRename.rename(ApiVersion.FIELD_NAME_PARITY, DebugInternals.getFullClassNameOpti(type).replace('.', '/'), legacyName); + } + + public static String stringifyNMSComponent(Component nms) { if (nms == null) { return null; } - return ComponentSerializer.parse(CraftChatMessage.toJSON(nms)); + return PaperAPITools.instance.parseJsonToText(CraftChatMessage.toJSON(nms)); } - public static Component componentToNMS(BaseComponent[] spigot) { - if (spigot == null) { + public static Component parseNMSComponent(String formattedText, PaperAPITools.BaseColor baseColor) { + if (formattedText == null) { return null; } - return CraftChatMessage.fromJSONOrNull(FormattedTextHelper.componentToJson(spigot)); - } - - @Override - public String updateLegacyName(Class type, String legacyName) { - return FieldRename.rename(ApiVersion.FIELD_NAME_PARITY, DebugInternals.getFullClassNameOpti(type).replace('.', '/'), legacyName); + return CraftChatMessage.fromJSON(PaperAPITools.instance.parseTextToJson(formattedText, baseColor)); } } diff --git a/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/helpers/AdvancementHelperImpl.java b/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/helpers/AdvancementHelperImpl.java index 7b70014dcb..59c4630773 100644 --- a/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/helpers/AdvancementHelperImpl.java +++ b/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/helpers/AdvancementHelperImpl.java @@ -2,9 +2,8 @@ import com.denizenscript.denizen.nms.interfaces.AdvancementHelper; import com.denizenscript.denizen.nms.v1_20.Handler; -import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.google.common.collect.ImmutableMap; -import net.md_5.bungee.api.ChatColor; import net.minecraft.advancements.*; import net.minecraft.advancements.critereon.ImpossibleTrigger; import net.minecraft.network.protocol.game.ClientboundUpdateAdvancementsPacket; @@ -159,7 +158,7 @@ private static AdvancementHolder asNMSCopy(com.denizenscript.denizen.nms.util.Ad ? getNMSAdvancementManager().advancements.get(CraftNamespacedKey.toMinecraft(advancement.parent)) : null; DisplayInfo display = new DisplayInfo(CraftItemStack.asNMSCopy(advancement.icon), - Handler.componentToNMS(FormattedTextHelper.parse(advancement.title, ChatColor.WHITE)), Handler.componentToNMS(FormattedTextHelper.parse(advancement.description, ChatColor.WHITE)), + Handler.parseNMSComponent(advancement.title, PaperAPITools.BaseColor.WHITE), Handler.parseNMSComponent(advancement.description, PaperAPITools.BaseColor.WHITE), Optional.ofNullable(advancement.background).map(CraftNamespacedKey::toMinecraft), AdvancementType.valueOf(advancement.frame.name()), advancement.toast, advancement.announceToChat, advancement.hidden); display.setLocation(advancement.xOffset, advancement.yOffset); diff --git a/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/helpers/EnchantmentHelperImpl.java b/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/helpers/EnchantmentHelperImpl.java index 92adb49cc0..d4b1cf1d38 100644 --- a/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/helpers/EnchantmentHelperImpl.java +++ b/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/helpers/EnchantmentHelperImpl.java @@ -5,7 +5,6 @@ import com.denizenscript.denizen.nms.v1_20.Handler; import com.denizenscript.denizen.nms.v1_20.ReflectionMappingsInfo; import com.denizenscript.denizen.scripts.containers.core.EnchantmentScriptContainer; -import com.denizenscript.denizen.utilities.FormattedTextHelper; import com.denizenscript.denizencore.utilities.CoreUtilities; import com.denizenscript.denizencore.utilities.ReflectionHelper; import com.denizenscript.denizencore.utilities.debugging.Debug; @@ -193,7 +192,7 @@ public int getMaxCost(Enchantment enchantment, int level) { @Override public String getFullName(Enchantment enchantment, int level) { - return FormattedTextHelper.stringify(Handler.componentToSpigot(((CraftEnchantment) enchantment).getHandle().getFullname(level))); + return Handler.stringifyNMSComponent(((CraftEnchantment) enchantment).getHandle().getFullname(level)); } // TODO: 1.20.6: MobType was removed in favor of using the entity type directly - deprecate + potentially backsupport with vanilla tags diff --git a/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/helpers/ItemHelperImpl.java b/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/helpers/ItemHelperImpl.java index cc304f59b4..c70a5829f4 100644 --- a/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/helpers/ItemHelperImpl.java +++ b/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/helpers/ItemHelperImpl.java @@ -8,7 +8,6 @@ import com.denizenscript.denizen.objects.ItemTag; import com.denizenscript.denizen.objects.properties.item.ItemComponentsPatch; import com.denizenscript.denizen.objects.properties.item.ItemRawNBT; -import com.denizenscript.denizen.utilities.FormattedTextHelper; import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.objects.core.MapTag; @@ -23,7 +22,6 @@ import com.mojang.serialization.JsonOps; import net.kyori.adventure.nbt.BinaryTag; import net.kyori.adventure.nbt.CompoundBinaryTag; -import net.md_5.bungee.api.ChatColor; import net.minecraft.advancements.critereon.BlockPredicate; import net.minecraft.core.*; import net.minecraft.core.component.DataComponentMap; @@ -446,7 +444,7 @@ public String getDisplayName(ItemTag item) { } net.minecraft.world.item.ItemStack nmsItemStack = CraftItemStack.asNMSCopy(item.getItemStack()); Component nmsDisplayName = nmsItemStack.get(DataComponents.CUSTOM_NAME); - return FormattedTextHelper.stringify(Handler.componentToSpigot(nmsDisplayName)); + return Handler.stringifyNMSComponent(nmsDisplayName); } @Override @@ -458,7 +456,7 @@ public List getLore(ItemTag item) { ItemLore nmsLore = nmsItemStack.get(DataComponents.LORE); List outList = new ArrayList<>(nmsLore.lines().size()); for (Component nmsLoreLine : nmsLore.lines()) { - outList.add(FormattedTextHelper.stringify(Handler.componentToSpigot(nmsLoreLine))); + outList.add(Handler.stringifyNMSComponent(nmsLoreLine)); } return outList; } @@ -470,7 +468,7 @@ public void setDisplayName(ItemTag item, String name) { nmsItemStack.remove(DataComponents.CUSTOM_NAME); } else { - nmsItemStack.set(DataComponents.CUSTOM_NAME, Handler.componentToNMS(FormattedTextHelper.parse(name, ChatColor.WHITE))); + nmsItemStack.set(DataComponents.CUSTOM_NAME, Handler.parseNMSComponent(name, PaperAPITools.BaseColor.WHITE)); } item.setItemStack(CraftItemStack.asBukkitCopy(nmsItemStack)); } @@ -484,7 +482,7 @@ public void setLore(ItemTag item, List lore) { else { List nmsLore = new ArrayList<>(lore.size()); for (String loreLine : lore) { - nmsLore.add(Handler.componentToNMS(FormattedTextHelper.parse(loreLine, ChatColor.WHITE))); + nmsLore.add(Handler.parseNMSComponent(loreLine, PaperAPITools.BaseColor.WHITE)); } nmsItemStack.set(DataComponents.LORE, new ItemLore(nmsLore)); } diff --git a/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/helpers/PacketHelperImpl.java b/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/helpers/PacketHelperImpl.java index 9d9ce41a15..5028e0dbaf 100644 --- a/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/helpers/PacketHelperImpl.java +++ b/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/helpers/PacketHelperImpl.java @@ -7,14 +7,13 @@ import com.denizenscript.denizen.nms.v1_20.impl.SidebarImpl; import com.denizenscript.denizen.nms.v1_20.impl.network.handlers.DenizenNetworkManagerImpl; import com.denizenscript.denizen.scripts.commands.entity.TeleportCommand; -import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizen.utilities.Utilities; import com.denizenscript.denizen.utilities.maps.MapImage; import com.denizenscript.denizen.utilities.packets.NetworkInterceptHelper; import com.denizenscript.denizencore.objects.core.ColorTag; import com.denizenscript.denizencore.utilities.ReflectionHelper; import com.denizenscript.denizencore.utilities.debugging.Debug; -import net.md_5.bungee.api.ChatColor; import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.Packet; @@ -148,8 +147,8 @@ public void showBlockAction(Player player, Location location, int action, int st @Override public void showTabListHeaderFooter(Player player, String header, String footer) { - Component cHeader = Handler.componentToNMS(FormattedTextHelper.parse(header, ChatColor.WHITE)); - Component cFooter = Handler.componentToNMS(FormattedTextHelper.parse(footer, ChatColor.WHITE)); + Component cHeader = Handler.parseNMSComponent(header, PaperAPITools.BaseColor.WHITE); + Component cFooter = Handler.parseNMSComponent(footer, PaperAPITools.BaseColor.WHITE); send(player, new ClientboundTabListPacket(cHeader, cFooter)); } @@ -157,10 +156,10 @@ public void showTabListHeaderFooter(Player player, String header, String footer) public void showTitle(Player player, String title, String subtitle, int fadeInTicks, int stayTicks, int fadeOutTicks) { send(player, new ClientboundSetTitlesAnimationPacket(fadeInTicks, stayTicks, fadeOutTicks)); if (title != null) { - send(player, new ClientboundSetTitleTextPacket(Handler.componentToNMS(FormattedTextHelper.parse(title, ChatColor.WHITE)))); + send(player, new ClientboundSetTitleTextPacket(Handler.parseNMSComponent(title, PaperAPITools.BaseColor.WHITE))); } if (subtitle != null) { - send(player, new ClientboundSetSubtitleTextPacket(Handler.componentToNMS(FormattedTextHelper.parse(subtitle, ChatColor.WHITE)))); + send(player, new ClientboundSetSubtitleTextPacket(Handler.parseNMSComponent(subtitle, PaperAPITools.BaseColor.WHITE))); } } @@ -238,7 +237,7 @@ public void sendRename(Player player, Entity entity, String name, boolean listMo return; } List> list = List.of( - createEntityData(ENTITY_DATA_ACCESSOR_CUSTOM_NAME, Optional.of(Handler.componentToNMS(FormattedTextHelper.parse(name, ChatColor.WHITE)))), + createEntityData(ENTITY_DATA_ACCESSOR_CUSTOM_NAME, Optional.of(Handler.parseNMSComponent(name, PaperAPITools.BaseColor.WHITE))), createEntityData(ENTITY_DATA_ACCESSOR_CUSTOM_NAME_VISIBLE, true) ); send(player, new ClientboundSetEntityDataPacket(entity.getEntityId(), list)); diff --git a/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/helpers/PlayerHelperImpl.java b/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/helpers/PlayerHelperImpl.java index 2f0c9f0d10..8acf11433b 100644 --- a/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/helpers/PlayerHelperImpl.java +++ b/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/helpers/PlayerHelperImpl.java @@ -17,7 +17,7 @@ import com.denizenscript.denizen.objects.ItemTag; import com.denizenscript.denizen.objects.LocationTag; import com.denizenscript.denizen.objects.PlayerTag; -import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizen.utilities.entity.DenizenEntityType; import com.denizenscript.denizen.utilities.entity.FakeEntity; import com.denizenscript.denizencore.objects.Mechanism; @@ -26,7 +26,6 @@ import com.mojang.authlib.GameProfile; import com.mojang.authlib.properties.Property; import it.unimi.dsi.fastutil.ints.IntList; -import net.md_5.bungee.api.ChatColor; import net.minecraft.core.BlockPos; import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; @@ -366,7 +365,7 @@ public void setSkinLayers(Player player, byte flags) { @Override public void setBossBarTitle(BossBar bar, String title) { - ((CraftBossBar) bar).getHandle().name = Handler.componentToNMS(FormattedTextHelper.parse(title, ChatColor.WHITE)); + ((CraftBossBar) bar).getHandle().name = Handler.parseNMSComponent(title, PaperAPITools.BaseColor.WHITE); ((CraftBossBar) bar).getHandle().broadcast(ClientboundBossEventPacket::createUpdateNamePacket); } @@ -421,7 +420,7 @@ public void sendPlayerInfoAddPacket(Player player, EnumSet edit if (texture != null) { profile.getProperties().put("textures", new Property("textures", texture, signature)); } - ClientboundPlayerInfoUpdatePacket.Entry entry = new ClientboundPlayerInfoUpdatePacket.Entry(id, profile, listed, latency, gameMode == null ? null : GameType.byId(gameMode.getValue()), display == null ? null : Handler.componentToNMS(FormattedTextHelper.parse(display, ChatColor.WHITE)), null); + ClientboundPlayerInfoUpdatePacket.Entry entry = new ClientboundPlayerInfoUpdatePacket.Entry(id, profile, listed, latency, gameMode == null ? null : GameType.byId(gameMode.getValue()), display == null ? null : Handler.parseNMSComponent(display, PaperAPITools.BaseColor.WHITE), null); PacketHelperImpl.send(player, ProfileEditorImpl.createInfoPacket(actions, List.of(entry))); } diff --git a/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/impl/ProfileEditorImpl.java b/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/impl/ProfileEditorImpl.java index 7c911163f0..cc2ba96ae1 100644 --- a/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/impl/ProfileEditorImpl.java +++ b/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/impl/ProfileEditorImpl.java @@ -8,12 +8,11 @@ import com.denizenscript.denizen.nms.v1_20.helpers.PacketHelperImpl; import com.denizenscript.denizen.nms.v1_20.impl.network.handlers.DenizenNetworkManagerImpl; import com.denizenscript.denizen.scripts.commands.entity.RenameCommand; -import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizencore.utilities.ReflectionHelper; import com.denizenscript.denizencore.utilities.debugging.Debug; import com.mojang.authlib.GameProfile; import com.mojang.authlib.properties.Property; -import net.md_5.bungee.api.ChatColor; import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket; import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket; @@ -94,7 +93,7 @@ public static ClientboundPlayerInfoUpdatePacket processPlayerInfoUpdatePacket(De modifiedProfile.getProperties().putAll(Denizen.supportsPaper ? entry.profile().getProperties() : baseProfile.getProperties()); } String listRename = RenameCommand.getCustomNameFor(entry.profileId(), networkManager.player.getBukkitEntity(), true); - Component displayName = listRename != null ? Handler.componentToNMS(FormattedTextHelper.parse(listRename, ChatColor.WHITE)) : entry.displayName(); + Component displayName = listRename != null ? Handler.parseNMSComponent(listRename, PaperAPITools.BaseColor.WHITE) : entry.displayName(); ClientboundPlayerInfoUpdatePacket.Entry modifiedEntry = new ClientboundPlayerInfoUpdatePacket.Entry(entry.profileId(), modifiedProfile, entry.listed(), entry.latency(), entry.gameMode(), displayName, entry.chatSession()); modifiedEntries.add(modifiedEntry); } diff --git a/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/impl/SidebarImpl.java b/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/impl/SidebarImpl.java index 5a76a4a10e..37cc69310f 100644 --- a/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/impl/SidebarImpl.java +++ b/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/impl/SidebarImpl.java @@ -3,9 +3,8 @@ import com.denizenscript.denizen.nms.abstracts.Sidebar; import com.denizenscript.denizen.nms.v1_20.Handler; import com.denizenscript.denizen.nms.v1_20.helpers.PacketHelperImpl; -import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizencore.utilities.debugging.Debug; -import net.md_5.bungee.api.ChatColor; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.numbers.StyledFormat; import net.minecraft.network.protocol.game.ClientboundSetDisplayObjectivePacket; @@ -47,7 +46,7 @@ public class SidebarImpl extends Sidebar { public SidebarImpl(Player player) { super(player); - Component chatComponentTitle = Handler.componentToNMS(FormattedTextHelper.parse(title, ChatColor.WHITE)); + Component chatComponentTitle = Handler.parseNMSComponent(title, PaperAPITools.BaseColor.WHITE); this.obj1 = new Objective(dummyScoreboard, "dummy_1", dummyCriteria, chatComponentTitle, ObjectiveCriteria.RenderType.INTEGER, false, StyledFormat.SIDEBAR_DEFAULT); this.obj2 = new Objective(dummyScoreboard, "dummy_2", dummyCriteria, chatComponentTitle, ObjectiveCriteria.RenderType.INTEGER, false, StyledFormat.SIDEBAR_DEFAULT); } @@ -55,7 +54,7 @@ public SidebarImpl(Player player) { @Override protected void setDisplayName(String title) { if (this.obj1 != null) { - Component chatComponentTitle = Handler.componentToNMS(FormattedTextHelper.parse(title, ChatColor.WHITE)); + Component chatComponentTitle = Handler.parseNMSComponent(title, PaperAPITools.BaseColor.WHITE); this.obj1.setDisplayName(chatComponentTitle); this.obj2.setDisplayName(chatComponentTitle); } @@ -77,7 +76,7 @@ public void sendUpdate() { String lineId = ids[i]; PlayerTeam team = new PlayerTeam(dummyScoreboard, lineId); team.getPlayers().add(lineId); - team.setPlayerPrefix(Handler.componentToNMS(FormattedTextHelper.parse(line, ChatColor.WHITE))); + team.setPlayerPrefix(Handler.parseNMSComponent(line, PaperAPITools.BaseColor.WHITE)); generatedTeams.add(team); PacketHelperImpl.send(player, ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(team, true)); PacketHelperImpl.send(player, new ClientboundSetScorePacket(lineId, obj1.getName(), this.scores[i], Optional.empty(), Optional.of(StyledFormat.SIDEBAR_DEFAULT))); diff --git a/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/impl/network/handlers/packet/EntityMetadataPacketHandlers.java b/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/impl/network/handlers/packet/EntityMetadataPacketHandlers.java index 40cf0c42af..f6ca91442e 100644 --- a/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/impl/network/handlers/packet/EntityMetadataPacketHandlers.java +++ b/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/impl/network/handlers/packet/EntityMetadataPacketHandlers.java @@ -7,9 +7,8 @@ import com.denizenscript.denizen.scripts.commands.entity.InvisibleCommand; import com.denizenscript.denizen.scripts.commands.entity.RenameCommand; import com.denizenscript.denizen.scripts.commands.entity.SneakCommand; -import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizencore.utilities.debugging.Debug; -import net.md_5.bungee.api.ChatColor; import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.game.ClientGamePacketListener; import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket; @@ -61,7 +60,7 @@ else if (nameToApply == null || (dataValue.id() != 2 && dataValue.id() != 3)) { data.add(SynchedEntityData.DataValue.create(PacketHelperImpl.ENTITY_DATA_ACCESSOR_FLAGS, flags)); } if (nameToApply != null) { - data.add(SynchedEntityData.DataValue.create(PacketHelperImpl.ENTITY_DATA_ACCESSOR_CUSTOM_NAME, Optional.of(Handler.componentToNMS(FormattedTextHelper.parse(nameToApply, ChatColor.WHITE))))); + data.add(SynchedEntityData.DataValue.create(PacketHelperImpl.ENTITY_DATA_ACCESSOR_CUSTOM_NAME, Optional.of(Handler.parseNMSComponent(nameToApply, PaperAPITools.BaseColor.WHITE)))); data.add(SynchedEntityData.DataValue.create(PacketHelperImpl.ENTITY_DATA_ACCESSOR_CUSTOM_NAME_VISIBLE, true)); } return new ClientboundSetEntityDataPacket(metadataPacket.id(), data); diff --git a/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/impl/network/handlers/packet/TablistUpdateEventPacketHandlers.java b/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/impl/network/handlers/packet/TablistUpdateEventPacketHandlers.java index 41695a47a6..da9fde198d 100644 --- a/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/impl/network/handlers/packet/TablistUpdateEventPacketHandlers.java +++ b/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/impl/network/handlers/packet/TablistUpdateEventPacketHandlers.java @@ -4,13 +4,12 @@ import com.denizenscript.denizen.nms.v1_20.Handler; import com.denizenscript.denizen.nms.v1_20.impl.ProfileEditorImpl; import com.denizenscript.denizen.nms.v1_20.impl.network.handlers.DenizenNetworkManagerImpl; -import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizencore.utilities.CoreUtilities; import com.denizenscript.denizencore.utilities.debugging.Debug; import com.google.common.base.Joiner; import com.mojang.authlib.GameProfile; import com.mojang.authlib.properties.Property; -import net.md_5.bungee.api.ChatColor; import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.game.ClientGamePacketListener; import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket; @@ -80,7 +79,7 @@ public static Packet processTablistPacket(DenizenNetwo } String modeText = update.gameMode() == null ? null : update.gameMode().name(); PlayerReceivesTablistUpdateScriptEvent.TabPacketData data = new PlayerReceivesTablistUpdateScriptEvent.TabPacketData(mode, profile.getId(), update.listed(), profile.getName(), - update.displayName() == null ? null : FormattedTextHelper.stringify(Handler.componentToSpigot(update.displayName())), modeText, texture, signature, update.latency()); + update.displayName() == null ? null : Handler.stringifyNMSComponent(update.displayName()), modeText, texture, signature, update.latency()); PlayerReceivesTablistUpdateScriptEvent.fire(networkManager.player.getBukkitEntity(), data); if (data.modified) { if (!isOverriding) { @@ -98,7 +97,7 @@ public static Packet processTablistPacket(DenizenNetwo newProfile.getProperties().put("textures", new Property("textures", data.texture, data.signature)); } ClientboundPlayerInfoUpdatePacket.Entry entry = new ClientboundPlayerInfoUpdatePacket.Entry(newProfile.getId(), newProfile, data.isListed, data.latency, data.gamemode == null ? null : GameType.byName(CoreUtilities.toLowerCase(data.gamemode)), - data.display == null ? null : Handler.componentToNMS(FormattedTextHelper.parse(data.display, ChatColor.WHITE)), update.chatSession()); + data.display == null ? null : Handler.parseNMSComponent(data.display, PaperAPITools.BaseColor.WHITE), update.chatSession()); networkManager.oldManager.send(ProfileEditorImpl.createInfoPacket(infoPacket.actions(), Collections.singletonList(entry))); } } diff --git a/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/Handler.java b/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/Handler.java index 1cd431f486..2dbfa250f7 100644 --- a/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/Handler.java +++ b/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/Handler.java @@ -16,7 +16,6 @@ import com.denizenscript.denizen.objects.LocationTag; import com.denizenscript.denizen.objects.MaterialTag; import com.denizenscript.denizen.objects.properties.item.ItemRawNBT; -import com.denizenscript.denizen.utilities.FormattedTextHelper; import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; @@ -34,8 +33,6 @@ import com.mojang.authlib.yggdrasil.ProfileResult; import com.mojang.serialization.DynamicOps; import net.kyori.adventure.nbt.CompoundBinaryTag; -import net.md_5.bungee.api.ChatColor; -import net.md_5.bungee.api.chat.BaseComponent; import net.minecraft.SharedConstants; import net.minecraft.core.BlockPos; import net.minecraft.core.Holder; @@ -115,7 +112,7 @@ public Handler() { enchantmentHelper = new EnchantmentHelperImpl(); registerConversion(ItemTag.class, ItemStack.class, item -> CraftItemStack.asNMSCopy(item.getItemStack())); - registerConversion(ElementTag.class, Component.class, element -> componentToNMS(FormattedTextHelper.parse(element.asString(), ChatColor.WHITE))); + registerConversion(ElementTag.class, Component.class, element -> parseNMSComponent(element.asString(), PaperAPITools.BaseColor.WHITE)); registerConversion(MaterialTag.class, BlockState.class, material -> ((CraftBlockData) material.getModernData()).getState()); registerConversion(LocationTag.class, Rotations.class, location -> new Rotations((float) location.getX(), (float) location.getY(), (float) location.getZ())); registerConversion(LocationTag.class, BlockPos.class, CraftLocation::toBlockPosition); @@ -247,7 +244,7 @@ else if (MINECRAFT_INVENTORY.isInstance(nms)) { public void setInventoryTitle(InventoryView view, String title) { AbstractContainerMenu menu = ((CraftInventoryView) view).getHandle(); try { - AbstractContainerMenu_title_SETTER.invoke(menu, componentToNMS(FormattedTextHelper.parse(title, ChatColor.DARK_GRAY))); + AbstractContainerMenu_title_SETTER.invoke(menu, parseNMSComponent(title, PaperAPITools.BaseColor.DARK_GRAY)); } catch (Throwable ex) { Debug.echoError(ex); @@ -366,20 +363,6 @@ public void setBossbarUUID(BossBar bar, UUID id) { } } - public static BaseComponent[] componentToSpigot(Component nms) { - if (nms == null) { - return null; - } - return FormattedTextHelper.parseJson(CraftChatMessage.toJSON(nms)); - } - - public static Component componentToNMS(BaseComponent[] spigot) { - if (spigot == null) { - return null; - } - return CraftChatMessage.fromJSONOrNull(FormattedTextHelper.componentToJson(spigot)); - } - public static final MethodHandle TAG_VALUE_OUTPUT_CONSTRUCTOR = ReflectionHelper.getConstructor(TagValueOutput.class, ProblemReporter.class, DynamicOps.class, CompoundTag.class); public static CompoundTag useValueOutput(Consumer handler) { @@ -422,4 +405,18 @@ private static void handleProblems(ProblemReporter.Collector nmsProblemReporter) public String updateLegacyName(Class type, String legacyName) { return FieldRename.rename(ApiVersion.FIELD_NAME_PARITY, DebugInternals.getFullClassNameOpti(type).replace('.', '/'), legacyName); } + + public static String stringifyNMSComponent(Component nms) { + if (nms == null) { + return null; + } + return PaperAPITools.instance.parseJsonToText(CraftChatMessage.toJSON(nms)); + } + + public static Component parseNMSComponent(String formattedText, PaperAPITools.BaseColor baseColor) { + if (formattedText == null) { + return null; + } + return CraftChatMessage.fromJSON(PaperAPITools.instance.parseTextToJson(formattedText, baseColor)); + } } diff --git a/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/helpers/AdvancementHelperImpl.java b/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/helpers/AdvancementHelperImpl.java index 0b2ca9366e..a7129e3638 100644 --- a/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/helpers/AdvancementHelperImpl.java +++ b/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/helpers/AdvancementHelperImpl.java @@ -2,9 +2,8 @@ import com.denizenscript.denizen.nms.interfaces.AdvancementHelper; import com.denizenscript.denizen.nms.v1_21.Handler; -import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.google.common.collect.ImmutableMap; -import net.md_5.bungee.api.ChatColor; import net.minecraft.advancements.*; import net.minecraft.advancements.critereon.ImpossibleTrigger; import net.minecraft.core.ClientAsset; @@ -175,7 +174,7 @@ private static AdvancementHolder asNMSCopy(com.denizenscript.denizen.nms.util.Ad ? getNMSAdvancementManager().advancements.get(CraftNamespacedKey.toMinecraft(advancement.parent)) : null; DisplayInfo display = new DisplayInfo(CraftItemStack.asNMSCopy(advancement.icon), - Handler.componentToNMS(FormattedTextHelper.parse(advancement.title, ChatColor.WHITE)), Handler.componentToNMS(FormattedTextHelper.parse(advancement.description, ChatColor.WHITE)), + Handler.parseNMSComponent(advancement.title, PaperAPITools.BaseColor.WHITE), Handler.parseNMSComponent(advancement.description, PaperAPITools.BaseColor.WHITE), Optional.ofNullable(advancement.background).map(CraftNamespacedKey::toMinecraft).map(ClientAsset::new), AdvancementType.valueOf(advancement.frame.name()), advancement.toast, advancement.announceToChat, advancement.hidden); display.setLocation(advancement.xOffset, advancement.yOffset); diff --git a/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/helpers/ItemHelperImpl.java b/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/helpers/ItemHelperImpl.java index 14298cc907..49152cbe2e 100644 --- a/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/helpers/ItemHelperImpl.java +++ b/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/helpers/ItemHelperImpl.java @@ -8,7 +8,6 @@ import com.denizenscript.denizen.objects.ItemTag; import com.denizenscript.denizen.objects.properties.item.ItemComponentsPatch; import com.denizenscript.denizen.objects.properties.item.ItemRawNBT; -import com.denizenscript.denizen.utilities.FormattedTextHelper; import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.objects.core.MapTag; @@ -23,7 +22,6 @@ import com.mojang.serialization.JsonOps; import net.kyori.adventure.nbt.BinaryTag; import net.kyori.adventure.nbt.CompoundBinaryTag; -import net.md_5.bungee.api.ChatColor; import net.minecraft.advancements.critereon.BlockPredicate; import net.minecraft.advancements.critereon.DataComponentMatchers; import net.minecraft.core.*; @@ -556,7 +554,7 @@ public String getDisplayName(ItemTag item) { } net.minecraft.world.item.ItemStack nmsItemStack = CraftItemStack.asNMSCopy(item.getItemStack()); Component nmsDisplayName = nmsItemStack.get(DataComponents.CUSTOM_NAME); - return FormattedTextHelper.stringify(Handler.componentToSpigot(nmsDisplayName)); + return Handler.stringifyNMSComponent(nmsDisplayName); } @Override @@ -568,7 +566,7 @@ public List getLore(ItemTag item) { ItemLore nmsLore = nmsItemStack.get(DataComponents.LORE); List outList = new ArrayList<>(nmsLore.lines().size()); for (Component nmsLoreLine : nmsLore.lines()) { - outList.add(FormattedTextHelper.stringify(Handler.componentToSpigot(nmsLoreLine))); + outList.add(Handler.stringifyNMSComponent(nmsLoreLine)); } return outList; } @@ -580,7 +578,7 @@ public void setDisplayName(ItemTag item, String name) { nmsItemStack.remove(DataComponents.CUSTOM_NAME); } else { - nmsItemStack.set(DataComponents.CUSTOM_NAME, Handler.componentToNMS(FormattedTextHelper.parse(name, ChatColor.WHITE))); + nmsItemStack.set(DataComponents.CUSTOM_NAME, Handler.parseNMSComponent(name, PaperAPITools.BaseColor.WHITE)); } item.setItemStack(CraftItemStack.asBukkitCopy(nmsItemStack)); } @@ -594,7 +592,7 @@ public void setLore(ItemTag item, List lore) { else { List nmsLore = new ArrayList<>(lore.size()); for (String loreLine : lore) { - nmsLore.add(Handler.componentToNMS(FormattedTextHelper.parse(loreLine, ChatColor.WHITE))); + nmsLore.add(Handler.parseNMSComponent(loreLine, PaperAPITools.BaseColor.WHITE)); } nmsItemStack.set(DataComponents.LORE, new ItemLore(nmsLore)); } diff --git a/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/helpers/PacketHelperImpl.java b/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/helpers/PacketHelperImpl.java index 0156bee78a..6501710d7b 100644 --- a/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/helpers/PacketHelperImpl.java +++ b/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/helpers/PacketHelperImpl.java @@ -8,14 +8,13 @@ import com.denizenscript.denizen.nms.v1_21.impl.network.handlers.DenizenNetworkManagerImpl; import com.denizenscript.denizen.objects.LocationTag; import com.denizenscript.denizen.scripts.commands.entity.TeleportCommand; -import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizen.utilities.Utilities; import com.denizenscript.denizen.utilities.maps.MapImage; import com.denizenscript.denizen.utilities.packets.NetworkInterceptHelper; import com.denizenscript.denizencore.objects.core.ColorTag; import com.denizenscript.denizencore.utilities.ReflectionHelper; import com.denizenscript.denizencore.utilities.debugging.Debug; -import net.md_5.bungee.api.ChatColor; import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.Packet; @@ -153,8 +152,8 @@ public void showBlockAction(Player player, Location location, int action, int st @Override public void showTabListHeaderFooter(Player player, String header, String footer) { - Component cHeader = Handler.componentToNMS(FormattedTextHelper.parse(header, ChatColor.WHITE)); - Component cFooter = Handler.componentToNMS(FormattedTextHelper.parse(footer, ChatColor.WHITE)); + Component cHeader = Handler.parseNMSComponent(header, PaperAPITools.BaseColor.WHITE); + Component cFooter = Handler.parseNMSComponent(footer, PaperAPITools.BaseColor.WHITE); send(player, new ClientboundTabListPacket(cHeader, cFooter)); } @@ -162,10 +161,10 @@ public void showTabListHeaderFooter(Player player, String header, String footer) public void showTitle(Player player, String title, String subtitle, int fadeInTicks, int stayTicks, int fadeOutTicks) { send(player, new ClientboundSetTitlesAnimationPacket(fadeInTicks, stayTicks, fadeOutTicks)); if (title != null) { - send(player, new ClientboundSetTitleTextPacket(Handler.componentToNMS(FormattedTextHelper.parse(title, ChatColor.WHITE)))); + send(player, new ClientboundSetTitleTextPacket(Handler.parseNMSComponent(title, PaperAPITools.BaseColor.WHITE))); } if (subtitle != null) { - send(player, new ClientboundSetSubtitleTextPacket(Handler.componentToNMS(FormattedTextHelper.parse(subtitle, ChatColor.WHITE)))); + send(player, new ClientboundSetSubtitleTextPacket(Handler.parseNMSComponent(subtitle, PaperAPITools.BaseColor.WHITE))); } } @@ -246,7 +245,7 @@ public void sendRename(Player player, Entity entity, String name, boolean listMo return; } List> list = List.of( - createEntityData(ENTITY_DATA_ACCESSOR_CUSTOM_NAME, Optional.of(Handler.componentToNMS(FormattedTextHelper.parse(name, ChatColor.WHITE)))), + createEntityData(ENTITY_DATA_ACCESSOR_CUSTOM_NAME, Optional.of(Handler.parseNMSComponent(name, PaperAPITools.BaseColor.WHITE))), createEntityData(ENTITY_DATA_ACCESSOR_CUSTOM_NAME_VISIBLE, true) ); send(player, new ClientboundSetEntityDataPacket(entity.getEntityId(), list)); diff --git a/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/helpers/PlayerHelperImpl.java b/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/helpers/PlayerHelperImpl.java index c3ee8fcced..e825520d53 100644 --- a/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/helpers/PlayerHelperImpl.java +++ b/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/helpers/PlayerHelperImpl.java @@ -17,7 +17,7 @@ import com.denizenscript.denizen.objects.ItemTag; import com.denizenscript.denizen.objects.LocationTag; import com.denizenscript.denizen.objects.PlayerTag; -import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizen.utilities.entity.DenizenEntityType; import com.denizenscript.denizen.utilities.entity.FakeEntity; import com.denizenscript.denizencore.objects.Mechanism; @@ -26,8 +26,6 @@ import com.mojang.authlib.GameProfile; import com.mojang.authlib.properties.Property; import it.unimi.dsi.fastutil.ints.IntList; -import net.md_5.bungee.api.ChatColor; -import net.minecraft.core.BlockPos; import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.protocol.common.ClientboundUpdateTagsPacket; @@ -377,7 +375,7 @@ public void setSkinLayers(Player player, byte flags) { @Override public void setBossBarTitle(BossBar bar, String title) { - ((CraftBossBar) bar).getHandle().name = Handler.componentToNMS(FormattedTextHelper.parse(title, ChatColor.WHITE)); + ((CraftBossBar) bar).getHandle().name = Handler.parseNMSComponent(title, PaperAPITools.BaseColor.WHITE); ((CraftBossBar) bar).getHandle().broadcast(ClientboundBossEventPacket::createUpdateNamePacket); } @@ -435,7 +433,7 @@ public void sendPlayerInfoAddPacket(Player player, EnumSet edit profile.getProperties().put("textures", new Property("textures", texture, signature)); } // TODO: 1.21.3: Player list order and hat visibility support - ClientboundPlayerInfoUpdatePacket.Entry entry = new ClientboundPlayerInfoUpdatePacket.Entry(id, profile, listed, latency, gameMode == null ? null : GameType.byId(gameMode.getValue()), display == null ? null : Handler.componentToNMS(FormattedTextHelper.parse(display, ChatColor.WHITE)), true, player.getPlayerListOrder(), null); + ClientboundPlayerInfoUpdatePacket.Entry entry = new ClientboundPlayerInfoUpdatePacket.Entry(id, profile, listed, latency, gameMode == null ? null : GameType.byId(gameMode.getValue()), display == null ? null : Handler.parseNMSComponent(display, PaperAPITools.BaseColor.WHITE), true, player.getPlayerListOrder(), null); PacketHelperImpl.send(player, ProfileEditorImpl.createInfoPacket(actions, List.of(entry))); } diff --git a/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/impl/ProfileEditorImpl.java b/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/impl/ProfileEditorImpl.java index 2f25a8878d..2cf2538dba 100644 --- a/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/impl/ProfileEditorImpl.java +++ b/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/impl/ProfileEditorImpl.java @@ -8,12 +8,11 @@ import com.denizenscript.denizen.nms.v1_21.helpers.PacketHelperImpl; import com.denizenscript.denizen.nms.v1_21.impl.network.handlers.DenizenNetworkManagerImpl; import com.denizenscript.denizen.scripts.commands.entity.RenameCommand; -import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizencore.utilities.ReflectionHelper; import com.denizenscript.denizencore.utilities.debugging.Debug; import com.mojang.authlib.GameProfile; import com.mojang.authlib.properties.Property; -import net.md_5.bungee.api.ChatColor; import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket; import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket; @@ -97,7 +96,7 @@ public static ClientboundPlayerInfoUpdatePacket processPlayerInfoUpdatePacket(De modifiedProfile.getProperties().putAll(Denizen.supportsPaper ? entry.profile().getProperties() : baseProfile.getProperties()); } String listRename = RenameCommand.getCustomNameFor(entry.profileId(), networkManager.player.getBukkitEntity(), true); - Component displayName = listRename != null ? Handler.componentToNMS(FormattedTextHelper.parse(listRename, ChatColor.WHITE)) : entry.displayName(); + Component displayName = listRename != null ? Handler.parseNMSComponent(listRename, PaperAPITools.BaseColor.WHITE) : entry.displayName(); ClientboundPlayerInfoUpdatePacket.Entry modifiedEntry = new ClientboundPlayerInfoUpdatePacket.Entry(entry.profileId(), modifiedProfile, entry.listed(), entry.latency(), entry.gameMode(), displayName, entry.showHat(), entry.listOrder(), entry.chatSession()); modifiedEntries.add(modifiedEntry); } diff --git a/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/impl/SidebarImpl.java b/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/impl/SidebarImpl.java index e765aa1487..36322954cb 100644 --- a/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/impl/SidebarImpl.java +++ b/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/impl/SidebarImpl.java @@ -3,9 +3,8 @@ import com.denizenscript.denizen.nms.abstracts.Sidebar; import com.denizenscript.denizen.nms.v1_21.Handler; import com.denizenscript.denizen.nms.v1_21.helpers.PacketHelperImpl; -import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizencore.utilities.debugging.Debug; -import net.md_5.bungee.api.ChatColor; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.numbers.StyledFormat; import net.minecraft.network.protocol.game.ClientboundSetDisplayObjectivePacket; @@ -47,7 +46,7 @@ public class SidebarImpl extends Sidebar { public SidebarImpl(Player player) { super(player); - Component chatComponentTitle = Handler.componentToNMS(FormattedTextHelper.parse(title, ChatColor.WHITE)); + Component chatComponentTitle = Handler.parseNMSComponent(title, PaperAPITools.BaseColor.WHITE); this.obj1 = new Objective(dummyScoreboard, "dummy_1", dummyCriteria, chatComponentTitle, ObjectiveCriteria.RenderType.INTEGER, false, StyledFormat.SIDEBAR_DEFAULT); this.obj2 = new Objective(dummyScoreboard, "dummy_2", dummyCriteria, chatComponentTitle, ObjectiveCriteria.RenderType.INTEGER, false, StyledFormat.SIDEBAR_DEFAULT); } @@ -55,7 +54,7 @@ public SidebarImpl(Player player) { @Override protected void setDisplayName(String title) { if (this.obj1 != null) { - Component chatComponentTitle = Handler.componentToNMS(FormattedTextHelper.parse(title, ChatColor.WHITE)); + Component chatComponentTitle = Handler.parseNMSComponent(title, PaperAPITools.BaseColor.WHITE); this.obj1.setDisplayName(chatComponentTitle); this.obj2.setDisplayName(chatComponentTitle); } @@ -77,7 +76,7 @@ public void sendUpdate() { String lineId = ids[i]; PlayerTeam team = new PlayerTeam(dummyScoreboard, lineId); team.getPlayers().add(lineId); - team.setPlayerPrefix(Handler.componentToNMS(FormattedTextHelper.parse(line, ChatColor.WHITE))); + team.setPlayerPrefix(Handler.parseNMSComponent(line, PaperAPITools.BaseColor.WHITE)); generatedTeams.add(team); PacketHelperImpl.send(player, ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(team, true)); PacketHelperImpl.send(player, new ClientboundSetScorePacket(lineId, obj1.getName(), this.scores[i], Optional.empty(), Optional.of(StyledFormat.SIDEBAR_DEFAULT))); diff --git a/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/impl/network/handlers/packet/EntityMetadataPacketHandlers.java b/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/impl/network/handlers/packet/EntityMetadataPacketHandlers.java index ee538c2b83..a25e8e87d2 100644 --- a/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/impl/network/handlers/packet/EntityMetadataPacketHandlers.java +++ b/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/impl/network/handlers/packet/EntityMetadataPacketHandlers.java @@ -7,9 +7,8 @@ import com.denizenscript.denizen.scripts.commands.entity.InvisibleCommand; import com.denizenscript.denizen.scripts.commands.entity.RenameCommand; import com.denizenscript.denizen.scripts.commands.entity.SneakCommand; -import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizencore.utilities.debugging.Debug; -import net.md_5.bungee.api.ChatColor; import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.game.ClientGamePacketListener; import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket; @@ -61,7 +60,7 @@ else if (nameToApply == null || (dataValue.id() != 2 && dataValue.id() != 3)) { data.add(SynchedEntityData.DataValue.create(PacketHelperImpl.ENTITY_DATA_ACCESSOR_FLAGS, flags)); } if (nameToApply != null) { - data.add(SynchedEntityData.DataValue.create(PacketHelperImpl.ENTITY_DATA_ACCESSOR_CUSTOM_NAME, Optional.of(Handler.componentToNMS(FormattedTextHelper.parse(nameToApply, ChatColor.WHITE))))); + data.add(SynchedEntityData.DataValue.create(PacketHelperImpl.ENTITY_DATA_ACCESSOR_CUSTOM_NAME, Optional.of(Handler.parseNMSComponent(nameToApply, PaperAPITools.BaseColor.WHITE)))); data.add(SynchedEntityData.DataValue.create(PacketHelperImpl.ENTITY_DATA_ACCESSOR_CUSTOM_NAME_VISIBLE, true)); } return new ClientboundSetEntityDataPacket(metadataPacket.id(), data); diff --git a/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/impl/network/handlers/packet/TablistUpdateEventPacketHandlers.java b/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/impl/network/handlers/packet/TablistUpdateEventPacketHandlers.java index a23de7900f..79ef4b71f6 100644 --- a/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/impl/network/handlers/packet/TablistUpdateEventPacketHandlers.java +++ b/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/impl/network/handlers/packet/TablistUpdateEventPacketHandlers.java @@ -4,13 +4,12 @@ import com.denizenscript.denizen.nms.v1_21.Handler; import com.denizenscript.denizen.nms.v1_21.impl.ProfileEditorImpl; import com.denizenscript.denizen.nms.v1_21.impl.network.handlers.DenizenNetworkManagerImpl; -import com.denizenscript.denizen.utilities.FormattedTextHelper; +import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizencore.utilities.CoreUtilities; import com.denizenscript.denizencore.utilities.debugging.Debug; import com.google.common.base.Joiner; import com.mojang.authlib.GameProfile; import com.mojang.authlib.properties.Property; -import net.md_5.bungee.api.ChatColor; import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.game.ClientGamePacketListener; import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket; @@ -80,7 +79,7 @@ public static Packet processTablistPacket(DenizenNetwo } String modeText = update.gameMode() == null ? null : update.gameMode().name(); PlayerReceivesTablistUpdateScriptEvent.TabPacketData data = new PlayerReceivesTablistUpdateScriptEvent.TabPacketData(mode, profile.getId(), update.listed(), profile.getName(), - update.displayName() == null ? null : FormattedTextHelper.stringify(Handler.componentToSpigot(update.displayName())), modeText, texture, signature, update.latency()); + update.displayName() == null ? null : Handler.stringifyNMSComponent(update.displayName()), modeText, texture, signature, update.latency()); PlayerReceivesTablistUpdateScriptEvent.fire(networkManager.player.getBukkitEntity(), data); if (data.modified) { if (!isOverriding) { @@ -98,7 +97,7 @@ public static Packet processTablistPacket(DenizenNetwo newProfile.getProperties().put("textures", new Property("textures", data.texture, data.signature)); } ClientboundPlayerInfoUpdatePacket.Entry entry = new ClientboundPlayerInfoUpdatePacket.Entry(newProfile.getId(), newProfile, data.isListed, data.latency, data.gamemode == null ? null : GameType.byName(CoreUtilities.toLowerCase(data.gamemode)), - data.display == null ? null : Handler.componentToNMS(FormattedTextHelper.parse(data.display, ChatColor.WHITE)), update.showHat(), update.listOrder(), update.chatSession()); + data.display == null ? null : Handler.parseNMSComponent(data.display, PaperAPITools.BaseColor.WHITE), update.showHat(), update.listOrder(), update.chatSession()); networkManager.oldManager.send(ProfileEditorImpl.createInfoPacket(infoPacket.actions(), Collections.singletonList(entry))); } } From 6899b5feae12e516a8d8b0021b0541f76c7be284 Mon Sep 17 00:00:00 2001 From: Aya <31237389+tal5@users.noreply.github.com> Date: Sun, 14 Sep 2025 21:48:34 +0100 Subject: [PATCH 22/24] Move alternate debug trimming --- .../main/java/com/denizenscript/denizen/paper/PaperModule.java | 3 +++ plugin/src/main/java/com/denizenscript/denizen/Denizen.java | 2 -- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/PaperModule.java b/paper/src/main/java/com/denizenscript/denizen/paper/PaperModule.java index 1f96ee702a..a7c00dd7e7 100644 --- a/paper/src/main/java/com/denizenscript/denizen/paper/PaperModule.java +++ b/paper/src/main/java/com/denizenscript/denizen/paper/PaperModule.java @@ -10,11 +10,13 @@ import com.denizenscript.denizen.paper.properties.*; import com.denizenscript.denizen.paper.tags.PaperTagBase; import com.denizenscript.denizen.paper.tags.TextFormattingTags; +import com.denizenscript.denizen.paper.utilities.FormattedTextHelper; import com.denizenscript.denizen.paper.utilities.PaperAPIToolsImpl; import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizencore.events.ScriptEvent; import com.denizenscript.denizencore.objects.properties.PropertyParser; import com.denizenscript.denizencore.utilities.debugging.Debug; +import com.denizenscript.denizencore.utilities.debugging.DebugInternals; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import org.bukkit.Bukkit; @@ -138,6 +140,7 @@ public static void init() { // Other helpers Bukkit.getPluginManager().registerEvents(new PaperEventHelpers(), Denizen.getInstance()); + DebugInternals.alternateTrimLogic = FormattedTextHelper::bukkitSafeDebugTrimming; PaperAPITools.instance = new PaperAPIToolsImpl(); PacketOutChat.convertComponentToJsonString = (o) -> componentToJson((Component) o); } diff --git a/plugin/src/main/java/com/denizenscript/denizen/Denizen.java b/plugin/src/main/java/com/denizenscript/denizen/Denizen.java index 9060b805b9..334e684df3 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/Denizen.java +++ b/plugin/src/main/java/com/denizenscript/denizen/Denizen.java @@ -51,7 +51,6 @@ import com.denizenscript.denizencore.utilities.CoreConfiguration; import com.denizenscript.denizencore.utilities.CoreUtilities; import com.denizenscript.denizencore.utilities.debugging.Debug; -import com.denizenscript.denizencore.utilities.debugging.DebugInternals; import com.denizenscript.denizencore.utilities.debugging.StrongWarning; import com.denizenscript.denizencore.utilities.text.ConfigUpdater; import org.bukkit.Bukkit; @@ -132,7 +131,6 @@ public void onEnable() { if (!PlayerFlagHandler.dataFolder.exists()) { PlayerFlagHandler.dataFolder.mkdir(); } - DebugInternals.alternateTrimLogic = FormattedTextHelper::bukkitSafeDebugTrimming; String javaVersion = System.getProperty("java.version"); Debug.log("Running on java version: " + javaVersion); if (javaVersion.startsWith("8") || javaVersion.startsWith("1.8") || javaVersion.startsWith("9") || javaVersion.startsWith("1.9") From e1df24893dd6043084807e7edb4055db5e57fc09 Mon Sep 17 00:00:00 2001 From: Aya <31237389+tal5@users.noreply.github.com> Date: Sun, 14 Sep 2025 21:54:46 +0100 Subject: [PATCH 23/24] Remove old impls --- .../utilities/FormattedTextHelper.java | 893 ------------------ .../denizen/utilities/HoverFormatHelper.java | 238 ----- 2 files changed, 1131 deletions(-) delete mode 100644 plugin/src/main/java/com/denizenscript/denizen/utilities/FormattedTextHelper.java delete mode 100644 plugin/src/main/java/com/denizenscript/denizen/utilities/HoverFormatHelper.java diff --git a/plugin/src/main/java/com/denizenscript/denizen/utilities/FormattedTextHelper.java b/plugin/src/main/java/com/denizenscript/denizen/utilities/FormattedTextHelper.java deleted file mode 100644 index 67392b5fa9..0000000000 --- a/plugin/src/main/java/com/denizenscript/denizen/utilities/FormattedTextHelper.java +++ /dev/null @@ -1,893 +0,0 @@ -package com.denizenscript.denizen.utilities; - -import com.denizenscript.denizen.nms.NMSHandler; -import com.denizenscript.denizen.nms.NMSVersion; -import com.denizenscript.denizen.objects.properties.bukkit.BukkitElementExtensions; -import com.denizenscript.denizencore.objects.core.ColorTag; -import com.denizenscript.denizencore.objects.core.ElementTag; -import com.denizenscript.denizencore.objects.core.ListTag; -import com.denizenscript.denizencore.objects.core.MapTag; -import com.denizenscript.denizencore.utilities.AsciiMatcher; -import com.denizenscript.denizencore.utilities.CoreConfiguration; -import com.denizenscript.denizencore.utilities.CoreUtilities; -import com.denizenscript.denizencore.utilities.ReflectionHelper; -import com.denizenscript.denizencore.utilities.debugging.Debug; -import com.google.gson.Gson; -import net.md_5.bungee.api.ChatColor; -import net.md_5.bungee.api.chat.*; -import net.md_5.bungee.chat.ChatVersion; -import net.md_5.bungee.chat.ComponentSerializer; -import net.md_5.bungee.chat.VersionedComponentSerializer; - -import java.util.List; - -public class FormattedTextHelper { - - // <--[language] - // @name Denizen Text Formatting - // @group Denizen Magic - // @description - // Denizen provides a variety of special chat format options like "on_hover" and "on_click". - // These options exist within Denizen and do not appear in the historical Minecraft legacy chat format that most plugins and systems read. - // That legacy system has 16 colors (0-9, A-F) and a few toggleable formats (bold, italic, etc). It does not contain anything that needs more than just an on/off. - // - // Modern Minecraft, however, supports a JSON based "raw" message format that can do click events, hover events, full RGB colors, etc. - // - // Denizen therefore has its own internal system that works like the legacy format system, but also supports the new options normally only available as 'raw JSON'. - // - // Because it is entirely processed within Denizen, these options only work within Denizen, when performing actions that support raw JSON input. - // This magic tool exists to let you write messages without having to write the messy JSON. - // - // Be aware that many inputs do not support raw JSON, and as such are limited only the historical Minecraft legacy format. - // Also be aware that click events, hover events, etc. are exclusively limited to the chat bar and the pages of books, as you cannot mouse over anything else. - // - // Also note that RGB colors use a format that Spigot invented, meaning they will work in places that use Spigot's parser OR Denizen's version, but nowhere that uses the vanilla format still. - // - // Thanks to Paper's implementation of component APIs where Spigot was too lazy to, Paper servers have advanced text formatting available in more areas. - // --> - - public static AsciiMatcher needsEscapeMatcher = new AsciiMatcher("&;[]"); - - public static String escape(String input) { - if (needsEscapeMatcher.containsAnyMatch(input)) { - input = input.replace("&", "&").replace(";", "&sc").replace("[", "&lb").replace("]", "&rb").replace("\n", "&nl"); - } - return input.replace(String.valueOf(ChatColor.COLOR_CHAR), "&ss"); - } - - public static String unescape(String input) { - if (input.indexOf('&') != -1) { - return input.replace("&sc", ";").replace("&lb", "[").replace("&rb", "]").replace("&nl", "\n").replace("&ss", String.valueOf(ChatColor.COLOR_CHAR)).replace("&", "&"); - } - return input; - } - - public static boolean hasRootFormat(BaseComponent component) { - if (component == null) { - return false; - } - if (component.hasFormatting()) { - return true; - } - if (!(component instanceof TextComponent)) { - return false; - } - if (!((TextComponent) component).getText().isEmpty()) { - return false; - } - List extra = component.getExtra(); - if (extra == null || extra.isEmpty()) { - return false; - } - return hasRootFormat(extra.get(0)); - } - - public static String stringify(BaseComponent[] components) { - if (components == null) { - return null; - } - if (components.length == 0) { - return ""; - } - StringBuilder builder = new StringBuilder(128 * components.length); - if (hasRootFormat(components[0])) { - builder.append(RESET); - } - for (BaseComponent component : components) { - if (component != null) { - builder.append(stringify(component)); - } - } - String output = builder.toString(); - while (output.endsWith(RESET)) { - output = output.substring(0, output.length() - RESET.length()); - } - while (output.startsWith(POSSIBLE_RESET_PREFIX) && output.length() > 4 && colorCodeInvalidator.isMatch(output.charAt(3))) { - output = output.substring(2); - } - return cleanRedundantCodes(output); - } - - public static String stringifyRGBSpigot(String hex) { - StringBuilder hexBuilder = new StringBuilder(7); - hexBuilder.append('x'); - for (int i = hex.length(); i < 6; i++) { - hexBuilder.append('0'); - } - hexBuilder.append(hex); - hex = hexBuilder.toString(); - StringBuilder outColor = new StringBuilder(); - for (char c : hex.toCharArray()) { - outColor.append(org.bukkit.ChatColor.COLOR_CHAR).append(c); - } - return outColor.toString(); - } - - public static String stringify(BaseComponent component) { - return stringifySub(component, null); - } - - public static String stringifySub(BaseComponent component, ChatColor parentColor) { - if (component == null) { - return null; - } - StringBuilder builder = new StringBuilder(128); - ChatColor color = component.getColorRaw(); - if (color == null) { - color = parentColor; - } - if (color != null) { - builder.append(color); - } - if (component.isBold()) { - builder.append(ChatColor.BOLD); - } - if (component.isItalic()) { - builder.append(ChatColor.ITALIC); - } - if (component.isStrikethrough()) { - builder.append(ChatColor.STRIKETHROUGH); - } - if (component.isUnderlined()) { - builder.append(ChatColor.UNDERLINE); - } - if (component.isObfuscated()) { - builder.append(ChatColor.MAGIC); - } - boolean hasFont = component.getFontRaw() != null; - if (hasFont) { - builder.append(ChatColor.COLOR_CHAR).append("[font=").append(component.getFont()).append("]"); - } - boolean hasInsertion = component.getInsertion() != null; - if (hasInsertion) { - builder.append(ChatColor.COLOR_CHAR).append("[insertion=").append(escape(component.getInsertion())).append("]"); - } - boolean hasHover = component.getHoverEvent() != null; - if (hasHover) { - HoverEvent hover = component.getHoverEvent(); - builder.append(ChatColor.COLOR_CHAR).append("[hover=").append(hover.getAction().name()).append(";").append(escape(HoverFormatHelper.stringForHover(hover))).append("]"); - } - boolean hasClick = component.getClickEvent() != null; - if (hasClick) { - ClickEvent click = component.getClickEvent(); - builder.append(ChatColor.COLOR_CHAR).append("[click=").append(click.getAction().name()).append(";").append(escape(click.getValue())).append("]"); - } - if (component instanceof TextComponent) { - builder.append(((TextComponent) component).getText()); - } - else if (component instanceof TranslatableComponent translatableComponent) { - MapTag map = new MapTag(); - map.putObject("key", new ElementTag(translatableComponent.getTranslate(), true)); - if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20) && translatableComponent.getFallback() != null) { - map.putObject("fallback", new ElementTag(translatableComponent.getFallback(), true)); - } - if (translatableComponent.getWith() != null) { - map.putObject("with", new ListTag(translatableComponent.getWith(), baseComponent -> new ElementTag(stringify(baseComponent), true))); - } - builder.append(ChatColor.COLOR_CHAR).append("[translate=").append(escape(map.savable())).append(']'); - } - else if (component instanceof SelectorComponent) { - builder.append(ChatColor.COLOR_CHAR).append("[selector=").append(escape(((SelectorComponent) component).getSelector())).append("]"); - } - else if (component instanceof KeybindComponent) { - builder.append(ChatColor.COLOR_CHAR).append("[keybind=").append(escape(((KeybindComponent) component).getKeybind())).append("]"); - } - else if (component instanceof ScoreComponent) { - builder.append(ChatColor.COLOR_CHAR).append("[score=").append(escape(((ScoreComponent) component).getName())) - .append(";").append(escape(((ScoreComponent) component).getObjective())) - .append(";").append(escape(((ScoreComponent) component).getValue())).append("]"); - } - List after = component.getExtra(); - if (after != null) { - for (BaseComponent afterComponent : after) { - builder.append(stringifySub(afterComponent, color)); - } - } - if (hasClick) { - builder.append(ChatColor.COLOR_CHAR + "[/click]"); - } - if (hasHover) { - builder.append(ChatColor.COLOR_CHAR + "[/hover]"); - } - if (hasInsertion) { - builder.append(ChatColor.COLOR_CHAR + "[/insertion]"); - } - if (hasFont) { - builder.append(ChatColor.COLOR_CHAR + "[reset=font]"); - } - builder.append(RESET); - String output = builder.toString(); - return cleanRedundantCodes(output); - } - - public static final String RESET = ChatColor.RESET.toString(), POSSIBLE_RESET_PREFIX = RESET + ChatColor.COLOR_CHAR; - - private static Boolean procBool(Boolean input, boolean optimize) { - if (input == null) { - return null; - } - if (optimize) { - return input ? true : null; - } - return input; - } - - public static TextComponent copyFormatToNewText(TextComponent last, boolean optimize) { - TextComponent toRet = new TextComponent(); - toRet.setObfuscated(procBool(last.isObfuscatedRaw(), optimize)); - toRet.setBold(procBool(last.isBoldRaw(), optimize)); - toRet.setStrikethrough(procBool(last.isStrikethroughRaw(), optimize)); - toRet.setUnderlined(procBool(last.isUnderlinedRaw(), optimize)); - toRet.setItalic(procBool(last.isItalicRaw(), optimize)); - toRet.setColor(last.getColorRaw()); - return toRet; - } - - public static BaseComponent[] parse(String str, ChatColor baseColor) { - if (str == null) { - return null; - } - return parse(str, baseColor, true); - } - - public static int findNextNormalColorSymbol(String base, int startAt) { - while (true) { - int next = base.indexOf(ChatColor.COLOR_CHAR, startAt); - if (next == -1 || next + 1 >= base.length()) { - return -1; - } - char after = base.charAt(next + 1); - if (colorCodeInvalidator.isMatch(after)) { - return next; - } - startAt = next + 1; - } - } - - public static int findEndIndexFor(String base, String startSymbol, String endSymbol, int startAt) { - int layers = 1; - while (true) { - int next = base.indexOf(ChatColor.COLOR_CHAR, startAt); - if (next == -1) { - return -1; - } - if (next + endSymbol.length() >= base.length()) { - return -1; - } - if (base.startsWith(startSymbol, next + 1)) { - layers++; - } - else if (base.startsWith(endSymbol, next + 1)) { - layers--; - if (layers == 0) { - return next; - } - } - startAt = next + 1; - } - } - - public static int findEndIndexFor(String base, String type, int startAt) { - return findEndIndexFor(base, "[" + type + "=", "[/" + type + "]", startAt); - } - - public static String HEX = "0123456789abcdefABCDEF"; - - public static AsciiMatcher allowedCharCodes = new AsciiMatcher(HEX + "klmnorxKLMNORX["); - - public static AsciiMatcher hexMatcher = new AsciiMatcher(HEX); - - public static AsciiMatcher colorCodesOrReset = new AsciiMatcher(HEX + "rR"); // Any color code that can be invalidated - - public static AsciiMatcher colorCodeInvalidator = new AsciiMatcher(HEX + "rRxX"); // Any code that can invalidate the colors above - - public static String cleanRedundantCodes(String str) { - int index = str.indexOf(ChatColor.COLOR_CHAR); - if (index == -1) { - return str; - } - int start = 0; - StringBuilder output = new StringBuilder(str.length()); - while (index != -1) { - output.append(str, start, index); - start = index; - if (index + 1 >= str.length()) { - break; - } - char symbol = str.charAt(index + 1); - if (allowedCharCodes.isMatch(symbol)) { - if (symbol == 'x' || symbol == 'X') { // Skip entire hex block - index = str.indexOf(ChatColor.COLOR_CHAR, index + 14); - continue; - } - int nextIndex = str.indexOf(ChatColor.COLOR_CHAR, index + 1); - if (colorCodesOrReset.isMatch(symbol) && nextIndex == index + 2 && nextIndex + 1 < str.length()) { - char nextSymbol = str.charAt(nextIndex + 1); - if (colorCodeInvalidator.isMatch(nextSymbol)) { - start = index + 2; // Exclude from output the initial (redundant) color code - index = nextIndex; - continue; - } - } - } - index = str.indexOf(ChatColor.COLOR_CHAR, index + 1); - } - output.append(str, start, str.length()); - return output.toString(); - } - - public static TextComponent getCleanRef() { - TextComponent reference = new TextComponent(); - reference.setBold(false); - reference.setItalic(false); - reference.setStrikethrough(false); - reference.setUnderlined(false); - reference.setObfuscated(false); - return reference; - } - - public static BaseComponent[] parseSimpleColorsOnly(String str) { - TextComponent root = new TextComponent(); - int firstChar = str.indexOf(ChatColor.COLOR_CHAR); - int lastStart = 0; - if (firstChar > 0) { - root.addExtra(new TextComponent(str.substring(0, firstChar))); - lastStart = firstChar; - } - TextComponent nextText = new TextComponent(); - while (firstChar != -1 && firstChar + 1 < str.length()) { - char c = str.charAt(firstChar + 1); - if (allowedCharCodes.isMatch(c)) { - if (c == 'r' || c == 'R') { - nextText.setText(str.substring(lastStart, firstChar)); - if (!nextText.getText().isEmpty()) { - root.addExtra(nextText); - } - nextText = getCleanRef(); - lastStart = firstChar + 2; - } - else if (c == 'X' || c == 'x' && firstChar + 13 < str.length()) { - StringBuilder color = new StringBuilder(12); - color.append("#"); - for (int i = 1; i <= 6; i++) { - if (str.charAt(firstChar + i * 2) != ChatColor.COLOR_CHAR) { - color = null; - break; - } - char hexChar = str.charAt(firstChar + 1 + i * 2); - if (!hexMatcher.isMatch(hexChar)) { - color = null; - break; - } - color.append(hexChar); - } - if (color != null) { - nextText.setText(str.substring(lastStart, firstChar)); - if (!nextText.getText().isEmpty()) { - root.addExtra(nextText); - } - nextText = getCleanRef(); - nextText.setColor(ChatColor.of(CoreUtilities.toUpperCase(color.toString()))); - firstChar += 12; - lastStart = firstChar + 2; - } - } - else if (colorCodesOrReset.isMatch(c)) { - nextText.setText(str.substring(lastStart, firstChar)); - if (!nextText.getText().isEmpty()) { - root.addExtra(nextText); - } - nextText = getCleanRef(); - nextText.setColor(ChatColor.getByChar(c)); - lastStart = firstChar + 2; - } - else { // format code - nextText.setText(str.substring(lastStart, firstChar)); - if (!nextText.getText().isEmpty()) { - root.addExtra(nextText); - } - nextText = copyFormatToNewText(nextText, false); - if (c == 'k' || c == 'K') { - nextText.setObfuscated(true); - } - else if (c == 'l' || c == 'L') { - nextText.setBold(true); - } - else if (c == 'm' || c == 'M') { - nextText.setStrikethrough(true); - } - else if (c == 'n' || c == 'N') { - nextText.setUnderlined(true); - } - else if (c == 'o' || c == 'O') { - nextText.setItalic(true); - } - lastStart = firstChar + 2; - } - } - firstChar = str.indexOf(ChatColor.COLOR_CHAR, firstChar + 1); - } - if (lastStart < str.length()) { - nextText.setText(str.substring(lastStart)); - root.addExtra(nextText); - } - return new BaseComponent[] { root }; - } - - public static BaseComponent[] parse(String str, ChatColor baseColor, boolean cleanBase) { - if (str == null) { - return null; - } - try { - return parseInternal(str, baseColor, cleanBase, false); - } - catch (Throwable ex) { - Debug.echoError(ex); - } - return new BaseComponent[]{new TextComponent(str)}; - } - - private static BaseComponent parseTranslatable(String str, ChatColor baseColor, boolean optimize) { - if (!str.startsWith("map@")) { - List innardParts = CoreUtilities.split(str, ';'); - TranslatableComponent component = new TranslatableComponent(unescape(innardParts.get(0))); - for (int i = 1; i < innardParts.size(); i++) { - for (BaseComponent subComponent : parseInternal(unescape(innardParts.get(i)), baseColor, false, optimize)) { - component.addWith(subComponent); - } - } - return component; - } - MapTag map = MapTag.valueOf(unescape(str), CoreUtilities.noDebugContext); - if (map == null) { - return new TextComponent(str); - } - ElementTag translationKey = map.getElement("key"); - if (translationKey == null) { - return new TextComponent(str); - } - TranslatableComponent component = new TranslatableComponent(translationKey.asString()); - ElementTag fallback = map.getElement("fallback"); - if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20) && fallback != null) { - component.setFallback(fallback.asString()); - } - ListTag withList = map.getObjectAs("with", ListTag.class, CoreUtilities.noDebugContext); - if (withList != null) { - for (String with : withList) { - for (BaseComponent withComponent : parseInternal(with, baseColor, false, optimize)) { - component.addWith(withComponent); - } - } - } - return component; - } - - public static BaseComponent[] parseInternal(String str, ChatColor baseColor, boolean cleanBase, boolean optimize) { - str = CoreUtilities.clearNBSPs(str); - int firstChar = str.indexOf(ChatColor.COLOR_CHAR); - if (firstChar == -1) { - if (str.contains("://")) { - firstChar = 0; - } - else { - TextComponent base = new TextComponent(); - base.addExtra(new TextComponent(str)); // This is for compat with how Spigot does parsing of plaintext. - return new BaseComponent[]{base}; - } - } - str = cleanRedundantCodes(str); - if (cleanBase && str.length() < 512) { - if (!str.contains(ChatColor.COLOR_CHAR + "[") && !str.contains("://")) { - return parseSimpleColorsOnly(str); - } - // Ensure compat with certain weird vanilla translate strings. - if (str.startsWith(ChatColor.COLOR_CHAR + "[translate=") && str.indexOf(']') == str.length() - 1) { - return new BaseComponent[] {parseTranslatable(str.substring("&[translate=".length(), str.length() - 1), baseColor, optimize)}; - } - if (str.length() > 3 && str.startsWith((ChatColor.COLOR_CHAR + "")) && hexMatcher.isMatch(str.charAt(1)) - && str.startsWith(ChatColor.COLOR_CHAR + "[translate=", 2) && str.indexOf(']') == str.length() - 1) { // eg "&6&[translate=block.minecraft.ominous_banner]" - BaseComponent component = parseTranslatable(str.substring("&[translate=".length() + 2, str.length() - 1), baseColor, optimize); - component.setColor(ChatColor.getByChar(str.charAt(1))); - return new BaseComponent[] {component}; - } - } - if (!optimize) { - optimize = str.contains(ChatColor.COLOR_CHAR + "[optimize=true]"); - } - TextComponent root = new TextComponent(); - TextComponent base = new TextComponent(); - if (cleanBase && !optimize) { - base.setBold(false); - base.setItalic(false); - base.setStrikethrough(false); - base.setUnderlined(false); - base.setObfuscated(false); - base.setColor(baseColor); - if (firstChar > 0) { - root.addExtra(new TextComponent(str.substring(0, firstChar))); - } - } - else { - base.setText(str.substring(0, firstChar)); - } - root.addExtra(base); - str = str.substring(firstChar); - char[] chars = str.toCharArray(); - int started = 0; - TextComponent nextText = new TextComponent(); - TextComponent lastText; - for (int i = 0; i < chars.length; i++) { - if (chars[i] == ChatColor.COLOR_CHAR && i + 1 < chars.length) { - char code = chars[i + 1]; - if (!allowedCharCodes.isMatch(code)) { - continue; - } - if (code == '[') { - int endBracket = str.indexOf(']', i + 2); - if (endBracket == -1) { - continue; - } - String innards = str.substring(i + 2, endBracket); - List innardParts = CoreUtilities.split(innards, ';'); - List innardBase = CoreUtilities.split(innardParts.get(0), '=', 2); - innardParts.remove(0); - String innardType = CoreUtilities.toLowerCase(innardBase.get(0)); - if (innardBase.size() == 2) { - nextText.setText(nextText.getText() + str.substring(started, i)); - base.addExtra(nextText); - lastText = nextText; - nextText = copyFormatToNewText(lastText, optimize); - nextText.setText(""); - if (innardType.equals("score") && innardParts.size() == 2) { - ScoreComponent component = new ScoreComponent(unescape(innardBase.get(1)), unescape(innardParts.get(0)), unescape(innardParts.get(1))); - lastText.addExtra(component); - } - else if (innardType.equals("keybind") && Utilities.matchesNamespacedKeyButCaseInsensitive(innardBase.get(1))) { - KeybindComponent component = new KeybindComponent(); - component.setKeybind(unescape(innardBase.get(1))); - lastText.addExtra(component); - } - else if (innardType.equals("selector")) { - SelectorComponent component = new SelectorComponent(unescape(innardBase.get(1))); - lastText.addExtra(component); - } - else if (innardType.equals("translate")) { - lastText.addExtra(parseTranslatable(innards.substring("translate=".length()), baseColor, optimize)); - } - else if (innardType.equals("click") && innardParts.size() == 1) { - int endIndex = findEndIndexFor(str, "click", endBracket); - if (endIndex == -1) { - continue; - } - TextComponent clickableText = new TextComponent(); - ClickEvent.Action action = ElementTag.asEnum(ClickEvent.Action.class, innardBase.get(1)); - clickableText.setClickEvent(new ClickEvent(action == null ? ClickEvent.Action.SUGGEST_COMMAND : action, unescape(innardParts.get(0)))); - for (BaseComponent subComponent : parseInternal(str.substring(endBracket + 1, endIndex), baseColor, false, optimize)) { - clickableText.addExtra(subComponent); - } - lastText.addExtra(clickableText); - endBracket = endIndex + "&[/click".length(); - } - else if (innardType.equals("hover")) { - int endIndex = findEndIndexFor(str, "hover", endBracket); - if (endIndex == -1) { - continue; - } - TextComponent hoverableText = new TextComponent(); - HoverEvent.Action action = ElementTag.asEnum(HoverEvent.Action.class, innardBase.get(1)); - if (HoverFormatHelper.processHoverInput(action == null ? HoverEvent.Action.SHOW_TEXT : action, hoverableText, innardParts.get(0))) { - continue; - } - for (BaseComponent subComponent : parseInternal(str.substring(endBracket + 1, endIndex), baseColor, false, optimize)) { - hoverableText.addExtra(subComponent); - } - lastText.addExtra(hoverableText); - endBracket = endIndex + "&[/hover".length(); - } - else if (innardType.equals("insertion")) { - int endIndex = str.indexOf(ChatColor.COLOR_CHAR + "[/insertion]", i); - int backupEndIndex = str.indexOf(ChatColor.COLOR_CHAR + "[insertion=", i + 5); - if (backupEndIndex > 0 && backupEndIndex < endIndex) { - endIndex = backupEndIndex; - } - if (endIndex == -1) { - continue; - } - TextComponent insertableText = new TextComponent(); - insertableText.setInsertion(unescape(innardBase.get(1))); - for (BaseComponent subComponent : parseInternal(str.substring(endBracket + 1, endIndex), baseColor, false, optimize)) { - insertableText.addExtra(subComponent); - } - lastText.addExtra(insertableText); - endBracket = endIndex + "&[/insertion".length(); - } - else if (innardType.equals("reset")) { - if (innardBase.get(1).length() == 1) { - char subCode = innardBase.get(1).charAt(0); - if (subCode == 'k' || subCode == 'K') { - nextText.setObfuscated(false); - } - else if (subCode == 'l' || subCode == 'L') { - nextText.setBold(false); - } - else if (subCode == 'm' || subCode == 'M') { - nextText.setStrikethrough(false); - } - else if (subCode == 'n' || subCode == 'N') { - nextText.setUnderlined(false); - } - else if (subCode == 'o' || subCode == 'O') { - nextText.setItalic(false); - } - } - else if (innardBase.get(1).equals("font")) { - nextText.setFont(base.getFont()); - } - else { - nextText.setColor(base.getColor()); - } - } - else if (innardType.equals("color")) { - String colorChar = innardBase.get(1); - ChatColor color = null; - if (colorChar.length() == 1) { - color = ChatColor.getByChar(colorChar.charAt(0)); - } - else if (colorChar.length() == 7) { - color = ChatColor.of(CoreUtilities.toUpperCase(colorChar)); - } - else if (CoreConfiguration.debugVerbose) { - Debug.echoError("Text parse issue: cannot interpret color '" + innardBase.get(1) + "'."); - } - if (color != null) { - int endIndex = findEndIndexFor(str, "[color=", "[reset=color]", endBracket); - if (endIndex == -1) { - nextText.setColor(color); - } - else { - TextComponent colorText = new TextComponent(); - colorText.setColor(color); - for (BaseComponent subComponent : parseInternal(str.substring(endBracket + 1, endIndex), color, false, optimize)) { - colorText.addExtra(subComponent); - } - lastText.addExtra(colorText); - endBracket = endIndex + "&[reset=color".length(); - } - } - } - else if (innardType.equals("gradient") && innardParts.size() == 2) { - String from = innardBase.get(1), to = innardParts.get(0), style = innardParts.get(1); - ColorTag fromColor = ColorTag.valueOf(from, CoreUtilities.noDebugContext); - ColorTag toColor = ColorTag.valueOf(to, CoreUtilities.noDebugContext); - BukkitElementExtensions.GradientStyle styleEnum = new ElementTag(style).asEnum(BukkitElementExtensions.GradientStyle.class); - if (fromColor == null || toColor == null || styleEnum == null) { - if (CoreConfiguration.debugVerbose) { - Debug.echoError("Text parse issue: cannot interpret gradient input '" + innards + "'."); - } - } - else { - int endIndex = findNextNormalColorSymbol(str, i + 1); - if (endIndex == -1) { - endIndex = str.length(); - } - String gradientText = BukkitElementExtensions.doGradient(str.substring(endBracket + 1, endIndex), fromColor, toColor, styleEnum); - for (BaseComponent subComponent : parseInternal(gradientText, baseColor, false, optimize)) { - lastText.addExtra(subComponent); - } - endBracket = endIndex - 1; - } - } - else if (innardType.equals("font") && Utilities.matchesNamespacedKey(innardBase.get(1))) { - int endIndex = findEndIndexFor(str, "[font=", "[reset=font]", endBracket); - if (endIndex == -1) { - nextText.setFont(innardBase.get(1)); - } - else { - TextComponent fontText = new TextComponent(); - fontText.setFont(innardBase.get(1)); - for (BaseComponent subComponent : parseInternal(str.substring(endBracket + 1, endIndex), baseColor, false, optimize)) { - fontText.addExtra(subComponent); - } - lastText.addExtra(fontText); - endBracket = endIndex + "&[reset=font".length(); - } - } - else if (innardType.equals("optimize")) { - // Ignore - } - else { - if (CoreConfiguration.debugVerbose) { - Debug.echoError("Text parse issue: cannot interpret type '" + innardType + "' with " + innardParts.size() + " parts."); - } - } - } - i = endBracket; - started = endBracket + 1; - continue; - } - else if (code == 'r' || code == 'R') { - nextText.setText(nextText.getText() + str.substring(started, i)); - if (!nextText.getText().isEmpty()) { - base.addExtra(nextText); - } - nextText = new TextComponent(); - nextText.setColor(baseColor); - } - else if (colorCodesOrReset.isMatch(code)) { - nextText.setText(nextText.getText() + str.substring(started, i)); - if (!nextText.getText().isEmpty()) { - base.addExtra(nextText); - } - nextText = new TextComponent(); - nextText.setColor(ChatColor.getByChar(code)); - } - else if (code == 'x') { - if (i + 13 >= chars.length) { - continue; - } - StringBuilder color = new StringBuilder(12); - color.append("#"); - for (int c = 1; c <= 6; c++) { - if (chars[i + c * 2] != ChatColor.COLOR_CHAR) { - color = null; - break; - } - char hexPart = chars[i + 1 + c * 2]; - if (!hexMatcher.isMatch(hexPart)) { - color = null; - break; - } - color.append(hexPart); - } - if (color == null) { - continue; - } - nextText.setText(nextText.getText() + str.substring(started, i)); - if (!nextText.getText().isEmpty()) { - base.addExtra(nextText); - } - nextText = new TextComponent(); - nextText.setColor(ChatColor.of(CoreUtilities.toUpperCase(color.toString()))); - i += 13; - started = i + 1; - continue; - } - else { - nextText.setText(nextText.getText() + str.substring(started, i)); - if (!nextText.getText().isEmpty()) { - base.addExtra(nextText); - } - nextText = copyFormatToNewText(nextText, optimize); - if (code == 'k' || code == 'K') { - nextText.setObfuscated(true); - } - else if (code == 'l' || code == 'L') { - nextText.setBold(true); - } - else if (code == 'm' || code == 'M') { - nextText.setStrikethrough(true); - } - else if (code == 'n' || code == 'N') { - nextText.setUnderlined(true); - } - else if (code == 'o' || code == 'O') { - nextText.setItalic(true); - } - } - i++; - started = i + 1; - } - else if (i + "https://a.".length() < chars.length && chars[i] == 'h' && chars[i + 1] == 't' && chars[i + 2] == 't' && chars[i + 3] == 'p') { - String subStr = str.substring(i, i + "https://a.".length()); - if (subStr.startsWith("https://") || subStr.startsWith("http://")) { - int nextSpace = CoreUtilities.indexOfAny(str, i, ' ', '\t', '\n', ChatColor.COLOR_CHAR); - if (nextSpace == -1) { - nextSpace = str.length(); - } - String url = str.substring(i, nextSpace); - nextText.setText(nextText.getText() + str.substring(started, i)); - base.addExtra(nextText); - lastText = nextText; - nextText = new TextComponent(lastText); - nextText.setText(""); - TextComponent clickableText = new TextComponent(url); - clickableText.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, url)); - lastText.addExtra(clickableText); - i = nextSpace - 1; - started = nextSpace; - continue; - } - } - } - nextText.setText(nextText.getText() + str.substring(started)); - if (!nextText.getText().isEmpty()) { - base.addExtra(nextText); - } - return new BaseComponent[] { cleanBase && !optimize ? root : base }; - } - - public static int indexOfLastColorBlockStart(String text) { - int result = text.lastIndexOf(ChatColor.COLOR_CHAR + "["); - if (result == -1 || text.indexOf(']', result + 2) != -1) { - return -1; - } - return result; - } - - /** - * Equivalent to DebugInternals.trimMessage, with a special check: - * If a message is cut in the middle of a format block like "&[font=x:y]", cut that block entirely out. - * (This is needed because a snip in the middle of this will explode with parsing errors). - */ - public static String bukkitSafeDebugTrimming(String message) { - int trimSize = CoreConfiguration.debugTrimLength; - if (message.length() > trimSize) { - int firstCut = (trimSize / 2) - 10, secondCut = message.length() - ((trimSize / 2) - 10); - String prePart = message.substring(0, firstCut); - String cutPart = message.substring(firstCut, secondCut); - String postPart = message.substring(secondCut); - int preEarlyCut = indexOfLastColorBlockStart(prePart); - if (preEarlyCut != -1) { - prePart = message.substring(0, preEarlyCut); - } - if (indexOfLastColorBlockStart(cutPart) != -1 || (preEarlyCut != -1 && cutPart.indexOf(']') == -1)) { - int lateCut = postPart.indexOf(']'); - if (lateCut != -1) { - postPart = postPart.substring(lateCut + 1); - } - } - message = prePart + "... *snip!*..." + postPart; - } - return message; - } - - public static Gson getBungeeGson() { - if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21)) { - return VersionedComponentSerializer.forVersion(ChatVersion.V1_21_5).getGson(); - } - else { - return ReflectionHelper.getFieldValue(ComponentSerializer.class, "gson", null); - } - } - - static { - // Explicitly before initializing vanillaStyleSpigotComponentGSON - HoverFormatHelper.tryInitializeItemHoverFix(); - } - - public static final Gson vanillaStyleSpigotComponentGSON = getBungeeGson().newBuilder().disableHtmlEscaping().create(); - - public static String componentToJson(BaseComponent[] components) { - if (components.length == 1) { - return vanillaStyleSpigotComponentGSON.toJson(components[0]); - } - return vanillaStyleSpigotComponentGSON.toJson(new TextComponent(components)); - } - - public static BaseComponent[] parseJson(String json) { - if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21)) { - return VersionedComponentSerializer.forVersion(ChatVersion.V1_21_5).parse(json); - } - return ComponentSerializer.parse(json); - } -} diff --git a/plugin/src/main/java/com/denizenscript/denizen/utilities/HoverFormatHelper.java b/plugin/src/main/java/com/denizenscript/denizen/utilities/HoverFormatHelper.java deleted file mode 100644 index 3e29a12ae7..0000000000 --- a/plugin/src/main/java/com/denizenscript/denizen/utilities/HoverFormatHelper.java +++ /dev/null @@ -1,238 +0,0 @@ -package com.denizenscript.denizen.utilities; - -import com.denizenscript.denizen.nms.NMSHandler; -import com.denizenscript.denizen.nms.NMSVersion; -import com.denizenscript.denizen.objects.EntityTag; -import com.denizenscript.denizen.objects.ItemTag; -import com.denizenscript.denizencore.objects.ObjectTag; -import com.denizenscript.denizencore.objects.core.ElementTag; -import com.denizenscript.denizencore.objects.core.MapTag; -import com.denizenscript.denizencore.tags.Attribute; -import com.denizenscript.denizencore.utilities.CoreUtilities; -import com.denizenscript.denizencore.utilities.ReflectionHelper; -import com.denizenscript.denizencore.utilities.debugging.Debug; -import com.google.gson.*; -import net.md_5.bungee.api.ChatColor; -import net.md_5.bungee.api.chat.BaseComponent; -import net.md_5.bungee.api.chat.HoverEvent; -import net.md_5.bungee.api.chat.TextComponent; -import net.md_5.bungee.api.chat.hover.content.*; -import net.md_5.bungee.chat.ChatVersion; -import net.md_5.bungee.chat.ComponentSerializer; -import net.md_5.bungee.chat.VersionedComponentSerializer; -import org.bukkit.Bukkit; -import org.bukkit.Registry; -import org.bukkit.inventory.ItemStack; - -import java.lang.reflect.Type; -import java.util.UUID; - -public class HoverFormatHelper { - - public static boolean processHoverInput(HoverEvent.Action action, TextComponent hoverableText, String input) { - Content content; - if (action == HoverEvent.Action.SHOW_ITEM) { - ItemTag item = ItemTag.valueOf(FormattedTextHelper.unescape(input), CoreUtilities.noDebugContext); - if (item == null) { - return true; - } - if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20)) { - content = new FixedItemHover(item.getBukkitMaterial().getKey().toString(), item.getAmount(), NMSHandler.itemHelper.getRawHoverComponentsJson(item.getItemStack())); - } - else { - content = new Item(item.getBukkitMaterial().getKey().toString(), item.getAmount(), net.md_5.bungee.api.chat.ItemTag.ofNbt(NMSHandler.itemHelper.getLegacyHoverNbt(item))); - } - } - else if (action == HoverEvent.Action.SHOW_ENTITY) { - String rawInput = FormattedTextHelper.unescape(input); - if (!rawInput.startsWith("map@")) { - content = parseLegacyEntityHover(rawInput); - if (content == null) { - return true; - } - } - else { - MapTag entityHoverData = MapTag.valueOf(rawInput, CoreUtilities.noDebugContext); - if (entityHoverData == null) { - return true; - } - ElementTag uuid = entityHoverData.getElement("uuid"); - if (uuid == null) { - return true; - } - ElementTag type = entityHoverData.getElement("type"); - ElementTag rawName = entityHoverData.getElement("name"); - BaseComponent name = rawName != null ? TextComponent.fromArray(FormattedTextHelper.parse(rawName.asString(), ChatColor.WHITE)) : null; - content = new Entity(type != null ? type.asString() : null, uuid.asString(), name); - } - } - else { - content = new Text(FormattedTextHelper.parse(FormattedTextHelper.unescape(input), ChatColor.WHITE)); - } - hoverableText.setHoverEvent(new HoverEvent(action, content)); - return false; - } - - public static String stringForHover(HoverEvent hover) { - if (hover.getContents().isEmpty()) { - return ""; - } - Content contentObject = hover.getContents().get(0); - if (contentObject instanceof Text textHover) { - Object value = textHover.getValue(); - if (value instanceof BaseComponent[] componentsValue) { - return FormattedTextHelper.stringify(componentsValue); - } - else { - return value.toString(); - } - } - else if (contentObject instanceof Item itemHover) { - ItemStack item = new ItemStack(Registry.MATERIAL.get(Utilities.parseNamespacedKey(itemHover.getId())), itemHover.getCount() == -1 ? 1 : itemHover.getCount()); - if (itemHover instanceof FixedItemHover fixedItemHover && fixedItemHover.getComponents() != null) { - item = NMSHandler.itemHelper.applyRawHoverComponentsJson(item, fixedItemHover.getComponents()); - } - else if (NMSHandler.getVersion().isAtMost(NMSVersion.v1_19) && itemHover.getTag() != null && itemHover.getTag().getNbt() != null) { - item = Bukkit.getUnsafe().modifyItemStack(item, itemHover.getTag().getNbt()); - } - return new ItemTag(item).identify(); - } - else if (contentObject instanceof Entity entityHover) { - return createEntityHoverData(entityHover.getId(), entityHover.getType(), entityHover.getName()).savable(); - } - else { - throw new UnsupportedOperationException(); - } - } - - public static MapTag createEntityHoverData(String uuid, String type, BaseComponent name) { - MapTag entityHoverData = new MapTag(); - entityHoverData.putObject("uuid", new ElementTag(uuid, true)); - if (type != null) { - entityHoverData.putObject("type", new ElementTag(type, true)); - } - else { - try { - // This isn't even optional, but is in Bungee for some reason - try our best to have a value - org.bukkit.entity.Entity found = EntityTag.getEntityForID(UUID.fromString(uuid)); - if (found != null) { - entityHoverData.putObject("type", new ElementTag(found.getType().getKey().toString(), true)); - } - } - catch (IllegalArgumentException ignore) {} - } - if (name != null) { - entityHoverData.putObject("name", new ElementTag(FormattedTextHelper.stringify(name), true)); - } - return entityHoverData; - } - - public static String parseObjectToHover(ObjectTag object, HoverEvent.Action action, Attribute attribute) { - return switch (action) { - case SHOW_ENTITY -> { - EntityTag toShow = object.asType(EntityTag.class, attribute.context); - if (toShow == null) { - attribute.echoError("Invalid hover object '" + object + "' specified for type 'SHOW_ENTITY': must be an EntityTag."); - yield null; - } - BaseComponent[] customName = PaperAPITools.instance.getCustomNameComponent(toShow.getBukkitEntity()); - yield createEntityHoverData(toShow.getUUID().toString(), toShow.getBukkitEntityType().getKey().toString(), customName != null ? new TextComponent(customName) : null).savable(); - } - case SHOW_ITEM -> { - ItemTag toShow = object.asType(ItemTag.class, attribute.context); - if (toShow == null) { - attribute.echoError("Invalid hover object '" + object + "' specified for type 'SHOW_ITEM': must be an ItemTag."); - yield null; - } - yield toShow.identify(); - } - case SHOW_TEXT -> object.toString(); - default -> { - attribute.echoError("Using unsupported hover type: " + action + '.'); - yield null; - } - }; - } - - private static Entity parseLegacyEntityHover(String input) { - EntityTag entity = EntityTag.valueOf(input, CoreUtilities.basicContext); - if (entity == null) { - return null; - } - BaseComponent name = null; - if (entity.getBukkitEntity() != null && entity.getBukkitEntity().isCustomNameVisible()) { - name = new TextComponent(); - for (BaseComponent component : FormattedTextHelper.parse(entity.getBukkitEntity().getCustomName(), ChatColor.WHITE)) { - name.addExtra(component); - } - } - return new Entity(entity.getBukkitEntityType().getKey().toString(), entity.getUUID().toString(), name); - } - - public static void tryInitializeItemHoverFix() { - if (!NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20)) { - return; - } - Gson bungeeGson = FormattedTextHelper.getBungeeGson(); - if (bungeeGson == null) { - return; - } - Gson fixedGson = bungeeGson.newBuilder() - .registerTypeAdapter(FixedItemHover.class, new FixedItemHoverSerializer()) - .registerTypeAdapter(Item.class, new FixedItemHoverSerializer()) - .create(); - try { - if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21)) { - ReflectionHelper.setFieldValue(VersionedComponentSerializer.class, "gson", VersionedComponentSerializer.forVersion(ChatVersion.V1_21_5), fixedGson); - } - else { - ReflectionHelper.getFinalSetter(ComponentSerializer.class, "gson").invoke(fixedGson); - } - } - catch (Throwable e) { - Debug.echoError(e); - } - } - - public static class FixedItemHover extends Item { - - private final JsonObject components; - - public FixedItemHover(String id, int count, JsonObject components) { - super(id, count, null); - this.components = components; - } - - public JsonObject getComponents() { - return components; - } - } - - public static class FixedItemHoverSerializer extends ItemSerializer { - - @Override - public Item deserialize(JsonElement element, Type type, JsonDeserializationContext context) throws JsonParseException { - Item deserialized = super.deserialize(element, type, context); - if (deserialized.getTag() != null) { - return deserialized; - } - JsonObject componentsObject = element.getAsJsonObject().getAsJsonObject("components"); - if (componentsObject == null) { - return deserialized; - } - return new FixedItemHover(deserialized.getId(), deserialized.getCount(), componentsObject); - } - - @Override - public JsonElement serialize(Item content, Type type, JsonSerializationContext context) { - JsonElement serialized = super.serialize(content, type, context); - if (!(content instanceof FixedItemHover fixedItemHover) || fixedItemHover.getComponents() == null) { - return serialized; - } - JsonObject serializedObject = serialized.getAsJsonObject(); - serializedObject.remove("tag"); - serializedObject.add("components", fixedItemHover.getComponents()); - return serializedObject; - } - } -} From b6fd33734f2048f5d86fd1ba73d352602dd2fddd Mon Sep 17 00:00:00 2001 From: Aya <31237389+tal5@users.noreply.github.com> Date: Fri, 19 Sep 2025 22:57:24 +0100 Subject: [PATCH 24/24] Item hovers handling --- dist/pom.xml | 3 ++ .../paper/utilities/FormattedTextHelper.java | 8 +++- .../paper/utilities/HoverFormatHelper.java | 43 +++++++++++++++---- .../denizen/nms/interfaces/ItemHelper.java | 11 +---- .../nms/v1_17/helpers/ItemHelperImpl.java | 9 ---- .../nms/v1_20/helpers/ItemHelperImpl.java | 28 +++--------- .../nms/v1_21/helpers/ItemHelperImpl.java | 27 +++--------- 7 files changed, 59 insertions(+), 70 deletions(-) diff --git a/dist/pom.xml b/dist/pom.xml index 25100bb2e5..fdaa7fc6bc 100644 --- a/dist/pom.xml +++ b/dist/pom.xml @@ -172,6 +172,9 @@ net.kyori.adventure.nbt com.denizenscript.shaded.net.adventure.nbt + + net.kyori.adventure.nbt.api.* + diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/FormattedTextHelper.java b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/FormattedTextHelper.java index 85bf98ad5b..02e17e626a 100644 --- a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/FormattedTextHelper.java +++ b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/FormattedTextHelper.java @@ -255,7 +255,13 @@ public static String stringifySub(Component component, TextColor parentColor) { boolean hasHover = component.hoverEvent() != null; if (hasHover) { HoverEvent hover = component.hoverEvent(); - builder.append(LEGACY_SECTION).append("[hover=").append(hover.action()).append(";").append(escape(HoverFormatHelper.stringForHover(hover))).append("]"); + String hoverString = HoverFormatHelper.stringForHover(hover); + if (hoverString != null) { + builder.append(LEGACY_SECTION).append("[hover=").append(hover.action()).append(";").append(escape(hoverString)).append("]"); + } + else { + hasHover = false; + } } boolean hasClick = component.clickEvent() != null; if (hasClick) { diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/HoverFormatHelper.java b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/HoverFormatHelper.java index 7ff3e505c3..04fa570d9a 100644 --- a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/HoverFormatHelper.java +++ b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/HoverFormatHelper.java @@ -9,6 +9,7 @@ import com.denizenscript.denizencore.objects.core.MapTag; import com.denizenscript.denizencore.tags.Attribute; import com.denizenscript.denizencore.utilities.CoreUtilities; +import com.denizenscript.denizencore.utilities.ReflectionHelper; import com.denizenscript.denizencore.utilities.debugging.Debug; import net.kyori.adventure.key.Key; import net.kyori.adventure.text.Component; @@ -17,9 +18,13 @@ import net.kyori.adventure.text.event.HoverEventSource; import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.NamespacedKey; import org.bukkit.Registry; import org.bukkit.inventory.ItemStack; +import java.lang.invoke.MethodHandle; +import java.util.Map; import java.util.UUID; public class HoverFormatHelper { @@ -70,26 +75,48 @@ else if (action == HoverEvent.Action.SHOW_ENTITY) { return false; } + public static final MethodHandle ADVENTURE_COMPONENTS_TO_NMS = NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20) ? + ReflectionHelper.getMethodHandle( + ReflectionHelper.getClassOrThrow("io.papermc.paper.adventure.PaperAdventure"), "asVanilla", Map.class + ) : null; + public static String stringForHover(HoverEvent hover) { if (hover.value() instanceof Component textHover) { return FormattedTextHelper.stringify(textHover); } else if (hover.value() instanceof HoverEvent.ShowItem itemHover) { - Debug.log("Item hover: " + itemHover.dataComponents()); - ItemStack item = new ItemStack(Registry.MATERIAL.get(itemHover.item()), itemHover.count()); - if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20)) { -// item = NMSHandler.itemHelper.applyRawHoverComponentsJson(item, fixedItemHover.getComponents()); TODO + Material material = Registry.MATERIAL.get(new NamespacedKey(itemHover.item().namespace(), itemHover.item().value())); + if (material == null || !material.isItem()) { + Debug.echoError("Invalid hover item type '" + itemHover.item() + "', please report this to the developers! See the stacktrace below for more information:"); + Debug.echoError(new RuntimeException()); + return null; + } + if (NMSHandler.getVersion().isAtMost(NMSVersion.v1_19)) { + ItemStack item = new ItemStack(material, itemHover.count()); + if (itemHover.nbt() != null) { + item = Bukkit.getUnsafe().modifyItemStack(item, itemHover.nbt().string()); + } + return new ItemTag(item).identify(); } - else if (itemHover.nbt() != null) { - item = Bukkit.getUnsafe().modifyItemStack(item, itemHover.nbt().string()); + if (itemHover.dataComponents().isEmpty()) { + return new ItemTag(material, itemHover.count()).identify(); + } + try { + Object nmsPatch = ADVENTURE_COMPONENTS_TO_NMS.invoke(itemHover.dataComponents()); + ItemStack item = NMSHandler.itemHelper.createItemWithNMSComponents(material, itemHover.count(), nmsPatch); + return new ItemTag(item).identify(); + } + catch (Throwable e) { + Debug.echoError(e); + return null; } - return new ItemTag(item).identify(); } else if (hover.value() instanceof HoverEvent.ShowEntity entityHover) { return createEntityHoverData(entityHover.id(), entityHover.type(), entityHover.name()).savable(); } else { - throw new UnsupportedOperationException(); + Debug.echoError("Unrecognized hover event: " + hover); + return null; } } diff --git a/plugin/src/main/java/com/denizenscript/denizen/nms/interfaces/ItemHelper.java b/plugin/src/main/java/com/denizenscript/denizen/nms/interfaces/ItemHelper.java index 4ae68a5f7f..a1b27a7218 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/nms/interfaces/ItemHelper.java +++ b/plugin/src/main/java/com/denizenscript/denizen/nms/interfaces/ItemHelper.java @@ -6,7 +6,6 @@ import com.denizenscript.denizen.objects.ItemTag; import com.denizenscript.denizen.utilities.nbt.CustomNBT; import com.denizenscript.denizencore.objects.core.MapTag; -import com.google.gson.JsonObject; import net.kyori.adventure.nbt.BinaryTag; import net.kyori.adventure.nbt.CompoundBinaryTag; import org.bukkit.DyeColor; @@ -44,15 +43,7 @@ public abstract class ItemHelper { public abstract String getJsonString(ItemStack itemStack); - public String getLegacyHoverNbt(ItemTag item) { // TODO: once 1.20 is the minimum supported version, remove this - return item.getItemMeta().getAsString(); - } - - public JsonObject getRawHoverComponentsJson(ItemStack item) { - throw new UnsupportedOperationException(); - } - - public ItemStack applyRawHoverComponentsJson(ItemStack item, JsonObject components) { + public ItemStack createItemWithNMSComponents(Material type, int count, Object nmsPatch) { throw new UnsupportedOperationException(); } diff --git a/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/helpers/ItemHelperImpl.java b/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/helpers/ItemHelperImpl.java index 8fd5ea1590..47d9bc1c9a 100644 --- a/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/helpers/ItemHelperImpl.java +++ b/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/helpers/ItemHelperImpl.java @@ -161,15 +161,6 @@ public String getJsonString(ItemStack itemStack) { return json.substring(176, json.length() - 185); } - @Override - public String getLegacyHoverNbt(ItemTag item) { - net.minecraft.nbt.CompoundTag tag = CraftItemStack.asNMSCopy(item.getItemStack()).getTag(); - if (tag == null) { - return null; - } - return tag.toString(); - } - @Override public PlayerProfile getSkullSkin(ItemStack is) { net.minecraft.world.item.ItemStack itemStack = CraftItemStack.asNMSCopy(is); diff --git a/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/helpers/ItemHelperImpl.java b/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/helpers/ItemHelperImpl.java index c70a5829f4..29b395566a 100644 --- a/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/helpers/ItemHelperImpl.java +++ b/v1_20/src/main/java/com/denizenscript/denizen/nms/v1_20/helpers/ItemHelperImpl.java @@ -15,11 +15,9 @@ import com.denizenscript.denizencore.utilities.ReflectionHelper; import com.denizenscript.denizencore.utilities.debugging.Debug; import com.google.common.collect.*; -import com.google.gson.JsonObject; import com.mojang.authlib.GameProfile; import com.mojang.authlib.properties.Property; import com.mojang.serialization.Dynamic; -import com.mojang.serialization.JsonOps; import net.kyori.adventure.nbt.BinaryTag; import net.kyori.adventure.nbt.CompoundBinaryTag; import net.minecraft.advancements.critereon.BlockPredicate; @@ -68,6 +66,7 @@ import org.bukkit.craftbukkit.v1_20_R4.entity.CraftPlayer; import org.bukkit.craftbukkit.v1_20_R4.inventory.CraftInventoryPlayer; import org.bukkit.craftbukkit.v1_20_R4.inventory.CraftItemStack; +import org.bukkit.craftbukkit.v1_20_R4.inventory.CraftItemType; import org.bukkit.craftbukkit.v1_20_R4.inventory.CraftRecipe; import org.bukkit.craftbukkit.v1_20_R4.map.CraftMapView; import org.bukkit.craftbukkit.v1_20_R4.util.CraftMagicNumbers; @@ -201,26 +200,13 @@ public String getJsonString(ItemStack itemStack) { } @Override - public JsonObject getRawHoverComponentsJson(ItemStack item) { - DataComponentPatch nmsComponents = CraftItemStack.asNMSCopy(item).getComponentsPatch(); - if (nmsComponents.isEmpty()) { - return null; + public ItemStack createItemWithNMSComponents(Material type, int count, Object nmsPatchObject) { + if (!(nmsPatchObject instanceof DataComponentPatch nmsPatch)) { + throw new IllegalArgumentException(nmsPatchObject + " is not a DataComponentPatch"); } - return DataComponentPatch.CODEC.encodeStart(CraftRegistry.getMinecraftRegistry().createSerializationContext(JsonOps.INSTANCE), nmsComponents).getOrThrow().getAsJsonObject(); - } - - @Override - public ItemStack applyRawHoverComponentsJson(ItemStack item, JsonObject components) { - return DataComponentPatch.CODEC.parse(CraftRegistry.getMinecraftRegistry().createSerializationContext(JsonOps.INSTANCE), components).mapOrElse( - nmsComponents -> { - net.minecraft.world.item.ItemStack nmsItem = CraftItemStack.asNMSCopy(item); - nmsItem.applyComponents(nmsComponents); - return CraftItemStack.asCraftMirror(nmsItem); - }, - error -> { - Debug.echoError("Invalid hover item data '" + components + "': " + error.message()); - return item; - }); + return CraftItemStack.asCraftMirror(new net.minecraft.world.item.ItemStack( + BuiltInRegistries.ITEM.wrapAsHolder(CraftItemType.bukkitToMinecraft(type)), count, nmsPatch + )); } @Override diff --git a/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/helpers/ItemHelperImpl.java b/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/helpers/ItemHelperImpl.java index 49152cbe2e..bccbed6fcc 100644 --- a/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/helpers/ItemHelperImpl.java +++ b/v1_21/src/main/java/com/denizenscript/denizen/nms/v1_21/helpers/ItemHelperImpl.java @@ -15,11 +15,9 @@ import com.denizenscript.denizencore.utilities.ReflectionHelper; import com.denizenscript.denizencore.utilities.debugging.Debug; import com.google.common.collect.*; -import com.google.gson.JsonObject; import com.mojang.authlib.GameProfile; import com.mojang.authlib.properties.Property; import com.mojang.serialization.Dynamic; -import com.mojang.serialization.JsonOps; import net.kyori.adventure.nbt.BinaryTag; import net.kyori.adventure.nbt.CompoundBinaryTag; import net.minecraft.advancements.critereon.BlockPredicate; @@ -313,26 +311,13 @@ public String getJsonString(ItemStack itemStack) { } @Override - public JsonObject getRawHoverComponentsJson(ItemStack item) { - DataComponentPatch nmsComponents = CraftItemStack.asNMSCopy(item).getComponentsPatch(); - if (nmsComponents.isEmpty()) { - return null; + public ItemStack createItemWithNMSComponents(Material type, int count, Object nmsPatchObject) { + if (!(nmsPatchObject instanceof DataComponentPatch nmsPatch)) { + throw new IllegalArgumentException(nmsPatchObject + " is not a DataComponentPatch"); } - return DataComponentPatch.CODEC.encodeStart(CraftRegistry.getMinecraftRegistry().createSerializationContext(JsonOps.INSTANCE), nmsComponents).getOrThrow().getAsJsonObject(); - } - - @Override - public ItemStack applyRawHoverComponentsJson(ItemStack item, JsonObject components) { - return DataComponentPatch.CODEC.parse(CraftRegistry.getMinecraftRegistry().createSerializationContext(JsonOps.INSTANCE), components).mapOrElse( - nmsComponents -> { - net.minecraft.world.item.ItemStack nmsItem = CraftItemStack.asNMSCopy(item); - nmsItem.applyComponents(nmsComponents); - return CraftItemStack.asCraftMirror(nmsItem); - }, - error -> { - Debug.echoError("Invalid hover item data '" + components + "': " + error.message()); - return item; - }); + return CraftItemStack.asCraftMirror(new net.minecraft.world.item.ItemStack( + BuiltInRegistries.ITEM.wrapAsHolder(CraftItemType.bukkitToMinecraft(type)), count, nmsPatch + )); } @Override