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/PaperModule.java b/paper/src/main/java/com/denizenscript/denizen/paper/PaperModule.java
index 58ff60ed66..a7c00dd7e7 100644
--- a/paper/src/main/java/com/denizenscript/denizen/paper/PaperModule.java
+++ b/paper/src/main/java/com/denizenscript/denizen/paper/PaperModule.java
@@ -9,15 +9,16 @@
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.FormattedTextHelper;
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 com.denizenscript.denizencore.utilities.debugging.DebugInternals;
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 {
@@ -135,33 +136,15 @@ public static void init() {
PaperWorldExtensions.register();
// Paper Tags
new PaperTagBase();
+ new TextFormattingTags();
// Other helpers
Bukkit.getPluginManager().registerEvents(new PaperEventHelpers(), Denizen.getInstance());
+ DebugInternals.alternateTrimLogic = FormattedTextHelper::bukkitSafeDebugTrimming;
PaperAPITools.instance = new PaperAPIToolsImpl();
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 090124e434..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
@@ -2,15 +2,569 @@
import com.denizenscript.denizen.nms.NMSHandler;
import com.denizenscript.denizen.nms.NMSVersion;
+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;
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.format.NamedTextColor;
import net.kyori.adventure.text.minimessage.MiniMessage;
+import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
public class PaperElementExtensions {
public static void register() {
+
+ // <--[tag]
+ // @attribute
+ // @returns ElementTag
+ // @Plugin Paper
+ // @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(PlainTextComponentSerializer.plainText().serialize(FormattedTextHelper.parse(object.asString(), NamedTextColor.WHITE)), true);
+ });
+
+ // <--[tag]
+ // @attribute
+ // @returns ElementTag
+ // @Plugin Paper
+ // @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(PaperModule.componentToJson(FormattedTextHelper.parse(object.asString(), NamedTextColor.WHITE)), true);
+ });
+
+ // <--[tag]
+ // @attribute
+ // @returns ElementTag
+ // @Plugin Paper
+ // @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(PaperModule.jsonToComponent(object.asString())));
+ });
+
+ // <--[tag]
+ // @attribute
+ // @returns ElementTag
+ // @Plugin Paper
+ // @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 = FormattedTextHelper.LEGACY_SECTION + "[optimize=true]";
+ if (object.asString().contains(opti)) {
+ return object;
+ }
+ return new ElementTag(opti + object.asString(), true);
+ });
+
+ // <--[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.
+ // 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(FormattedTextHelper.LEGACY_SECTION + "[hover=SHOW_ITEM;" + FormattedTextHelper.escape(item.identify()) + "]" + object.asString() + FormattedTextHelper.LEGACY_SECTION + "[/hover]", true);
+ });
+
+ // <--[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.
+ // 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
+ // @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.
+ // 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);
+ 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;
+ }
+ }
+ String hoverData = HoverFormatHelper.parseObjectToHover(hover, type, attribute);
+ if (hoverData == null) {
+ return null;
+ }
+ return new ElementTag(FormattedTextHelper.LEGACY_SECTION + "[hover=" + type + ';' + FormattedTextHelper.escape(hoverData) + ']'
+ + object.asString() + FormattedTextHelper.LEGACY_SECTION + "[/hover]", true);
+ });
+
+ // <--[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.
+ // 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(FormattedTextHelper.LEGACY_SECTION + "[click=OPEN_URL;" + FormattedTextHelper.escape(url.asString()) + "]" + object.asString() + FormattedTextHelper.LEGACY_SECTION + "[/click]", true);
+ });
+
+ // <--[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>).
+ // 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(FormattedTextHelper.LEGACY_SECTION + "[click=RUN_COMMAND;/denizenclickable chat " + FormattedTextHelper.escape(chat.asString()) + "]" + object.asString() + FormattedTextHelper.LEGACY_SECTION + "[/click]", true);
+ });
+
+ // <--[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.
+ // 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
+ // @Plugin Paper
+ // @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(FormattedTextHelper.LEGACY_SECTION + "[click=" + type + ";" + FormattedTextHelper.escape(command.asString()) + "]"
+ + object.asString() + FormattedTextHelper.LEGACY_SECTION + "[/click]", true);
+ });
+
+ // <--[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.
+ // 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(FormattedTextHelper.LEGACY_SECTION + "[insertion=" + FormattedTextHelper.escape(insertion.asString()) + "]"
+ + object.asString() + FormattedTextHelper.LEGACY_SECTION + "[/insertion]", true);
+ });
+
+ // <--[tag]
+ // @attribute
+ // @returns ElementTag
+ // @Plugin Paper
+ // @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) == FormattedTextHelper.LEGACY_SECTION) {
+ return new ElementTag(FormattedTextHelper.LEGACY_SECTION + "[color=" + object.asString().charAt(1) + "]", true);
+ }
+ return null;
+ });
+
+ // <--[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.
+ // 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) == FormattedTextHelper.LEGACY_SECTION) {
+ return new ElementTag(FormattedTextHelper.LEGACY_SECTION + "[reset=" + object.asString().charAt(1) + "]", true);
+ }
+ else if (object.asString().startsWith(FormattedTextHelper.LEGACY_SECTION + "[font=") && object.asString().endsWith("]")) {
+ return new ElementTag(FormattedTextHelper.LEGACY_SECTION + "[reset=font]", true);
+ }
+ return null;
+ });
+
+ // <--[tag]
+ // @attribute
+ // @returns ElementTag
+ // @Plugin Paper
+ // @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(LegacyFormatting.ITALIC + object.asString() + FormattedTextHelper.LEGACY_SECTION + "[reset=o]", true);
+ });
+
+ // <--[tag]
+ // @attribute
+ // @returns ElementTag
+ // @Plugin Paper
+ // @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(LegacyFormatting.BOLD + object.asString() + FormattedTextHelper.LEGACY_SECTION + "[reset=l]", true);
+ });
+
+ // <--[tag]
+ // @attribute
+ // @returns ElementTag
+ // @Plugin Paper
+ // @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(LegacyFormatting.UNDERLINE + object.asString() + FormattedTextHelper.LEGACY_SECTION + "[reset=n]", true);
+ });
+
+ // <--[tag]
+ // @attribute
+ // @returns ElementTag
+ // @Plugin Paper
+ // @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(LegacyFormatting.STRIKETHROUGH + object.asString() + FormattedTextHelper.LEGACY_SECTION + "[reset=m]", true);
+ });
+
+ // <--[tag]
+ // @attribute
+ // @returns ElementTag
+ // @Plugin Paper
+ // @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(LegacyFormatting.OBFUSCATED + object.asString() + FormattedTextHelper.LEGACY_SECTION + "[reset=k]", true);
+ });
+
+ // <--[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.
+ // 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(FormattedTextHelper.LEGACY_SECTION + "[color=f]" + color + object.asString() + FormattedTextHelper.LEGACY_SECTION + "[reset=color]", true);
+ });
+
+ // <--[tag]
+ // @attribute ]>
+ // @returns ElementTag
+ // @Plugin Paper
+ // @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) {
+ LegacyColor color = LegacyColor.legacyFromChar(colorName.charAt(0));
+ if (color != null) {
+ colorOut = color.toString();
+ }
+ }
+ else if (colorName.length() == 7 && colorName.startsWith("#")) {
+ return new ElementTag(FormattedTextHelper.LEGACY_SECTION + "[color=" + colorName + "]" + object.asString() + FormattedTextHelper.LEGACY_SECTION + "[reset=color]", true);
+ }
+ 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);
+ 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(FormattedTextHelper.LEGACY_SECTION + "[color=#" + hex + "]" + object.asString() + FormattedTextHelper.LEGACY_SECTION + "[reset=color]", true);
+ }
+ if (colorOut == null) {
+ 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(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() + FormattedTextHelper.LEGACY_SECTION + "[reset=color]", true);
+ });
+
+ // <--[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>"
+ // 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(FormattedTextHelper.LEGACY_SECTION + "[font=" + fontName + "]" + object.asString() + FormattedTextHelper.LEGACY_SECTION + "[reset=font]", true);
+ });
+
+ // <--[tag]
+ // @attribute )]>
+ // @returns ElementTag
+ // @Plugin Paper
+ // @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(FormattedTextHelper.LEGACY_SECTION).append(pattern.charAt(i % pattern.length())).append(str.charAt(i));
+ }
+ return new ElementTag(output.toString(), true);
+ });
+
+ // <--[tag]
+ // @attribute )]>
+ // @returns ElementTag
+ // @Plugin Paper
+ // @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(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));
+ }
+ int rgb = Integer.parseInt(new String(colors), 16);
+ HSB = ColorTag.fromRGB(rgb).toHSB();
+ str = str.substring(14);
+ }
+ float hue = HSB[0] / 255f;
+ int length = PlainTextComponentSerializer.plainText().serialize(FormattedTextHelper.parse(str, NamedTextColor.WHITE)).length();
+ if (length == 0) {
+ return new ElementTag("", true);
+ }
+ 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 == FormattedTextHelper.LEGACY_SECTION && i + 1 < str.length()) {
+ char c2 = str.charAt(i + 1);
+ if (FORMAT_CODES_MATCHER.isMatch(c2)) {
+ addedFormat += String.valueOf(FormattedTextHelper.LEGACY_SECTION) + 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(), true);
+ });
+
+ // <--[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.
+ // 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(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, true);
+ });
+
+ // <--[tag]
+ // @attribute ;to=]>
+ // @returns ElementTag
+ // @Plugin Paper
+ // @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, true);
+ });
+
if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_18)) {
// <--[tag]
@@ -23,7 +577,7 @@ public static void register() {
// 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]
@@ -40,4 +594,96 @@ public static void register() {
});
}
}
+
+ public enum GradientStyle { RGB, HSB }
+
+ public static String doGradient(String str, ColorTag fromColor, ColorTag toColor, GradientStyle style) {
+ int length = PlainTextComponentSerializer.plainText().serialize(FormattedTextHelper.parse(str, NamedTextColor.WHITE)).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 == FormattedTextHelper.LEGACY_SECTION && i + 1 < str.length()) {
+ char c2 = str.charAt(i + 1);
+ if (FORMAT_CODES_MATCHER.isMatch(c2)) {
+ addedFormat += String.valueOf(FormattedTextHelper.LEGACY_SECTION) + 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/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..0a2a1e6df4
--- /dev/null
+++ b/paper/src/main/java/com/denizenscript/denizen/paper/tags/TextFormattingTags.java
@@ -0,0 +1,360 @@
+package com.denizenscript.denizen.paper.tags;
+
+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.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.kyori.adventure.text.event.HoverEvent;
+import net.kyori.adventure.text.format.NamedTextColor;
+
+public class TextFormattingTags {
+
+ 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.
+ // 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
+ // @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.
+ // 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);
+ 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;
+ }
+ }
+ String hoverData = HoverFormatHelper.parseObjectToHover(hover, type, attribute);
+ if (hoverData == null) {
+ return null;
+ }
+ 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.
+ // 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
+ // @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.
+ // 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(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.
+ // 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(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(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(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(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!"
+ // 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(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>.
+ // -->
+ TagManager.registerStaticTagBaseHandler(ElementTag.class, "&selector", (attribute) -> {
+ if (!attribute.hasParam()) {
+ return null;
+ }
+ String selectorText = attribute.getParam();
+ 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.
+ // 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
+ // @Plugin Paper
+ // @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(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).
+ // 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(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.
+ // 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) {
+ LegacyColor color = LegacyColor.legacyFromChar(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) {
+ 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, 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.
+ // 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(PaperElementExtensions.GradientStyle.class)) {
+ attribute.echoError("Invalid gradient style '" + style + "'");
+ return null;
+ }
+ 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".
+ // 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(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.
+ // 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(FormattedTextHelper.LEGACY_SECTION + "[optimize=true]", true);
+ });
+ }
+}
diff --git a/plugin/src/main/java/com/denizenscript/denizen/utilities/FormattedTextHelper.java b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/FormattedTextHelper.java
similarity index 52%
rename from plugin/src/main/java/com/denizenscript/denizen/utilities/FormattedTextHelper.java
rename to paper/src/main/java/com/denizenscript/denizen/paper/utilities/FormattedTextHelper.java
index 67392b5fa9..02e17e626a 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/utilities/FormattedTextHelper.java
+++ b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/FormattedTextHelper.java
@@ -1,893 +1,954 @@
-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);
- }
-}
+package com.denizenscript.denizen.paper.utilities;
+
+import com.denizenscript.denizen.nms.NMSHandler;
+import com.denizenscript.denizen.nms.NMSVersion;
+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;
+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.debugging.Debug;
+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 {
+
+ // <--[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 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 char colorChar;
+ public final String colorString;
+ public final NamedTextColor color;
+
+ 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 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].color : null;
+ }
+
+ public static LegacyColor legacyFromChar(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 = new IdentityHashMap<>(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;
+ }
+ }
+ }
+
+ 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(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(LEGACY_SECTION)).replace("&", "&");
+ }
+ return input;
+ }
+
+ public static boolean hasRootFormat(Component component) {
+ if (component == null) {
+ return false;
+ }
+ if (component.hasStyling()) {
+ return true;
+ }
+ if (!(component instanceof TextComponent textComponent)) {
+ return false;
+ }
+ if (!textComponent.content().isEmpty()) {
+ return false;
+ }
+ List children = component.children();
+ if (children.isEmpty()) {
+ return false;
+ }
+ return hasRootFormat(children.get(0));
+ }
+
+ public static String stringify(Component component) {
+ if (component == null) {
+ return null;
+ }
+ String output = stringifySub(component);
+ if (hasRootFormat(component)) {
+ output = RESET + output;
+ }
+ 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(LEGACY_SECTION).append(c);
+ }
+ return outColor.toString();
+ }
+
+ public static String stringifySub(Component component) {
+ return stringifySub(component, null);
+ }
+
+ public static String stringifySub(Component component, TextColor parentColor) {
+ if (component == null) {
+ return null;
+ }
+ StringBuilder builder = new StringBuilder(128);
+ TextColor color = component.color();
+ if (color == null) {
+ color = parentColor;
+ }
+ if (color != null) {
+ if (color instanceof NamedTextColor namedTextColor) {
+ builder.append(LegacyColor.fromModern(namedTextColor));
+ }
+ else {
+ builder.append(stringifyRGBSpigot(color.asHexString().substring(1)));
+ }
+ }
+ if (component.hasDecoration(TextDecoration.BOLD)) {
+ builder.append(LegacyFormatting.BOLD);
+ }
+ if (component.hasDecoration(TextDecoration.ITALIC)) {
+ builder.append(LegacyFormatting.ITALIC);
+ }
+ if (component.hasDecoration(TextDecoration.STRIKETHROUGH)) {
+ builder.append(LegacyFormatting.STRIKETHROUGH);
+ }
+ if (component.hasDecoration(TextDecoration.UNDERLINED)) {
+ builder.append(LegacyFormatting.UNDERLINE);
+ }
+ if (component.hasDecoration(TextDecoration.OBFUSCATED)) {
+ builder.append(LegacyFormatting.OBFUSCATED);
+ }
+ boolean hasFont = component.font() != null;
+ if (hasFont) {
+ builder.append(LEGACY_SECTION).append("[font=").append(component.font()).append("]");
+ }
+ boolean hasInsertion = component.insertion() != null;
+ if (hasInsertion) {
+ builder.append(LEGACY_SECTION).append("[insertion=").append(escape(component.insertion())).append("]");
+ }
+ boolean hasHover = component.hoverEvent() != null;
+ if (hasHover) {
+ HoverEvent> hover = component.hoverEvent();
+ 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) {
+ 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 textComponent) {
+ builder.append(textComponent.content());
+ }
+ else if (component instanceof TranslatableComponent translatableComponent) {
+ MapTag map = new MapTag();
+ 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.arguments().isEmpty()) {
+ 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(']');
+ }
+ else if (component instanceof SelectorComponent) {
+ // TODO separator
+ builder.append(LEGACY_SECTION).append("[selector=").append(escape(((SelectorComponent) component).pattern())).append("]");
+ }
+ else if (component instanceof KeybindComponent) {
+ builder.append(LEGACY_SECTION).append("[keybind=").append(escape(((KeybindComponent) component).keybind())).append("]");
+ }
+ else if (component instanceof ScoreComponent) {
+ // 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(LEGACY_SECTION + "[/click]");
+ }
+ if (hasHover) {
+ builder.append(LEGACY_SECTION + "[/hover]");
+ }
+ if (hasInsertion) {
+ builder.append(LEGACY_SECTION + "[/insertion]");
+ }
+ if (hasFont) {
+ builder.append(LEGACY_SECTION + "[reset=font]");
+ }
+ builder.append(RESET);
+ String output = builder.toString();
+ return cleanRedundantCodes(output);
+ }
+
+ public static final String RESET = LegacyFormatting.RESET.toString(), POSSIBLE_RESET_PREFIX = RESET + LEGACY_SECTION;
+
+ 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 && state == TextDecoration.State.FALSE) {
+ return;
+ }
+ destination.decoration(decoration, state);
+ }
+
+ 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 Component parse(String str, TextColor 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(LEGACY_SECTION, 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(LEGACY_SECTION, 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(LEGACY_SECTION);
+ 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(LEGACY_SECTION, index + 14);
+ continue;
+ }
+ 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)) {
+ start = index + 2; // Exclude from output the initial (redundant) color code
+ index = nextIndex;
+ continue;
+ }
+ }
+ }
+ index = str.indexOf(LEGACY_SECTION, index + 1);
+ }
+ output.append(str, start, str.length());
+ return output.toString();
+ }
+
+ 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 Component parseSimpleColorsOnly(String str) {
+ TextComponent.Builder root = Component.text();
+ int firstChar = str.indexOf(LEGACY_SECTION);
+ int lastStart = 0;
+ if (firstChar > 0) {
+ root.append(Component.text(str.substring(0, firstChar)));
+ lastStart = firstChar;
+ }
+ 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.content(str.substring(lastStart, firstChar));
+ if (!nextText.content().isEmpty()) {
+ root.append(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) != LEGACY_SECTION) {
+ 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.content(str.substring(lastStart, firstChar));
+ if (!nextText.content().isEmpty()) {
+ root.append(nextText);
+ }
+ nextText = getCleanRef();
+ nextText.color(TextColor.fromHexString(CoreUtilities.toUpperCase(color.toString())));
+ firstChar += 12;
+ lastStart = firstChar + 2;
+ }
+ }
+ else if (colorCodesOrReset.isMatch(c)) {
+ nextText.content(str.substring(lastStart, firstChar));
+ if (!nextText.content().isEmpty()) {
+ root.append(nextText);
+ }
+ nextText = getCleanRef();
+ nextText.color(LegacyColor.fromChar(c));
+ lastStart = firstChar + 2;
+ }
+ else { // format code
+ nextText.content(str.substring(lastStart, firstChar));
+ if (!nextText.content().isEmpty()) {
+ root.append(nextText);
+ }
+ nextText = copyFormatToNewText(nextText, false);
+ if (c == 'k' || c == 'K') {
+ nextText.decoration(TextDecoration.OBFUSCATED, true);
+ }
+ else if (c == 'l' || c == 'L') {
+ nextText.decoration(TextDecoration.BOLD, true);
+ }
+ else if (c == 'm' || c == 'M') {
+ nextText.decoration(TextDecoration.STRIKETHROUGH, true);
+ }
+ else if (c == 'n' || c == 'N') {
+ nextText.decoration(TextDecoration.UNDERLINED, true);
+ }
+ else if (c == 'o' || c == 'O') {
+ nextText.decoration(TextDecoration.ITALIC, true);
+ }
+ lastStart = firstChar + 2;
+ }
+ }
+ firstChar = str.indexOf(LEGACY_SECTION, firstChar + 1);
+ }
+ if (lastStart < str.length()) {
+ nextText.content(str.substring(lastStart));
+ root.append(nextText);
+ }
+ return root.build();
+ }
+
+ public static Component parse(String str, TextColor baseColor, boolean cleanBase) {
+ if (str == null) {
+ return null;
+ }
+ try {
+ return parseInternal(str, baseColor, cleanBase, false);
+ }
+ catch (Throwable ex) {
+ Debug.echoError(ex);
+ }
+ return Component.text(str);
+ }
+
+ // TODO cleanup handling here?
+ private static Component parseTranslatable(String str, TextColor baseColor, boolean optimize) {
+ if (!str.startsWith("map@")) {
+ List innardParts = CoreUtilities.split(str, ';');
+ 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++) {
+ args.add(parseInternal(unescape(innardParts.get(i)), baseColor, false, optimize));
+ }
+ return Component.translatable(translation, args);
+ }
+ MapTag map = MapTag.valueOf(unescape(str), CoreUtilities.noDebugContext);
+ if (map == null) {
+ return Component.text(str);
+ }
+ ElementTag translationKey = map.getElement("key");
+ if (translationKey == null) {
+ 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) {
+ args.add(parseInternal(with, baseColor, false, optimize));
+ }
+ }
+ 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 Component parseInternal(String str, TextColor baseColor, boolean cleanBase, boolean optimize) {
+ str = CoreUtilities.clearNBSPs(str);
+ int firstChar = str.indexOf(LEGACY_SECTION);
+ if (firstChar == -1) {
+ if (str.contains("://")) {
+ firstChar = 0;
+ }
+ else {
+ // This is for compact with how Spigot does parsing of plaintext.
+ return Component.textOfChildren(Component.text(str));
+ }
+ }
+ str = cleanRedundantCodes(str);
+ if (cleanBase && str.length() < 512) {
+ if (!str.contains(LEGACY_SECTION + "[") && !str.contains("://")) {
+ return parseSimpleColorsOnly(str);
+ }
+ // 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(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);
+ return component.color(LegacyColor.fromChar(str.charAt(1)));
+ }
+ }
+ if (!optimize) {
+ optimize = str.contains(LEGACY_SECTION + "[optimize=true]");
+ }
+ TextComponent.Builder root = Component.text();
+ TextComponent.Builder base;
+ if (cleanBase && !optimize) {
+ base = getCleanRef();
+ base.color(baseColor);
+ if (firstChar > 0) {
+ root.append(Component.text(str.substring(0, firstChar)));
+ }
+ }
+ else {
+ base = Component.text();
+ base.content(str.substring(0, firstChar));
+ }
+ str = str.substring(firstChar);
+ char[] chars = str.toCharArray();
+ int started = 0;
+ TextComponent.Builder nextText = Component.text();
+ TextComponent.Builder lastText;
+ for (int i = 0; i < chars.length; i++) {
+ if (chars[i] == LEGACY_SECTION && 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.content(nextText.content() + str.substring(started, i));
+ lastText = nextText;
+ nextText = copyFormatToNewText(lastText, optimize);
+ nextText.content("");
+ if (innardType.equals("score") && innardParts.size() == 2) {
+ // 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 = Component.keybind(unescape(innardBase.get(1)));
+ lastText.append(component);
+ }
+ else if (innardType.equals("selector")) {
+ SelectorComponent component = Component.selector(unescape(innardBase.get(1)));
+ lastText.append(component);
+ }
+ else if (innardType.equals("translate")) {
+ 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.Builder clickableText = Component.text();
+ ClickEvent.Action action = ElementTag.asEnum(ClickEvent.Action.class, innardBase.get(1));
+ // 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")) {
+ int endIndex = findEndIndexFor(str, "hover", endBracket);
+ if (endIndex == -1) {
+ continue;
+ }
+ 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;
+ }
+ 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(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.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.decoration(TextDecoration.OBFUSCATED, false);
+ }
+ else if (subCode == 'l' || subCode == 'L') {
+ nextText.decoration(TextDecoration.BOLD, false);
+ }
+ else if (subCode == 'm' || subCode == 'M') {
+ nextText.decoration(TextDecoration.STRIKETHROUGH, false);
+ }
+ else if (subCode == 'n' || subCode == 'N') {
+ nextText.decoration(TextDecoration.UNDERLINED, false);
+ }
+ else if (subCode == 'o' || subCode == 'O') {
+ nextText.decoration(TextDecoration.ITALIC, false);
+ }
+ }
+ else if (innardBase.get(1).equals("font")) {
+ // TODO builder
+ nextText.font(base.build().font());
+ }
+ else {
+ // TODO builder
+ nextText.color(base.build().color());
+ }
+ }
+ else if (innardType.equals("color")) {
+ String colorChar = innardBase.get(1);
+ TextColor color = null;
+ if (colorChar.length() == 1) {
+ color = LegacyColor.fromChar(colorChar.charAt(0));
+ }
+ else if (colorChar.length() == 7) {
+ color = TextColor.fromHexString(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.color(color);
+ }
+ else {
+ 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();
+ }
+ }
+ }
+ 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);
+ 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 + "'.");
+ }
+ }
+ else {
+ int endIndex = findNextNormalColorSymbol(str, i + 1);
+ if (endIndex == -1) {
+ endIndex = str.length();
+ }
+ String gradientText = PaperElementExtensions.doGradient(str.substring(endBracket + 1, endIndex), fromColor, toColor, styleEnum);
+ 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.font(Key.key(innardBase.get(1)));
+ }
+ else {
+ 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();
+ }
+ }
+ else if (innardType.equals("optimize")) {
+ // Ignore
+ }
+ else {
+ if (CoreConfiguration.debugVerbose) {
+ Debug.echoError("Text parse issue: cannot interpret type '" + innardType + "' with " + innardParts.size() + " parts.");
+ }
+ }
+ base.append(lastText);
+ }
+ i = endBracket;
+ started = endBracket + 1;
+ continue;
+ }
+ else if (code == 'r' || code == 'R') {
+ nextText.content(nextText.content() + str.substring(started, i));
+ if (!nextText.content().isEmpty()) {
+ base.append(nextText);
+ }
+ nextText = Component.text();
+ nextText.color(baseColor);
+ }
+ else if (colorCodesOrReset.isMatch(code)) {
+ nextText.content(nextText.content() + str.substring(started, i));
+ if (!nextText.content().isEmpty()) {
+ base.append(nextText);
+ }
+ nextText = Component.text();
+ nextText.color(LegacyColor.fromChar(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] != LEGACY_SECTION) {
+ 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.content(nextText.content() + str.substring(started, i));
+ if (!nextText.content().isEmpty()) {
+ base.append(nextText);
+ }
+ nextText = Component.text();
+ nextText.color(TextColor.fromHexString(CoreUtilities.toUpperCase(color.toString())));
+ i += 13;
+ started = i + 1;
+ continue;
+ }
+ else {
+ 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.decoration(TextDecoration.OBFUSCATED, true);
+ }
+ else if (code == 'l' || code == 'L') {
+ nextText.decoration(TextDecoration.BOLD, true);
+ }
+ else if (code == 'm' || code == 'M') {
+ nextText.decoration(TextDecoration.STRIKETHROUGH, true);
+ }
+ else if (code == 'n' || code == 'N') {
+ nextText.decoration(TextDecoration.UNDERLINED, true);
+ }
+ else if (code == 'o' || code == 'O') {
+ nextText.decoration(TextDecoration.ITALIC, 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', LEGACY_SECTION);
+ if (nextSpace == -1) {
+ nextSpace = str.length();
+ }
+ String url = str.substring(i, nextSpace);
+ nextText.content(nextText.content() + str.substring(started, i));
+ lastText = nextText;
+ // TODO builder copying
+ nextText = lastText.build().toBuilder();
+ nextText.content("");
+ TextComponent.Builder clickableText = Component.text().content(url);
+ clickableText.clickEvent(ClickEvent.openUrl(url));
+ lastText.append(clickableText);
+ base.append(lastText);
+ i = nextSpace - 1;
+ started = nextSpace;
+ continue;
+ }
+ }
+ }
+ nextText.content(nextText.content() + str.substring(started));
+ if (!nextText.content().isEmpty()) {
+ base.append(nextText);
+ }
+ return cleanBase && !optimize ? root.append(base).build() : base.build();
+ }
+
+ public static int indexOfLastColorBlockStart(String text) {
+ int result = text.lastIndexOf(LEGACY_SECTION + "[");
+ 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;
+ }
+}
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..04fa570d9a
--- /dev/null
+++ b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/HoverFormatHelper.java
@@ -0,0 +1,170 @@
+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.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 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.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 {
+
+ public static boolean processHoverInput(HoverEvent.Action> action, TextComponent.Builder hoverableText, String input) {
+ HoverEventSource> content;
+ if (action == HoverEvent.Action.SHOW_ITEM) {
+ 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 = 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 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");
+ Component name = rawName != null ? FormattedTextHelper.parse(rawName.asString(), NamedTextColor.WHITE) : null;
+ content = HoverEvent.showEntity(Key.key(type.asString()), uuid, name);
+ }
+ }
+ else {
+ content = FormattedTextHelper.parse(FormattedTextHelper.unescape(input), NamedTextColor.WHITE);
+ }
+ hoverableText.hoverEvent(content);
+ 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) {
+ 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();
+ }
+ 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;
+ }
+ }
+ else if (hover.value() instanceof HoverEvent.ShowEntity entityHover) {
+ return createEntityHoverData(entityHover.id(), entityHover.type(), entityHover.name()).savable();
+ }
+ else {
+ Debug.echoError("Unrecognized hover event: " + hover);
+ return null;
+ }
+ }
+
+ public static MapTag createEntityHoverData(UUID uuid, Key type, Component name) {
+ MapTag entityHoverData = new MapTag();
+ entityHoverData.putObject("uuid", new ElementTag(uuid.toString(), true));
+ entityHoverData.putObject("type", new ElementTag(type.asString(), true));
+ 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) {
+ 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;
+ }
+ return createEntityHoverData(toShow.getUUID(), toShow.getBukkitEntityType().key(), toShow.getBukkitEntity() != null ? toShow.getBukkitEntity().customName() : null).savable();
+ }
+ 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();
+ }
+ else if (action == HoverEvent.Action.SHOW_TEXT) {
+ return object.identify();
+ }
+ else {
+ attribute.echoError("Using unsupported hover type: " + action + '.');
+ return null;
+ }
+ }
+
+ private static HoverEventSource parseLegacyEntityHover(String input) {
+ EntityTag entity = EntityTag.valueOf(input, CoreUtilities.basicContext);
+ if (entity == null) {
+ return null;
+ }
+ Component name = null;
+ if (entity.getBukkitEntity() != null && entity.getBukkitEntity().isCustomNameVisible()) {
+ name = entity.getBukkitEntity().customName();
+ }
+ return HoverEvent.showEntity(entity.getBukkitEntityType(), entity.getUUID(), name);
+ }
+}
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..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
@@ -8,10 +8,10 @@
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;
+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;
@@ -20,10 +20,12 @@
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;
-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;
@@ -36,6 +38,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;
@@ -49,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
@@ -62,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);
}
@@ -76,28 +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());
- }
-
- @Override
- public BaseComponent[] getCustomNameComponent(Entity entity) {
- Component customName = entity.customName();
- return customName != null ? FormattedTextHelper.parseJson(PaperModule.componentToJson(customName)) : null;
+ 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
@@ -105,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
@@ -121,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));
}
}
@@ -129,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
@@ -249,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<>();
@@ -337,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
@@ -361,28 +359,27 @@ 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
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
@@ -409,4 +406,80 @@ 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 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());
+ 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 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 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));
+ }
+
+ @Override
+ public String parseTextToJson(String formattedText, BaseColor baseColor) {
+ return PaperModule.componentToJson(FormattedTextHelper.parse(formattedText, switch (baseColor) {
+ case WHITE -> NamedTextColor.WHITE;
+ case BLACK -> NamedTextColor.BLACK;
+ case GRAY -> NamedTextColor.GRAY;
+ case DARK_GRAY -> NamedTextColor.DARK_GRAY;
+ }));
+ }
+
+ @Override
+ public String parseJsonToText(String json) {
+ return FormattedTextHelper.stringify(PaperModule.jsonToComponent(json));
+ }
}
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")
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/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/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");
}
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/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/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/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/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/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/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
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 3f71572930..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 ? new TextComponent(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;
- }
- }
-}
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..13206b05f7 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java
@@ -5,9 +5,16 @@
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;
+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;
@@ -20,13 +27,16 @@
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.UUID;
import java.util.function.Predicate;
public class PaperAPITools {
@@ -45,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();
@@ -71,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);
}
@@ -112,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();
}
@@ -233,4 +234,87 @@ public boolean hasCustomName(PotionMeta meta) {
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 addPage(BookMeta meta, String page) {
+ meta.addPage(page);
+ }
+
+ 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(jsonToBungee(jsonPage));
+ }
+ 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 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));
+ }
+
+ public enum BaseColor { WHITE, BLACK, GRAY, DARK_GRAY }
+
+ 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(switch (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);
+ return bungeeToJson(base);
+ }
+
+ public String parseJsonToText(String 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/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;
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));
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/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 be378e2c3d..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,9 +3,8 @@
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.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 +91,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) {
@@ -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..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
@@ -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;
@@ -164,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);
@@ -250,8 +238,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 +250,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 +267,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 +285,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 4f948d0b87..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
@@ -3,20 +3,21 @@
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;
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;
import com.denizenscript.denizen.utilities.blocks.FakeBlock;
@@ -26,16 +27,13 @@
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 +269,10 @@ public boolean processActionbarPacket(Packet> packet, GenericFutureListener
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();
@@ -282,8 +280,7 @@ public boolean processActionbarPacket(Packet> packet, GenericFutureListener
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;
}
@@ -609,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;
}
@@ -949,7 +946,7 @@ public boolean processPacketHandlerForPacket(Packet> 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/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 6fa2f7d5f2..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,9 +4,8 @@
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.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 +95,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) {
@@ -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 4d830865e1..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,7 @@
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;
import com.denizenscript.denizen.utilities.blocks.FakeBlock;
@@ -37,8 +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.md_5.bungee.chat.ComponentSerializer;
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 ex
}
String modeText = update.getGameMode() == null ? null : update.getGameMode().name();
PlayerReceivesTablistUpdateScriptEvent.TabPacketData data = new PlayerReceivesTablistUpdateScriptEvent.TabPacketData(mode, profile.getId(), true, profile.getName(),
- update.getDisplayName() == null ? null : FormattedTextHelper.stringify(Handler.componentToSpigot(update.getDisplayName())), modeText, texture, signature, update.getLatency());
+ update.getDisplayName() == null ? null : Handler.stringifyNMSComponent(update.getDisplayName()), modeText, texture, signature, update.getLatency());
PlayerReceivesTablistUpdateScriptEvent.fire(player.getBukkitEntity(), data);
if (data.modified) {
if (!isOverriding) {
@@ -373,7 +371,7 @@ public boolean processTablistPacket(Packet> packet, GenericFutureListener ex
newProfile.getProperties().put("textures", new Property("textures", data.texture, data.signature));
}
newPacket.getEntries().add(new ClientboundPlayerInfoPacket.PlayerUpdate(newProfile, data.latency, data.gamemode == null ? null : GameType.byName(CoreUtilities.toLowerCase(data.gamemode)),
- data.display == null ? null : Handler.componentToNMS(FormattedTextHelper.parse(data.display, ChatColor.WHITE))));
+ data.display == null ? null : Handler.parseNMSComponent(data.display, PaperAPITools.BaseColor.WHITE)));
oldManager.send(newPacket, genericfuturelistener);
}
}
@@ -395,10 +393,10 @@ public boolean processActionbarPacket(Packet> packet, GenericFutureListener
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();
@@ -406,8 +404,7 @@ public boolean processActionbarPacket(Packet> packet, GenericFutureListener
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;
}
@@ -758,7 +755,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;
}
@@ -1118,7 +1115,7 @@ public boolean processPacketHandlerForPacket(Packet> 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/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 395b31fb0a..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,10 +4,9 @@
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.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 +97,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) {
@@ -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 60724c27f0..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,7 @@
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;
import com.denizenscript.denizen.utilities.blocks.FakeBlock;
@@ -35,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;
@@ -409,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) {
@@ -427,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);
}
}
@@ -464,10 +463,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 +474,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;
}
@@ -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);
@@ -1237,7 +1235,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/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 c8b1400c6a..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;
@@ -22,6 +21,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 +106,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) {
@@ -192,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..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
@@ -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;
@@ -16,14 +15,11 @@
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.md_5.bungee.api.ChatColor;
import net.minecraft.advancements.critereon.BlockPredicate;
import net.minecraft.core.*;
import net.minecraft.core.component.DataComponentMap;
@@ -70,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;
@@ -203,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
@@ -446,7 +430,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 +442,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 +454,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 +468,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/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/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_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/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..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
@@ -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;
@@ -16,14 +15,11 @@
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.md_5.bungee.api.ChatColor;
import net.minecraft.advancements.critereon.BlockPredicate;
import net.minecraft.advancements.critereon.DataComponentMatchers;
import net.minecraft.core.*;
@@ -315,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
@@ -556,7 +539,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 +551,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 +563,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 +577,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/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/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)));
}
}
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