Build Chat API over Adventure instead of Bungeecord-chat

This commit is contained in:
2021-07-09 00:27:59 +02:00
parent 80cc70a570
commit 304faa072e
10 changed files with 240 additions and 131 deletions

View File

@@ -13,6 +13,13 @@
<packaging>jar</packaging>
<name>PandaLib-Core</name>
<repositories>
<repository>
<id>sonatype-oss-snapshots</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
</repository>
</repositories>
<dependencies>
<dependency>
@@ -21,6 +28,19 @@
<version>${bungeecord.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-api</artifactId>
<version>4.7.0</version>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-platform-bungeecord</artifactId>
<version>4.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.github.classgraph</groupId>
<artifactId>classgraph</artifactId>

View File

@@ -1,39 +1,53 @@
package fr.pandacube.lib.core.chat;
import java.awt.Color;
import java.util.UUID;
import java.util.Objects;
import java.util.function.Supplier;
import java.util.function.UnaryOperator;
import org.checkerframework.checker.nullness.qual.NonNull;
import net.kyori.adventure.key.Key;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.ComponentLike;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.event.HoverEventSource;
import net.kyori.adventure.text.format.Style;
import net.kyori.adventure.text.format.TextColor;
import net.kyori.adventure.text.format.TextDecoration;
import net.kyori.adventure.text.format.TextDecoration.State;
import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.ItemTag;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.chat.hover.content.Content;
import net.md_5.bungee.api.chat.hover.content.Entity;
import net.md_5.bungee.api.chat.hover.content.Item;
import net.md_5.bungee.api.chat.hover.content.Text;
public abstract class Chat extends ChatStatic {
public abstract class Chat extends ChatStatic implements HoverEventSource<Component>, ComponentLike {
protected BaseComponent component;
protected Component component;
protected boolean console = false;
public Chat(BaseComponent c) {
public Chat(Component c) {
Objects.requireNonNull(c, "Provided component must not be null");
component = c;
}
public BaseComponent get() {
return toBungee(component);
}
public Component getAdv() {
return component;
}
public BaseComponent[] getAsArray() {
return new BaseComponent[] { component };
return toBungeeArray(component);
}
public String getLegacyText() {
return component.toLegacyText();
return LegacyComponentSerializer.legacySection().serializeOr(component, "");
}
@@ -41,30 +55,30 @@ public abstract class Chat extends ChatStatic {
public Chat then(BaseComponent subComponent) {
// here are some optimizations to avoid unnecessary component nesting
if (subComponent instanceof TextComponent) {
TextComponent txtComp = (TextComponent) subComponent;
if (!txtComp.hasFormatting() && (txtComp.getText() == null || txtComp.getText().isEmpty())) {
return then(toAdventure(subComponent));
}
public Chat then(Chat comp) {
return then(comp.getAdv());
}
public Chat then(BaseComponent[] components) {
return then(toAdventure(components));
}
public Chat then(Component comp) {
if (comp instanceof TextComponent) {
TextComponent txtComp = (TextComponent) comp;
if (!txtComp.hasStyling() && (txtComp.content() == null || txtComp.content().isEmpty())) {
// no need to add the provided component to the current component.
// but eventual child component must be added
if (txtComp.getExtra() != null) {
for (BaseComponent child : txtComp.getExtra())
if (txtComp.children() != null && !txtComp.children().isEmpty()) {
for (Component child : txtComp.children())
then(child);
}
return this;
}
}
component.addExtra(subComponent);
return this;
}
public Chat then(Chat comp) { return then(comp.get()); }
public Chat then(BaseComponent[] components) {
if (components != null) {
for (BaseComponent c : components) {
then(c);
}
}
component.append(comp);
return this;
}
@@ -82,7 +96,7 @@ public abstract class Chat extends ChatStatic {
public Chat thenPlayerName(String legacyText) { return then(playerNameText(legacyText)); }
public Chat thenNewLine() { return thenText("\n"); }
public Chat thenNewLine() { return then(Component.newline()); }
public Chat thenLegacyText(Object legacyText) { return then(legacyText(legacyText)); }
@@ -90,7 +104,7 @@ public abstract class Chat extends ChatStatic {
public Chat thenKeyBind(String key) { return then(keybind(key)); }
public Chat thenScore(String name, String objective, String value) { return then(score(name, objective, value)); }
public Chat thenScore(String name, String objective) { return then(score(name, objective)); }
@@ -191,13 +205,14 @@ public abstract class Chat extends ChatStatic {
public static class FormatableChat extends Chat {
public FormatableChat(BaseComponent c) {
public FormatableChat(Component c) {
super(c);
}
public FormatableChat console(boolean c) { console = c; return this; }
public FormatableChat color(ChatColor c) { component.setColor(c); return this; }
public FormatableChat color(TextColor c) { component.color(c); return this; }
public FormatableChat color(ChatColor c) { return color(TextColor.color(c.getColor().getRGB())); }
public FormatableChat color(Color c) { return color(ChatColor.of(c)); }
public FormatableChat color(String c) { return color(ChatColor.of(c)); }
@@ -224,63 +239,52 @@ public abstract class Chat extends ChatStatic {
public FormatableChat dataColor() { return color(config.dataColor); }
public FormatableChat decorationColor() { return color(config.decorationColor); }
public FormatableChat font(String f) { component.setFont(f); return this; }
private FormatableChat setStyle(UnaryOperator<Style> styleOp) {
component.style(styleOp.apply(component.style()));
return this;
}
private FormatableChat setDecoration(TextDecoration deco, Boolean state) {
return setStyle(s -> s.decoration(deco, State.byBoolean(state)));
}
public FormatableChat bold(Boolean b) { component.setBold(b); return this; }
public FormatableChat font(Key f) { return setStyle(s -> s.font(f)); }
public FormatableChat bold(Boolean b) { return setDecoration(TextDecoration.BOLD, b); }
public FormatableChat bold() { return bold(true); }
public FormatableChat italic(Boolean i) { component.setItalic(i); return this; }
public FormatableChat italic(Boolean i) { return setDecoration(TextDecoration.ITALIC, i); }
public FormatableChat italic() { return italic(true); }
public FormatableChat underlined(Boolean u) { component.setUnderlined(u); return this; }
public FormatableChat underlined(Boolean u) { return setDecoration(TextDecoration.UNDERLINED, u); }
public FormatableChat underlined() { return underlined(true); }
public FormatableChat strikethrough(Boolean s) { component.setStrikethrough(s); return this; }
public FormatableChat strikethrough(Boolean s) { return setDecoration(TextDecoration.STRIKETHROUGH, s); }
public FormatableChat strikethrough() { return strikethrough(true); }
public FormatableChat obfuscated(Boolean o) { component.setObfuscated(o); return this; }
public FormatableChat obfuscated(Boolean o) { return setDecoration(TextDecoration.OBFUSCATED, o); }
public FormatableChat obfuscated() { return obfuscated(true); }
public FormatableChat shiftClickInsertion(String i) { component.setInsertion(i); return this; }
public FormatableChat shiftClickInsertion(String i) { component.insertion(i); return this; }
private FormatableChat clickEvent(ClickEvent e) { component.setClickEvent(e); return this; }
private FormatableChat clickEvent(ClickEvent.Action a, String v) { return clickEvent(new ClickEvent(a, v)); }
public FormatableChat clickCommand(String cmdWithSlash) { return clickEvent(ClickEvent.Action.RUN_COMMAND, cmdWithSlash); }
public FormatableChat clickSuggest(String cmdWithSlash) { return clickEvent(ClickEvent.Action.SUGGEST_COMMAND, cmdWithSlash); }
public FormatableChat clickClipboard(String value) { return clickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, value); }
public FormatableChat clickURL(String url) { return clickEvent(ClickEvent.Action.OPEN_URL, url); }
public FormatableChat clickBookPage(int page) { return clickEvent(ClickEvent.Action.CHANGE_PAGE, Integer.toString(page)); }
private FormatableChat click(ClickEvent e) { component.clickEvent(e); return this; }
public FormatableChat clickCommand(String cmdWithSlash) { return click(ClickEvent.runCommand(cmdWithSlash)); }
public FormatableChat clickSuggest(String cmdWithSlash) { return click(ClickEvent.suggestCommand(cmdWithSlash)); }
public FormatableChat clickClipboard(String value) { return click(ClickEvent.copyToClipboard(value)); }
public FormatableChat clickURL(String url) { return click(ClickEvent.openUrl(url)); }
public FormatableChat clickBookPage(int page) { return click(ClickEvent.changePage(page)); }
private FormatableChat hoverEvent(HoverEvent e) { component.setHoverEvent(e); return this; }
private FormatableChat hoverEvent(HoverEvent.Action a, Content v) { return hoverEvent(new HoverEvent(a, v)); }
private FormatableChat hoverText(Text v) { return hoverEvent(HoverEvent.Action.SHOW_TEXT, v); }
@SuppressWarnings("deprecation")
public FormatableChat hoverText(BaseComponent v) {
try {
return hoverText(new Text( new BaseComponent[] {v}));
} catch (NoSuchMethodError e) {
return hoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new BaseComponent[] {v}));
}
}
public FormatableChat hoverText(Chat v) { return hoverText(v.get()); }
public FormatableChat hoverText(String legacyText) { return hoverText(legacyText(legacyText)); }
private FormatableChat hoverItem(Item v) { return hoverEvent(HoverEvent.Action.SHOW_ITEM, v); }
/** @param id namespaced item id */
public FormatableChat hoverItem(String id, int stackSize, ItemTag tag) { return hoverItem(new Item(id, stackSize, tag)); }
/** @param id namespaced item id */
public FormatableChat hoverItem(String id, int stackSize) { return hoverItem(id, stackSize, null); }
/** @param id namespaced item id */
public FormatableChat hoverItem(String id, ItemTag tag) { return hoverItem(id, -1, tag); }
/** @param id namespaced item id */
public FormatableChat hoverItem(String id) { return hoverItem(id, -1, null); }
public FormatableChat hoverEntity(Entity e) { return hoverEvent(HoverEvent.Action.SHOW_ENTITY, e); }
/** @param type namespaced entity type
* @param id cannot be null */
public FormatableChat hoverEntity(String type, UUID id, BaseComponent displayName) { return hoverEntity(new Entity(type, id.toString(), displayName)); }
/** @param type namespaced entity type
* @param id cannot be null */
public FormatableChat hoverEntity(String type, UUID id) { return hoverEntity(type, id, null); }
public FormatableChat hover(HoverEventSource<?> e) { component.hoverEvent(e); return this; }
public FormatableChat hover(Chat v) { return hover(v.getAdv()); }
public FormatableChat hover(BaseComponent v) { return hover(toAdventure(v)); }
public FormatableChat hover(BaseComponent[] v) { return hover(toAdventure(v)); }
public FormatableChat hover(String legacyText) { return hover(legacyText(legacyText)); }
@Deprecated
public FormatableChat hoverText(BaseComponent v) { return hover(v); }
@Deprecated
public FormatableChat hoverText(Chat v) { return hover(v); }
@Deprecated
public FormatableChat hoverText(String legacyText) { return hover(legacyText); }
}
@@ -289,6 +293,18 @@ public abstract class Chat extends ChatStatic {
@Override
public @NonNull HoverEvent<Component> asHoverEvent(@NonNull UnaryOperator<Component> op) {
return HoverEvent.showText(op.apply(getAdv()));
}
@Override
public @NonNull Component asComponent() {
return getAdv();
}
@@ -305,9 +321,51 @@ public abstract class Chat extends ChatStatic {
}
return values;
}
/* package */ static ComponentLike[] filterObjToComponentLike(Object[] values) {
if (values == null)
return null;
ComponentLike[] ret = new ComponentLike[values.length];
for (int i = 0; i < values.length; i++) {
Object v = values[i];
if (v instanceof Chat)
ret[i] = ((Chat) v).getAdv();
else if (v instanceof BaseComponent[])
ret[i] = toAdventure((BaseComponent[]) v);
else if (v instanceof BaseComponent)
ret[i] = toAdventure((BaseComponent) v);
else
ret[i] = Component.text(Objects.toString(v));
}
return ret;
}
/* package */ static Component toAdventure(BaseComponent[] components) {
return BungeeComponentSerializer.get().deserialize(components);
}
/* package */ static Component toAdventure(BaseComponent component) {
return toAdventure(new BaseComponent[] { component });
}
/* package */ static BaseComponent[] toBungeeArray(Component component) {
return BungeeComponentSerializer.get().serialize(component);
}
/* package */ static BaseComponent toBungee(Component component) {
BaseComponent[] arr = toBungeeArray(component);
return arr.length == 1 ? arr[0] : new net.md_5.bungee.api.chat.TextComponent(arr);
}
public static Chat italicFalseIfNotSet(Chat c) {
if (c instanceof FormatableChat) {
if (c.component.style().decoration(TextDecoration.ITALIC) == State.NOT_SET)
((FormatableChat) c).italic(false);
}
return c;
}

View File

@@ -3,31 +3,32 @@ package fr.pandacube.lib.core.chat;
import java.util.Objects;
import fr.pandacube.lib.core.chat.Chat.FormatableChat;
import net.kyori.adventure.text.Component;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.KeybindComponent;
import net.md_5.bungee.api.chat.Keybinds;
import net.md_5.bungee.api.chat.ScoreComponent;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.chat.TranslatableComponent;
public abstract class ChatStatic {
public static FormatableChat chatComponent(Component c) {
return new FormatableChat(c);
}
public static FormatableChat chatComponent(BaseComponent c) {
return new FormatableChat(c);
return new FormatableChat(Chat.toAdventure(c));
}
public static FormatableChat chat() {
return chatComponent(new TextComponent());
return chatComponent(Component.empty());
}
public static FormatableChat chatComponent(BaseComponent[] c) {
return chatComponent(new TextComponent(c));
return chatComponent(Chat.toAdventure(c));
}
public static FormatableChat text(Object plainText) {
return chatComponent(new TextComponent(Objects.toString(plainText)));
return chatComponent(Component.text(Objects.toString(plainText)));
}
public static FormatableChat legacyText(Object legacyText) {
@@ -59,15 +60,15 @@ public abstract class ChatStatic {
}
public static FormatableChat translation(String key, Object... with) {
return chatComponent(new TranslatableComponent(key, Chat.filterChatToBaseComponent(with)));
return chatComponent(Component.translatable(key, Chat.filterObjToComponentLike(with)));
}
/** @param key one of the values in {@link Keybinds}. */
/** @param key one of the values in {@link net.md_5.bungee.api.chat.Keybinds} */
public static FormatableChat keybind(String key) {
return chatComponent(new KeybindComponent(key));
return chatComponent(Component.keybind(key));
}
public static FormatableChat score(String name, String objective, String value) {
return chatComponent(new ScoreComponent(name, objective, value));
public static FormatableChat score(String name, String objective) {
return chatComponent(Component.score(name, objective));
}
}

View File

@@ -60,7 +60,7 @@ public class ChatUtil {
return chat()
.clickURL(url)
.color(Chat.getConfig().urlColor)
.hoverText(
.hover(
hover != null ? hover : Chat.text(dispURL)
)
.then(element)
@@ -86,7 +86,7 @@ public class ChatUtil {
.clickCommand(commandWithSlash)
.color(Chat.getConfig().commandColor);
if (hoverText != null)
c.hoverText(hoverText);
c.hover(hoverText);
return c.then(d).get();
}
@@ -111,7 +111,7 @@ public class ChatUtil {
.clickSuggest(commandWithSlash)
.color(Chat.getConfig().commandColor);
if (hoverText != null)
c.hoverText(hoverText);
c.hover(hoverText);
return c.then(d).get();
}