Compare commits

...

7 Commits

51 changed files with 416 additions and 353 deletions

View File

@ -9,11 +9,11 @@ that are detailed in their respective Readme file (if any).
- `pandalib-util` General purpose utility and helper classes; - `pandalib-util` General purpose utility and helper classes;
- `pandalib-chat` A chat API working on top of the Adventure API; - `pandalib-chat` A chat API working on top of the Adventure API;
- `pandalib-db` An ORM working with a MySQL server through JDBC; - `pandalib-db` An ORM working with a MySQL server through JDBC;
- `pandalib-bungee` Utility and helper classes to use in Bungeecord plugins. Also provides platform implementation for `pandalib-players` and `pandalib-commands`; - `pandalib-bungee` Utility and helper classes to use in BungeeCord plugins. Also provides platform implementation for `pandalib-players` and `pandalib-commands`;
- `pandalib-paper` Utility and helper classes to use in Spigot/Paper plugins. Also provides platform implementation for `pandalib-players` and `pandalib-commands`; - `pandalib-paper` Utility and helper classes to use in Spigot/Paper plugins. Also provides platform implementation for `pandalib-players` and `pandalib-commands`;
- `pandalib-reflect` A reflection wrapper to make reflective operation easier; - `pandalib-reflect` A reflection wrapper to make reflective operation easier;
- `pandalib-permissions` A general purpose permission system; - `pandalib-permissions` A general purpose permission system;
- `pandalib-bungee-permissions` Integration of the permission system `pandalib-permissions` into Bungeecord; - `pandalib-bungee-permissions` Integration of the permission system `pandalib-permissions` into BungeeCord;
- `pandalib-paper-permissions` Integration of the permission system `pandalib-permissions` into Bukkit, Vault and WEPIF permission systems; - `pandalib-paper-permissions` Integration of the permission system `pandalib-permissions` into Bukkit, Vault and WEPIF permission systems;
- `pandalib-players` A library to handle classes representing online or offline players; - `pandalib-players` A library to handle classes representing online or offline players;
- `pandalib-players-permissible` An extension of `pandalib-players` with support for the permission system `pandalib-permissions`; - `pandalib-players-permissible` An extension of `pandalib-players` with support for the permission system `pandalib-permissions`;

View File

@ -21,11 +21,6 @@
</repositories> </repositories>
<dependencies> <dependencies>
<dependency>
<groupId>fr.pandacube.lib</groupId>
<artifactId>pandalib-util</artifactId>
<version>${project.version}</version>
</dependency>
<dependency> <dependency>
<groupId>fr.pandacube.lib</groupId> <groupId>fr.pandacube.lib</groupId>
<artifactId>pandalib-chat</artifactId> <artifactId>pandalib-chat</artifactId>

View File

@ -1,7 +1,7 @@
package fr.pandacube.lib.bungee.chat; package fr.pandacube.lib.bungee.chat;
import fr.pandacube.lib.chat.Chat; import fr.pandacube.lib.chat.Chat;
import fr.pandacube.lib.chat.Chat.FormatableChat; import fr.pandacube.lib.chat.Chat.FormattableChat;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.ComponentLike; import net.kyori.adventure.text.ComponentLike;
import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer; import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer;
@ -15,22 +15,22 @@ public class ChatBungee {
/** /**
* Creates a {@link FormatableChat} from the provided Bungee {@link BaseComponent}. * Creates a {@link FormattableChat} from the provided Bungee {@link BaseComponent}.
* @param c the {@link BaseComponent}. * @param c the {@link BaseComponent}.
* @return a new {@link FormatableChat}. * @return a new {@link FormattableChat}.
*/ */
public static FormatableChat chatComponent(BaseComponent c) { public static FormattableChat chatComponent(BaseComponent c) {
return Chat.chatComponent(toAdventure(c)); return Chat.chatComponent(toAdventure(c));
} }
/** /**
* Creates a {@link FormatableChat} from the provided Bungee {@link BaseComponent BaseComponent[]}. * Creates a {@link FormattableChat} from the provided Bungee {@link BaseComponent BaseComponent[]}.
* @param c the array of {@link BaseComponent}. * @param c the array of {@link BaseComponent}.
* @return a new {@link FormatableChat}. * @return a new {@link FormattableChat}.
*/ */
public static FormatableChat chatComponent(BaseComponent[] c) { public static FormattableChat chatComponent(BaseComponent[] c) {
return Chat.chatComponent(toAdventure(c)); return Chat.chatComponent(toAdventure(c));
} }

View File

@ -1,7 +1,7 @@
package fr.pandacube.lib.bungee; package fr.pandacube.lib.bungee;
import fr.pandacube.lib.bungee.util.BungeeDailyLogRotateFileHandler; import fr.pandacube.lib.bungee.util.BungeeDailyLogRotateFileHandler;
import fr.pandacube.lib.bungee.util.PluginMessagePassthrough; import fr.pandacube.lib.bungee.util.PluginMessagePassThrough;
import net.md_5.bungee.api.plugin.Plugin; import net.md_5.bungee.api.plugin.Plugin;
/** /**
@ -24,7 +24,7 @@ public class PandaLibBungee {
* Method to be called in {@link Plugin#onEnable()} method. * Method to be called in {@link Plugin#onEnable()} method.
*/ */
public static void onEnable() { public static void onEnable() {
PluginMessagePassthrough.init(plugin); PluginMessagePassThrough.init(plugin);
BungeeDailyLogRotateFileHandler.init(true); BungeeDailyLogRotateFileHandler.init(true);
} }

View File

@ -7,7 +7,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
* Class that holds the configuration varables for {@link BungeeBackupManager}. * Class that holds the configuration variables for {@link BungeeBackupManager}.
*/ */
@SuppressWarnings("CanBeFinal") @SuppressWarnings("CanBeFinal")
public class BungeeBackupConfig { public class BungeeBackupConfig {

View File

@ -7,14 +7,14 @@ import fr.pandacube.lib.core.backup.RotatedLogsBackupProcess;
import java.io.File; import java.io.File;
/** /**
* Handles the backup processes for a Bungeecord instance. * Handles the backup processes for a BungeeCord instance.
*/ */
public class BungeeBackupManager extends BackupManager { public class BungeeBackupManager extends BackupManager {
BungeeBackupConfig config; BungeeBackupConfig config;
/** /**
* Instanciate a new {@link BungeeBackupManager}. * Creates a new {@link BungeeBackupManager}.
* @param config the configuration. * @param config the configuration.
*/ */
public BungeeBackupManager(BungeeBackupConfig config) { public BungeeBackupManager(BungeeBackupConfig config) {

View File

@ -6,7 +6,7 @@ import java.io.File;
import java.util.function.BiPredicate; import java.util.function.BiPredicate;
/** /**
* The backup process responsible for the working directory of the current Bungeecord instance. * The backup process responsible for the working directory of the current BungeeCord instance.
*/ */
public class BungeeWorkdirProcess extends BackupProcess { public class BungeeWorkdirProcess extends BackupProcess {

View File

@ -6,7 +6,7 @@ import net.md_5.bungee.api.connection.ProxiedPlayer;
import fr.pandacube.lib.players.standalone.AbstractOffPlayer; import fr.pandacube.lib.players.standalone.AbstractOffPlayer;
/** /**
* Represents any player on a Bungeecord proxy, either offline or online. * Represents any player on a BungeeCord proxy, either offline or online.
*/ */
public interface BungeeOffPlayer extends AbstractOffPlayer { public interface BungeeOffPlayer extends AbstractOffPlayer {

View File

@ -20,7 +20,7 @@ import net.md_5.bungee.protocol.packet.PluginMessage;
import java.util.Locale; import java.util.Locale;
/** /**
* Represents any online player on a Bungeecord proxy. * Represents any online player on a BungeeCord proxy.
*/ */
public interface BungeeOnlinePlayer extends BungeeOffPlayer, AbstractOnlinePlayer { public interface BungeeOnlinePlayer extends BungeeOffPlayer, AbstractOnlinePlayer {

View File

@ -19,16 +19,16 @@ import net.md_5.bungee.event.EventHandler;
* <p> * <p>
* Usage example, in your plugin init code: * Usage example, in your plugin init code:
* <pre>{@code * <pre>{@code
* PluginMessagePassthrough.init(yourPluginInstance); * PluginMessagePassThrough.init(yourPluginInstance);
* PluginMessagePassthrough.register("worldedit:cui"); // plugin message used by WorldEdit * PluginMessagePassThrough.register("worldedit:cui"); // plugin message used by WorldEdit
* }</pre> * }</pre>
*/ */
public class PluginMessagePassthrough implements Listener { public class PluginMessagePassThrough implements Listener {
private static final List<String> channels = Collections.synchronizedList(new ArrayList<>()); private static final List<String> channels = Collections.synchronizedList(new ArrayList<>());
private static final PluginMessagePassthrough instance = new PluginMessagePassthrough(); private static final PluginMessagePassThrough instance = new PluginMessagePassThrough();
/** /**
* Initialize the {@link PluginMessagePassthrough}. * Initialize the {@link PluginMessagePassThrough}.
* It registers the required event listener. * It registers the required event listener.
* @param plugin the plugin instance. * @param plugin the plugin instance.
*/ */
@ -92,7 +92,7 @@ public class PluginMessagePassthrough implements Listener {
} }
private PluginMessagePassthrough() { } private PluginMessagePassThrough() { }
/** /**

View File

@ -35,8 +35,8 @@ import java.util.function.UnaryOperator;
* This class implements {@link ComponentLike} and {@link HoverEventSource} so they can be used directly in * This class implements {@link ComponentLike} and {@link HoverEventSource} so they can be used directly in
* Adventure API and its implementation without using the final methods of this builder. * Adventure API and its implementation without using the final methods of this builder.
* <p> * <p>
* The unique possible concrete subclass of this class, {@link FormatableChat}, takes care of the formatting of the * The unique possible concrete subclass of this class, {@link FormattableChat}, takes care of the formatting of the
* built component. The rationale for this design is explained in the documentation of {@link FormatableChat}. * built component. The rationale for this design is explained in the documentation of {@link FormattableChat}.
*/ */
public abstract sealed class Chat extends ChatStatic implements HoverEventSource<Component>, ComponentLike { public abstract sealed class Chat extends ChatStatic implements HoverEventSource<Component>, ComponentLike {
@ -296,7 +296,7 @@ public abstract sealed class Chat extends ChatStatic implements HoverEventSource
* @param key the keybinding to display. * @param key the keybinding to display.
* @return this. * @return this.
*/ */
public Chat thenKeyBind(String key) { return then(keybind(key)); } public Chat thenKeyBind(String key) { return then(keyBind(key)); }
/** /**
* Appends a component with the provided score name and objective. * Appends a component with the provided score name and objective.
@ -454,7 +454,7 @@ public abstract sealed class Chat extends ChatStatic implements HoverEventSource
* Appends a component filling a chat line with the configured decoration character and * Appends a component filling a chat line with the configured decoration character and
* color and a left-aligned text. * color and a left-aligned text.
* @param leftText the text aligned to the left. * @param leftText the text aligned to the left.
* @return a new {@link FormatableChat} filling a chat line with the configured decoration character * @return a new {@link FormattableChat} filling a chat line with the configured decoration character
* and color and a left-aligned text. * and color and a left-aligned text.
*/ */
public Chat thenLeftText(ComponentLike leftText) { return then(leftText(leftText, console)); } public Chat thenLeftText(ComponentLike leftText) { return then(leftText(leftText, console)); }
@ -463,7 +463,7 @@ public abstract sealed class Chat extends ChatStatic implements HoverEventSource
* Appends a component filling a chat line with the configured decoration character and * Appends a component filling a chat line with the configured decoration character and
* color and a right-aligned text. * color and a right-aligned text.
* @param rightText the text aligned to the right. * @param rightText the text aligned to the right.
* @return a new {@link FormatableChat} filling a chat line with the configured decoration character * @return a new {@link FormattableChat} filling a chat line with the configured decoration character
* and color and a right-aligned text. * and color and a right-aligned text.
*/ */
public Chat thenRightText(ComponentLike rightText) { return then(rightText(rightText, console)); } public Chat thenRightText(ComponentLike rightText) { return then(rightText(rightText, console)); }
@ -472,7 +472,7 @@ public abstract sealed class Chat extends ChatStatic implements HoverEventSource
* Appends a component filling a chat line with the configured decoration character and * Appends a component filling a chat line with the configured decoration character and
* color and a centered text. * color and a centered text.
* @param centerText the text aligned to the center. * @param centerText the text aligned to the center.
* @return a new {@link FormatableChat} filling a chat line with the configured decoration character * @return a new {@link FormattableChat} filling a chat line with the configured decoration character
* and color and a centered text. * and color and a centered text.
*/ */
public Chat thenCenterText(ComponentLike centerText) { public Chat thenCenterText(ComponentLike centerText) {
@ -481,7 +481,7 @@ public abstract sealed class Chat extends ChatStatic implements HoverEventSource
/** /**
* Appends a component filling a chat line with the configured decoration character and color. * Appends a component filling a chat line with the configured decoration character and color.
* @return a new {@link FormatableChat} filling a chat line with a decoration character and color. * @return a new {@link FormattableChat} filling a chat line with a decoration character and color.
*/ */
public Chat thenFilledLine() { return then(filledLine(console)); } public Chat thenFilledLine() { return then(filledLine(console)); }
@ -520,10 +520,10 @@ public abstract sealed class Chat extends ChatStatic implements HoverEventSource
* .thenText("!"); // short for .then(Chat.text("!")) * .thenText("!"); // short for .then(Chat.text("!"))
* // the red color for "!" is not needed because the parent component is already red. * // the red color for "!" is not needed because the parent component is already red.
* }</pre> * }</pre>
* When calling {@link #then(Component) #then(...)} on a {@link FormatableChat}, the method returns itself, cast * When calling {@link #then(Component) #then(...)} on a {@link FormattableChat}, the method returns itself, cast
* to {@link Chat}, to prevent future formatting (that the programmer would think it formats the previously appended * to {@link Chat}, to prevent future formatting (that the programmer would think it formats the previously appended
* subcomponent). If the formatting of the currently built component is needed, since {@link Chat} is a sealed * subcomponent). If the formatting of the currently built component is needed, since {@link Chat} is a sealed
* class which only subclass is {@link FormatableChat}, you can cast the builder, and use the format methods again. * class which only subclass is {@link FormattableChat}, you can cast the builder, and use the format methods again.
* <pre>{@code * <pre>{@code
* Chat component = Chat.text("Hello ").red() * Chat component = Chat.text("Hello ").red()
* .then(Chat.text("world").darkRed().bold()) * .then(Chat.text("world").darkRed().bold())
@ -532,8 +532,8 @@ public abstract sealed class Chat extends ChatStatic implements HoverEventSource
* ((FormatableChat)component).underlined(); // this will not format only the last appended text. * ((FormatableChat)component).underlined(); // this will not format only the last appended text.
* }</pre> * }</pre>
*/ */
public static final class FormatableChat extends Chat { public static final class FormattableChat extends Chat {
/* package */ FormatableChat(ComponentBuilder<?, ?> c) { /* package */ FormattableChat(ComponentBuilder<?, ?> c) {
super(c); super(c);
} }
@ -543,33 +543,33 @@ public abstract sealed class Chat extends ChatStatic implements HoverEventSource
* @param c true for console, false for game UI. * @param c true for console, false for game UI.
* @return this. * @return this.
*/ */
public FormatableChat console(boolean c) { console = c; return this; } public FormattableChat console(boolean c) { console = c; return this; }
/** /**
* Configure the width of the line. * Configure the width of the line.
* @param w the width to consider when rendering the line. In pixel for game UI rendering, n character for * @param w the width to consider when rendering the line. In pixel for game UI rendering, n character for
* console rendering. * console rendering.
* @return this. * @return this.
*/ */
public FormatableChat maxWidth(int w) { maxWidth = w; return this; } public FormattableChat maxWidth(int w) { maxWidth = w; return this; }
/** /**
* Sets the color of this component. * Sets the color of this component.
* @param c the color. * @param c the color.
* @return this. * @return this.
*/ */
public FormatableChat color(TextColor c) { builder.color(c); return this; } public FormattableChat color(TextColor c) { builder.color(c); return this; }
/** /**
* Sets the color of this component. * Sets the color of this component.
* @param c the color. * @param c the color.
* @return this. * @return this.
*/ */
public FormatableChat color(Color c) { return color(c == null ? null : TextColor.color(c.getRGB())); } public FormattableChat color(Color c) { return color(c == null ? null : TextColor.color(c.getRGB())); }
/** /**
* Sets the color of this component. * Sets the color of this component.
* @param c the color. * @param c the color.
* @return this. * @return this.
*/ */
public FormatableChat color(String c) { public FormattableChat color(String c) {
if (c == null) if (c == null)
return color((TextColor) null); return color((TextColor) null);
TextColor tc = c.startsWith("#") TextColor tc = c.startsWith("#")
@ -585,138 +585,138 @@ public abstract sealed class Chat extends ChatStatic implements HoverEventSource
* Sets the color of this component to {@link NamedTextColor#BLACK}. * Sets the color of this component to {@link NamedTextColor#BLACK}.
* @return this. * @return this.
*/ */
public FormatableChat black() { return color(NamedTextColor.BLACK); } public FormattableChat black() { return color(NamedTextColor.BLACK); }
/** /**
* Sets the color of this component to {@link NamedTextColor#DARK_BLUE}. * Sets the color of this component to {@link NamedTextColor#DARK_BLUE}.
* @return this. * @return this.
*/ */
public FormatableChat darkBlue() { return color(NamedTextColor.DARK_BLUE); } public FormattableChat darkBlue() { return color(NamedTextColor.DARK_BLUE); }
/** /**
* Sets the color of this component to {@link NamedTextColor#DARK_GREEN}. * Sets the color of this component to {@link NamedTextColor#DARK_GREEN}.
* @return this. * @return this.
*/ */
public FormatableChat darkGreen() { return color(NamedTextColor.DARK_GREEN); } public FormattableChat darkGreen() { return color(NamedTextColor.DARK_GREEN); }
/** /**
* Sets the color of this component to {@link NamedTextColor#DARK_AQUA}. * Sets the color of this component to {@link NamedTextColor#DARK_AQUA}.
* @return this. * @return this.
*/ */
public FormatableChat darkAqua() { return color(NamedTextColor.DARK_AQUA); } public FormattableChat darkAqua() { return color(NamedTextColor.DARK_AQUA); }
/** /**
* Sets the color of this component to {@link NamedTextColor#DARK_RED}. * Sets the color of this component to {@link NamedTextColor#DARK_RED}.
* @return this. * @return this.
*/ */
public FormatableChat darkRed() { return color(NamedTextColor.DARK_RED); } public FormattableChat darkRed() { return color(NamedTextColor.DARK_RED); }
/** /**
* Sets the color of this component to {@link NamedTextColor#DARK_PURPLE}. * Sets the color of this component to {@link NamedTextColor#DARK_PURPLE}.
* @return this. * @return this.
*/ */
public FormatableChat darkPurple() { return color(NamedTextColor.DARK_PURPLE); } public FormattableChat darkPurple() { return color(NamedTextColor.DARK_PURPLE); }
/** /**
* Sets the color of this component to {@link NamedTextColor#GOLD}. * Sets the color of this component to {@link NamedTextColor#GOLD}.
* @return this. * @return this.
*/ */
public FormatableChat gold() { return color(NamedTextColor.GOLD); } public FormattableChat gold() { return color(NamedTextColor.GOLD); }
/** /**
* Sets the color of this component to {@link NamedTextColor#GRAY}. * Sets the color of this component to {@link NamedTextColor#GRAY}.
* @return this. * @return this.
*/ */
public FormatableChat gray() { return color(NamedTextColor.GRAY); } public FormattableChat gray() { return color(NamedTextColor.GRAY); }
/** /**
* Sets the color of this component to {@link NamedTextColor#DARK_GRAY}. * Sets the color of this component to {@link NamedTextColor#DARK_GRAY}.
* @return this. * @return this.
*/ */
public FormatableChat darkGray() { return color(NamedTextColor.DARK_GRAY); } public FormattableChat darkGray() { return color(NamedTextColor.DARK_GRAY); }
/** /**
* Sets the color of this component to {@link NamedTextColor#BLUE}. * Sets the color of this component to {@link NamedTextColor#BLUE}.
* @return this. * @return this.
*/ */
public FormatableChat blue() { return color(NamedTextColor.BLUE); } public FormattableChat blue() { return color(NamedTextColor.BLUE); }
/** /**
* Sets the color of this component to {@link NamedTextColor#GREEN}. * Sets the color of this component to {@link NamedTextColor#GREEN}.
* @return this. * @return this.
*/ */
public FormatableChat green() { return color(NamedTextColor.GREEN); } public FormattableChat green() { return color(NamedTextColor.GREEN); }
/** /**
* Sets the color of this component to {@link NamedTextColor#AQUA}. * Sets the color of this component to {@link NamedTextColor#AQUA}.
* @return this. * @return this.
*/ */
public FormatableChat aqua() { return color(NamedTextColor.AQUA); } public FormattableChat aqua() { return color(NamedTextColor.AQUA); }
/** /**
* Sets the color of this component to {@link NamedTextColor#RED}. * Sets the color of this component to {@link NamedTextColor#RED}.
* @return this. * @return this.
*/ */
public FormatableChat red() { return color(NamedTextColor.RED); } public FormattableChat red() { return color(NamedTextColor.RED); }
/** /**
* Sets the color of this component to {@link NamedTextColor#LIGHT_PURPLE}. * Sets the color of this component to {@link NamedTextColor#LIGHT_PURPLE}.
* @return this. * @return this.
*/ */
public FormatableChat lightPurple() { return color(NamedTextColor.LIGHT_PURPLE); } public FormattableChat lightPurple() { return color(NamedTextColor.LIGHT_PURPLE); }
/** /**
* Sets the color of this component to {@link NamedTextColor#YELLOW}. * Sets the color of this component to {@link NamedTextColor#YELLOW}.
* @return this. * @return this.
*/ */
public FormatableChat yellow() { return color(NamedTextColor.YELLOW); } public FormattableChat yellow() { return color(NamedTextColor.YELLOW); }
/** /**
* Sets the color of this component to {@link NamedTextColor#WHITE}. * Sets the color of this component to {@link NamedTextColor#WHITE}.
* @return this. * @return this.
*/ */
public FormatableChat white() { return color(NamedTextColor.WHITE); } public FormattableChat white() { return color(NamedTextColor.WHITE); }
/** /**
* Sets the color of this component to {@link ChatConfig#successColor}. * Sets the color of this component to {@link ChatConfig#successColor}.
* @return this. * @return this.
*/ */
public FormatableChat successColor() { return color(ChatConfig.successColor); } public FormattableChat successColor() { return color(ChatConfig.successColor); }
/** /**
* Sets the color of this component to {@link ChatConfig#failureColor}. * Sets the color of this component to {@link ChatConfig#failureColor}.
* @return this. * @return this.
*/ */
public FormatableChat failureColor() { return color(ChatConfig.failureColor); } public FormattableChat failureColor() { return color(ChatConfig.failureColor); }
/** /**
* Sets the color of this component to {@link ChatConfig#infoColor}. * Sets the color of this component to {@link ChatConfig#infoColor}.
* @return this. * @return this.
*/ */
public FormatableChat infoColor() { return color(ChatConfig.infoColor); } public FormattableChat infoColor() { return color(ChatConfig.infoColor); }
/** /**
* Sets the color of this component to {@link ChatConfig#warningColor}. * Sets the color of this component to {@link ChatConfig#warningColor}.
* @return this. * @return this.
*/ */
public FormatableChat warningColor() { return color(ChatConfig.warningColor); } public FormattableChat warningColor() { return color(ChatConfig.warningColor); }
/** /**
* Sets the color of this component to {@link ChatConfig#dataColor}. * Sets the color of this component to {@link ChatConfig#dataColor}.
* @return this. * @return this.
*/ */
public FormatableChat dataColor() { return color(ChatConfig.dataColor); } public FormattableChat dataColor() { return color(ChatConfig.dataColor); }
/** /**
* Sets the color of this component to {@link ChatConfig#decorationColor}. * Sets the color of this component to {@link ChatConfig#decorationColor}.
* @return this. * @return this.
*/ */
public FormatableChat decorationColor() { return color(ChatConfig.decorationColor); } public FormattableChat decorationColor() { return color(ChatConfig.decorationColor); }
/** /**
* Sets the color of this component to {@link ChatConfig#urlColor}. * Sets the color of this component to {@link ChatConfig#urlColor}.
* @return this. * @return this.
*/ */
public FormatableChat urlColor() { return color(ChatConfig.urlColor); } public FormattableChat urlColor() { return color(ChatConfig.urlColor); }
/** /**
* Sets the color of this component to {@link ChatConfig#commandColor}. * Sets the color of this component to {@link ChatConfig#commandColor}.
* @return this. * @return this.
*/ */
public FormatableChat commandColor() { return color(ChatConfig.commandColor); } public FormattableChat commandColor() { return color(ChatConfig.commandColor); }
/** /**
* Sets the color of this component to {@link ChatConfig#highlightedCommandColor}. * Sets the color of this component to {@link ChatConfig#highlightedCommandColor}.
* @return this. * @return this.
*/ */
public FormatableChat highlightedCommandColor() { return color(ChatConfig.highlightedCommandColor); } public FormattableChat highlightedCommandColor() { return color(ChatConfig.highlightedCommandColor); }
/** /**
* Sets the color of this component to {@link ChatConfig#broadcastColor}. * Sets the color of this component to {@link ChatConfig#broadcastColor}.
* @return this. * @return this.
*/ */
public FormatableChat broadcastColor() { return color(ChatConfig.broadcastColor); } public FormattableChat broadcastColor() { return color(ChatConfig.broadcastColor); }
private FormatableChat setStyle(Consumer<Style.Builder> styleOp) { builder.style(styleOp); return this; } private FormattableChat setStyle(Consumer<Style.Builder> styleOp) { builder.style(styleOp); return this; }
private FormatableChat setDecoration(TextDecoration deco, Boolean state) { private FormattableChat setDecoration(TextDecoration deco, Boolean state) {
return setStyle(b -> b.decoration(deco, State.byBoolean(state))); return setStyle(b -> b.decoration(deco, State.byBoolean(state)));
} }
@ -726,56 +726,56 @@ public abstract sealed class Chat extends ChatStatic implements HoverEventSource
* @param b true to enable, false to disable, or null to inherit from parent. * @param b true to enable, false to disable, or null to inherit from parent.
* @return this. * @return this.
*/ */
public FormatableChat bold(Boolean b) { return setDecoration(TextDecoration.BOLD, b); } public FormattableChat bold(Boolean b) { return setDecoration(TextDecoration.BOLD, b); }
/** /**
* Enables the bold status of this component. * Enables the bold status of this component.
* @return this. * @return this.
*/ */
public FormatableChat bold() { return bold(true); } public FormattableChat bold() { return bold(true); }
/** /**
* Sets the italic status of this component. * Sets the italic status of this component.
* @param i true to enable, false to disable, or null to inherit from parent. * @param i true to enable, false to disable, or null to inherit from parent.
* @return this. * @return this.
*/ */
public FormatableChat italic(Boolean i) { return setDecoration(TextDecoration.ITALIC, i); } public FormattableChat italic(Boolean i) { return setDecoration(TextDecoration.ITALIC, i); }
/** /**
* Enables the italic status of this component. * Enables the italic status of this component.
* @return this. * @return this.
*/ */
public FormatableChat italic() { return italic(true); } public FormattableChat italic() { return italic(true); }
/** /**
* Sets the underlined status of this component. * Sets the underlined status of this component.
* @param u true to enable, false to disable, or null to inherit from parent. * @param u true to enable, false to disable, or null to inherit from parent.
* @return this. * @return this.
*/ */
public FormatableChat underlined(Boolean u) { return setDecoration(TextDecoration.UNDERLINED, u); } public FormattableChat underlined(Boolean u) { return setDecoration(TextDecoration.UNDERLINED, u); }
/** /**
* Enables the underlined status of this component. * Enables the underlined status of this component.
* @return this. * @return this.
*/ */
public FormatableChat underlined() { return underlined(true); } public FormattableChat underlined() { return underlined(true); }
/** /**
* Sets the strikethrough status of this component. * Sets the strikethrough status of this component.
* @param s true to enable, false to disable, or null to inherit from parent. * @param s true to enable, false to disable, or null to inherit from parent.
* @return this. * @return this.
*/ */
public FormatableChat strikethrough(Boolean s) { return setDecoration(TextDecoration.STRIKETHROUGH, s); } public FormattableChat strikethrough(Boolean s) { return setDecoration(TextDecoration.STRIKETHROUGH, s); }
/** /**
* Enables the strikethrough status of this component. * Enables the strikethrough status of this component.
* @return this. * @return this.
*/ */
public FormatableChat strikethrough() { return strikethrough(true); } public FormattableChat strikethrough() { return strikethrough(true); }
/** /**
* Sets the obfuscated status of this component. * Sets the obfuscated status of this component.
* @param o true to enable, false to disable, or null to inherit from parent. * @param o true to enable, false to disable, or null to inherit from parent.
* @return this. * @return this.
*/ */
public FormatableChat obfuscated(Boolean o) { return setDecoration(TextDecoration.OBFUSCATED, o); } public FormattableChat obfuscated(Boolean o) { return setDecoration(TextDecoration.OBFUSCATED, o); }
/** /**
* Enables the obfuscated status of this component. * Enables the obfuscated status of this component.
* @return this. * @return this.
*/ */
public FormatableChat obfuscated() { return obfuscated(true); } public FormattableChat obfuscated() { return obfuscated(true); }
/** /**
@ -783,7 +783,7 @@ public abstract sealed class Chat extends ChatStatic implements HoverEventSource
* @param f the font namespaced key. * @param f the font namespaced key.
* @return this. * @return this.
*/ */
public FormatableChat font(Key f) { return setStyle(s -> s.font(f)); } public FormattableChat font(Key f) { return setStyle(s -> s.font(f)); }
/** /**
@ -791,7 +791,7 @@ public abstract sealed class Chat extends ChatStatic implements HoverEventSource
* @param i the text to insert. * @param i the text to insert.
* @return this. * @return this.
*/ */
public FormatableChat shiftClickInsertion(String i) { builder.insertion(i); return this; } public FormattableChat shiftClickInsertion(String i) { builder.insertion(i); return this; }
/** /**
@ -799,37 +799,37 @@ public abstract sealed class Chat extends ChatStatic implements HoverEventSource
* @param e the {@link ClickEvent}. * @param e the {@link ClickEvent}.
* @return this. * @return this.
*/ */
private FormatableChat click(ClickEvent e) { builder.clickEvent(e); return this; } private FormattableChat click(ClickEvent e) { builder.clickEvent(e); return this; }
/** /**
* Configure this component to execute the specified command when clicked. * Configure this component to execute the specified command when clicked.
* @param cmdWithSlash the command to execute. * @param cmdWithSlash the command to execute.
* @return this. * @return this.
*/ */
public FormatableChat clickCommand(String cmdWithSlash) { return click(ClickEvent.runCommand(cmdWithSlash)); } public FormattableChat clickCommand(String cmdWithSlash) { return click(ClickEvent.runCommand(cmdWithSlash)); }
/** /**
* Configure this component to insert in the chat-box the specified command when clicked. * Configure this component to insert in the chat-box the specified command when clicked.
* @param cmdWithSlash the command to suggest. * @param cmdWithSlash the command to suggest.
* @return this. * @return this.
*/ */
public FormatableChat clickSuggest(String cmdWithSlash) { return click(ClickEvent.suggestCommand(cmdWithSlash)); } public FormattableChat clickSuggest(String cmdWithSlash) { return click(ClickEvent.suggestCommand(cmdWithSlash)); }
/** /**
* Configure this component to copy into clipboard the specified text when clicked. * Configure this component to copy into clipboard the specified text when clicked.
* @param value the text to copy. * @param value the text to copy.
* @return this. * @return this.
*/ */
public FormatableChat clickClipboard(String value) { return click(ClickEvent.copyToClipboard(value)); } public FormattableChat clickClipboard(String value) { return click(ClickEvent.copyToClipboard(value)); }
/** /**
* Configure this component to open the specified URL when clicked. * Configure this component to open the specified URL when clicked.
* @param url the URL to open. * @param url the URL to open.
* @return this. * @return this.
*/ */
public FormatableChat clickURL(String url) { return click(ClickEvent.openUrl(url)); } public FormattableChat clickURL(String url) { return click(ClickEvent.openUrl(url)); }
/** /**
* Configure this component to change the page of the opened book when clicked. * Configure this component to change the page of the opened book when clicked.
* @param page the page to go to. * @param page the page to go to.
* @return this. * @return this.
*/ */
public FormatableChat clickBookPage(int page) { return click(ClickEvent.changePage(page)); } public FormattableChat clickBookPage(int page) { return click(ClickEvent.changePage(page)); }
/** /**
@ -837,31 +837,31 @@ public abstract sealed class Chat extends ChatStatic implements HoverEventSource
* @param e the {@link HoverEventSource}. * @param e the {@link HoverEventSource}.
* @return this. * @return this.
*/ */
public FormatableChat hover(HoverEventSource<?> e) { builder.hoverEvent(e); return this; } public FormattableChat hover(HoverEventSource<?> e) { builder.hoverEvent(e); return this; }
/** /**
* Configure this component to show the provided component when hovered. * Configure this component to show the provided component when hovered.
* @param v the component to show. * @param v the component to show.
* @return this. * @return this.
*/ */
public FormatableChat hover(Component v) { return hover((HoverEventSource<Component>) v); } public FormattableChat hover(Component v) { return hover((HoverEventSource<Component>) v); }
/** /**
* Configure this component to show the provided component when hovered. * Configure this component to show the provided component when hovered.
* @param v the component to show. * @param v the component to show.
* @return this. * @return this.
*/ */
public FormatableChat hover(Chat v) { return hover((HoverEventSource<Component>) v); } public FormattableChat hover(Chat v) { return hover((HoverEventSource<Component>) v); }
/** /**
* Configure this component to show the provided component when hovered. * Configure this component to show the provided component when hovered.
* @param v the component to show. * @param v the component to show.
* @return this. * @return this.
*/ */
public FormatableChat hover(ComponentLike v) { return hover(v.asComponent()); } public FormattableChat hover(ComponentLike v) { return hover(v.asComponent()); }
/** /**
* Configure this component to show the provided legacy text when hovered. * Configure this component to show the provided legacy text when hovered.
* @param legacyText the legacy text to show. * @param legacyText the legacy text to show.
* @return this. * @return this.
*/ */
public FormatableChat hover(String legacyText) { return hover(legacyText(legacyText)); } public FormattableChat hover(String legacyText) { return hover(legacyText(legacyText)); }
} }
@ -932,14 +932,14 @@ public abstract sealed class Chat extends ChatStatic implements HoverEventSource
/** /**
* Force the italic formatting to be set to false if it is not explicitly set in the component. * Force the italic formatting to be set to false if it is not explicitly set in the component.
* This is useful for item lores that defaults to italic in the game UI. * This is useful for item lore that defaults to italic in the game UI.
* @param c the {@link Chat} in which to set the italic property if needed. * @param c the {@link Chat} in which to set the italic property if needed.
* @return the provided {@link Chat} instance. * @return the provided {@link Chat} instance.
*/ */
public static Chat italicFalseIfNotSet(Chat c) { public static Chat italicFalseIfNotSet(Chat c) {
c.builder.style(b -> { c.builder.style(b -> {
if (b.build().decoration(TextDecoration.ITALIC) == State.NOT_SET) { if (b.build().decoration(TextDecoration.ITALIC) == State.NOT_SET) {
((FormatableChat) c).italic(false); ((FormattableChat) c).italic(false);
} }
}); });
return c; return c;

View File

@ -5,7 +5,7 @@ import net.kyori.adventure.text.ComponentLike;
import net.kyori.adventure.text.format.TextColor; import net.kyori.adventure.text.format.TextColor;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import fr.pandacube.lib.chat.Chat.FormatableChat; import fr.pandacube.lib.chat.Chat.FormattableChat;
/** /**
* Builder for a {@link Chat} component for filling a chat line, with decoration and eventual aligned text. * Builder for a {@link Chat} component for filling a chat line, with decoration and eventual aligned text.
@ -150,10 +150,10 @@ public class ChatFilledLine implements ComponentLike {
/** /**
* Renders this line to a {@link FormatableChat}. * Renders this line to a {@link FormattableChat}.
* @return a new {@link FormatableChat} built by this {@link ChatFilledLine}. * @return a new {@link FormattableChat} built by this {@link ChatFilledLine}.
*/ */
public FormatableChat toChat() { public FormattableChat toChat() {
int maxWidth = (this.maxWidth != null) int maxWidth = (this.maxWidth != null)
? this.maxWidth ? this.maxWidth
: console ? ChatUtil.CONSOLE_NB_CHAR_DEFAULT : ChatUtil.DEFAULT_CHAT_WIDTH; : console ? ChatUtil.CONSOLE_NB_CHAR_DEFAULT : ChatUtil.DEFAULT_CHAT_WIDTH;
@ -170,7 +170,7 @@ public class ChatFilledLine implements ComponentLike {
int textWidth = ChatUtil.componentWidth(text.asComponent(), console); int textWidth = ChatUtil.componentWidth(text.asComponent(), console);
if (textWidth > maxWidth) if (textWidth > maxWidth)
return (FormatableChat) text; return (FormattableChat) text;
int repeatedCharWidth = ChatUtil.charW(decorationChar, console, decorationBold); int repeatedCharWidth = ChatUtil.charW(decorationChar, console, decorationBold);
int nbCharLeft = 0, nbCharRight = 0; int nbCharLeft = 0, nbCharRight = 0;
@ -179,12 +179,12 @@ public class ChatFilledLine implements ComponentLike {
case CENTER -> { case CENTER -> {
nbCharLeft = nbCharRight = (maxWidth - textWidth) / 2 / repeatedCharWidth; nbCharLeft = nbCharRight = (maxWidth - textWidth) / 2 / repeatedCharWidth;
if (nbCharLeft == 0) if (nbCharLeft == 0)
return (FormatableChat) text; return (FormattableChat) text;
} }
case LEFT, RIGHT -> { case LEFT, RIGHT -> {
int remWidth = textWidth + nbSide * repeatedCharWidth; int remWidth = textWidth + nbSide * repeatedCharWidth;
if (remWidth > maxWidth) if (remWidth > maxWidth)
return (FormatableChat) text; return (FormattableChat) text;
boolean left = alignment == Alignment.LEFT; boolean left = alignment == Alignment.LEFT;
int nbOtherSide = (maxWidth - remWidth) / repeatedCharWidth; int nbOtherSide = (maxWidth - remWidth) / repeatedCharWidth;
nbCharLeft = left ? nbSide : nbOtherSide; nbCharLeft = left ? nbSide : nbOtherSide;
@ -197,7 +197,7 @@ public class ChatFilledLine implements ComponentLike {
.then(text); .then(text);
if (decorationChar != ' ' || spacesDecorationRightSide) if (decorationChar != ' ' || spacesDecorationRightSide)
d.then(Chat.text(ChatUtil.repeatedChar(decorationChar, nbCharRight)).color(decorationColor).bold(decorationBold)); d.then(Chat.text(ChatUtil.repeatedChar(decorationChar, nbCharRight)).color(decorationColor).bold(decorationBold));
return (FormatableChat) d; return (FormattableChat) d;
} }

View File

@ -1,6 +1,6 @@
package fr.pandacube.lib.chat; package fr.pandacube.lib.chat;
import fr.pandacube.lib.chat.Chat.FormatableChat; import fr.pandacube.lib.chat.Chat.FormattableChat;
import net.kyori.adventure.text.BlockNBTComponent; import net.kyori.adventure.text.BlockNBTComponent;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.ComponentBuilder; import net.kyori.adventure.text.ComponentBuilder;
@ -27,27 +27,27 @@ public abstract class ChatStatic {
private static FormatableChat chatComponent(Component c) { private static FormattableChat chatComponent(Component c) {
return new FormatableChat(componentToBuilder(c)); return new FormattableChat(componentToBuilder(c));
} }
/** /**
* Creates a {@link FormatableChat} from the provided {@link ComponentLike}. * Creates a {@link FormattableChat} from the provided {@link ComponentLike}.
* If the provided component is an instance of {@link Chat}, its content will be duplicated, and the provided one * If the provided component is an instance of {@link Chat}, its content will be duplicated, and the provided one
* will be untouched. * will be untouched.
* @param c the {@link ComponentLike}. * @param c the {@link ComponentLike}.
* @return a new {@link FormatableChat}. * @return a new {@link FormattableChat}.
*/ */
public static FormatableChat chatComponent(ComponentLike c) { public static FormattableChat chatComponent(ComponentLike c) {
return chatComponent(c.asComponent()); return chatComponent(c.asComponent());
} }
/** /**
* Creates a {@link FormatableChat} with an empty main text content. * Creates a {@link FormattableChat} with an empty main text content.
* @return a new empty {@link FormatableChat}. * @return a new empty {@link FormattableChat}.
*/ */
public static FormatableChat chat() { public static FormattableChat chat() {
return new FormatableChat(Component.text()); return new FormattableChat(Component.text());
} }
@ -56,60 +56,60 @@ public abstract class ChatStatic {
/** /**
* Creates a {@link FormatableChat} with the provided plain text as its main text content. * Creates a {@link FormattableChat} with the provided plain text as its main text content.
* @param plainText the text to use as the content. * @param plainText the text to use as the content.
* @return a new {@link FormatableChat} with the provided text as its main text content. * @return a new {@link FormattableChat} with the provided text as its main text content.
* @throws IllegalArgumentException if the {@code plainText} parameter is instance of {@link Chat} or * @throws IllegalArgumentException if the {@code plainText} parameter is instance of {@link Chat} or
* {@link Component}. The caller should use {@link #chatComponent(ComponentLike)} * {@link Component}. The caller should use {@link #chatComponent(ComponentLike)}
* instead. * instead.
*/ */
public static FormatableChat text(Object plainText) { public static FormattableChat text(Object plainText) {
if (plainText instanceof ComponentLike) { if (plainText instanceof ComponentLike) {
throw new IllegalArgumentException("Expected any object except instance of " + ComponentLike.class + ". Received " + plainText + ". Please use ChatStatic.chatComponent(ComponentLike) instead."); throw new IllegalArgumentException("Expected any object except instance of " + ComponentLike.class + ". Received " + plainText + ". Please use ChatStatic.chatComponent(ComponentLike) instead.");
} }
return new FormatableChat(Component.text().content(Objects.toString(plainText))); return new FormattableChat(Component.text().content(Objects.toString(plainText)));
} }
/** /**
* Creates a {@link FormatableChat} with the provided legacy text as its content, using the section {@code "§"} * Creates a {@link FormattableChat} with the provided legacy text as its content, using the section {@code "§"}
* character. * character.
* @param legacyText the legacy text to use as the content, that uses the {@code "§"} character. * @param legacyText the legacy text to use as the content, that uses the {@code "§"} character.
* @return a new {@link FormatableChat} with the provided text as its content. * @return a new {@link FormattableChat} with the provided text as its content.
* @throws IllegalArgumentException If the {@code legacyText} parameter is instance of {@link Chat} or * @throws IllegalArgumentException If the {@code legacyText} parameter is instance of {@link Chat} or
* {@link Component}. The caller should use {@link #chatComponent(ComponentLike)} * {@link Component}. The caller should use {@link #chatComponent(ComponentLike)}
* instead. * instead.
*/ */
public static FormatableChat legacyText(Object legacyText) { public static FormattableChat legacyText(Object legacyText) {
return legacyText(legacyText, LegacyComponentSerializer.SECTION_CHAR); return legacyText(legacyText, LegacyComponentSerializer.SECTION_CHAR);
} }
/** /**
* Creates a {@link FormatableChat} with the provided legacy text as its content, using the ampersand {@code "&"} * Creates a {@link FormattableChat} with the provided legacy text as its content, using the ampersand {@code "&"}
* character. * character.
* @param legacyText the legacy text to use as the content, that uses the {@code "&"} character. * @param legacyText the legacy text to use as the content, that uses the {@code "&"} character.
* @return a new {@link FormatableChat} with the provided text as its content. * @return a new {@link FormattableChat} with the provided text as its content.
* @throws IllegalArgumentException If the {@code legacyText} parameter is instance of {@link Chat} or * @throws IllegalArgumentException If the {@code legacyText} parameter is instance of {@link Chat} or
* {@link Component}. The caller should use {@link #chatComponent(ComponentLike)} * {@link Component}. The caller should use {@link #chatComponent(ComponentLike)}
* instead. * instead.
*/ */
public static FormatableChat legacyAmpersandText(Object legacyText) { public static FormattableChat legacyAmpersandText(Object legacyText) {
return legacyText(legacyText, LegacyComponentSerializer.AMPERSAND_CHAR); return legacyText(legacyText, LegacyComponentSerializer.AMPERSAND_CHAR);
} }
/** /**
* Creates a {@link FormatableChat} with the provided legacy text as its content, using the specified * Creates a {@link FormattableChat} with the provided legacy text as its content, using the specified
* legacyCharacter. * legacyCharacter.
* @param legacyText the legacy text to use as the content. * @param legacyText the legacy text to use as the content.
* @param legacyCharacter the character used in the provided text to prefix color and format code. * @param legacyCharacter the character used in the provided text to prefix color and format code.
* @return a new {@link FormatableChat} with the provided text as its content. * @return a new {@link FormattableChat} with the provided text as its content.
* @throws IllegalArgumentException If the {@code legacyText} parameter is instance of {@link Chat} or * @throws IllegalArgumentException If the {@code legacyText} parameter is instance of {@link Chat} or
* {@link Component}. The caller should use {@link #chatComponent(ComponentLike)} * {@link Component}. The caller should use {@link #chatComponent(ComponentLike)}
* instead. * instead.
*/ */
private static FormatableChat legacyText(Object legacyText, char legacyCharacter) { private static FormattableChat legacyText(Object legacyText, char legacyCharacter) {
if (legacyText instanceof ComponentLike) { if (legacyText instanceof ComponentLike) {
throw new IllegalArgumentException("Expected any object except instance of " + ComponentLike.class + ". Received " + legacyText + ". Please use ChatStatic.chatComponent(ComponentLike) instead."); throw new IllegalArgumentException("Expected any object except instance of " + ComponentLike.class + ". Received " + legacyText + ". Please use ChatStatic.chatComponent(ComponentLike) instead.");
} }
@ -118,118 +118,118 @@ public abstract class ChatStatic {
/** /**
* Creates a {@link FormatableChat} with the provided MiniMessage text as its content. * Creates a {@link FormattableChat} with the provided MiniMessage text as its content.
* @param miniMessageText the MiniMessage text to use as the content. * @param miniMessageText the MiniMessage text to use as the content.
* @return a new {@link FormatableChat} with the provided text as its content. * @return a new {@link FormattableChat} with the provided text as its content.
*/ */
public static FormatableChat miniMessageText(String miniMessageText) { public static FormattableChat miniMessageText(String miniMessageText) {
return chatComponent(MiniMessage.miniMessage().deserialize(miniMessageText)); return chatComponent(MiniMessage.miniMessage().deserialize(miniMessageText));
} }
/** /**
* Creates a {@link FormatableChat} with the provided plain text as its main text content, and colored using the * Creates a {@link FormattableChat} with the provided plain text as its main text content, and colored using the
* {@link ChatConfig#infoColor configured info color}. * {@link ChatConfig#infoColor configured info color}.
* @param plainText the text to use as the content. * @param plainText the text to use as the content.
* @return a new {@link FormatableChat} with the provided text as its main text content, and the configured color. * @return a new {@link FormattableChat} with the provided text as its main text content, and the configured color.
* @throws IllegalArgumentException if the {@code plainText} parameter is instance of {@link Chat} or * @throws IllegalArgumentException if the {@code plainText} parameter is instance of {@link Chat} or
* {@link Component}. The caller should use {@link #chatComponent(ComponentLike)} and * {@link Component}. The caller should use {@link #chatComponent(ComponentLike)} and
* {@link FormatableChat#infoColor()} instead. * {@link FormattableChat#infoColor()} instead.
*/ */
public static FormatableChat infoText(Object plainText) { public static FormattableChat infoText(Object plainText) {
return text(plainText).infoColor(); return text(plainText).infoColor();
} }
/** /**
* Creates a {@link FormatableChat} with the provided plain text as its main text content, and colored using the * Creates a {@link FormattableChat} with the provided plain text as its main text content, and colored using the
* {@link ChatConfig#warningColor configured warning color}. * {@link ChatConfig#warningColor configured warning color}.
* @param plainText the text to use as the content. * @param plainText the text to use as the content.
* @return a new {@link FormatableChat} with the provided text as its main text content, and the configured color. * @return a new {@link FormattableChat} with the provided text as its main text content, and the configured color.
* @throws IllegalArgumentException if the {@code plainText} parameter is instance of {@link Chat} or * @throws IllegalArgumentException if the {@code plainText} parameter is instance of {@link Chat} or
* {@link Component}. The caller should use {@link #chatComponent(ComponentLike)} and * {@link Component}. The caller should use {@link #chatComponent(ComponentLike)} and
* {@link FormatableChat#warningColor()} instead. * {@link FormattableChat#warningColor()} instead.
*/ */
public static FormatableChat warningText(Object plainText) { public static FormattableChat warningText(Object plainText) {
return text(plainText).warningColor(); return text(plainText).warningColor();
} }
/** /**
* Creates a {@link FormatableChat} with the provided plain text as its main text content, and colored using the * Creates a {@link FormattableChat} with the provided plain text as its main text content, and colored using the
* {@link ChatConfig#dataColor configured data color}. * {@link ChatConfig#dataColor configured data color}.
* @param plainText the text to use as the content. * @param plainText the text to use as the content.
* @return a new {@link FormatableChat} with the provided text as its main text content, and the configured color. * @return a new {@link FormattableChat} with the provided text as its main text content, and the configured color.
* @throws IllegalArgumentException if the {@code plainText} parameter is instance of {@link Chat} or * @throws IllegalArgumentException if the {@code plainText} parameter is instance of {@link Chat} or
* {@link Component}. The caller should use {@link #chatComponent(ComponentLike)} and * {@link Component}. The caller should use {@link #chatComponent(ComponentLike)} and
* {@link FormatableChat#dataColor()} instead. * {@link FormattableChat#dataColor()} instead.
*/ */
public static FormatableChat dataText(Object plainText) { public static FormattableChat dataText(Object plainText) {
return text(plainText).dataColor(); return text(plainText).dataColor();
} }
/** /**
* Creates a {@link FormatableChat} with the provided plain text as its main text content, and colored using the * Creates a {@link FormattableChat} with the provided plain text as its main text content, and colored using the
* {@link ChatConfig#decorationColor configured decorationColor color}. * {@link ChatConfig#decorationColor configured decorationColor color}.
* @param plainText the text to use as the content. * @param plainText the text to use as the content.
* @return a new {@link FormatableChat} with the provided text as its main text content, and the configured color. * @return a new {@link FormattableChat} with the provided text as its main text content, and the configured color.
* @throws IllegalArgumentException if the {@code plainText} parameter is instance of {@link Chat} or * @throws IllegalArgumentException if the {@code plainText} parameter is instance of {@link Chat} or
* {@link Component}. The caller should use {@link #chatComponent(ComponentLike)} and * {@link Component}. The caller should use {@link #chatComponent(ComponentLike)} and
* {@link FormatableChat#decorationColor()} instead. * {@link FormattableChat#decorationColor()} instead.
*/ */
public static FormatableChat decorationText(Object plainText) { public static FormattableChat decorationText(Object plainText) {
return text(plainText).decorationColor(); return text(plainText).decorationColor();
} }
/** /**
* Creates a {@link FormatableChat} with the provided plain text as its main text content, and colored using the * Creates a {@link FormattableChat} with the provided plain text as its main text content, and colored using the
* {@link ChatConfig#successColor configured success color}. * {@link ChatConfig#successColor configured success color}.
* @param plainText the text to use as the content. * @param plainText the text to use as the content.
* @return a new {@link FormatableChat} with the provided text as its main text content, and the configured color. * @return a new {@link FormattableChat} with the provided text as its main text content, and the configured color.
* @throws IllegalArgumentException if the {@code plainText} parameter is instance of {@link Chat} or * @throws IllegalArgumentException if the {@code plainText} parameter is instance of {@link Chat} or
* {@link Component}. The caller should use {@link #chatComponent(ComponentLike)} and * {@link Component}. The caller should use {@link #chatComponent(ComponentLike)} and
* {@link FormatableChat#successColor()} instead. * {@link FormattableChat#successColor()} instead.
*/ */
public static FormatableChat successText(Object plainText) { public static FormattableChat successText(Object plainText) {
return text(plainText).successColor(); return text(plainText).successColor();
} }
/** /**
* Creates a {@link FormatableChat} with the provided plain text as its main text content, and colored using the * Creates a {@link FormattableChat} with the provided plain text as its main text content, and colored using the
* {@link ChatConfig#failureColor configured failure color}. * {@link ChatConfig#failureColor configured failure color}.
* @param plainText the text to use as the content. * @param plainText the text to use as the content.
* @return a new {@link FormatableChat} with the provided text as its main text content, and the configured color. * @return a new {@link FormattableChat} with the provided text as its main text content, and the configured color.
* @throws IllegalArgumentException if the {@code plainText} parameter is instance of {@link Chat} or * @throws IllegalArgumentException if the {@code plainText} parameter is instance of {@link Chat} or
* {@link Component}. The caller should use {@link #chatComponent(ComponentLike)} and * {@link Component}. The caller should use {@link #chatComponent(ComponentLike)} and
* {@link FormatableChat#failureColor()} instead. * {@link FormattableChat#failureColor()} instead.
*/ */
public static FormatableChat failureText(Object plainText) { public static FormattableChat failureText(Object plainText) {
return text(plainText).failureColor(); return text(plainText).failureColor();
} }
/** /**
* Creates a {@link FormatableChat} with the provided legacy text as its main text content, and colored in white in * Creates a {@link FormattableChat} with the provided legacy text as its main text content, and colored in white in
* case there is no color on the generated parent component. * case there is no color on the generated parent component.
* @param legacyText the legacy text to use as the content. * @param legacyText the legacy text to use as the content.
* @return a new {@link FormatableChat} with the provided text as its main text content, and the configured color. * @return a new {@link FormattableChat} with the provided text as its main text content, and the configured color.
* @throws IllegalArgumentException if the {@code plainText} parameter is instance of {@link Chat} or * @throws IllegalArgumentException if the {@code plainText} parameter is instance of {@link Chat} or
* {@link Component}. The caller should use {@link #chatComponent(ComponentLike)} and * {@link Component}. The caller should use {@link #chatComponent(ComponentLike)} and
* {@link FormatableChat#failureColor()} instead. * {@link FormattableChat#failureColor()} instead.
*/ */
public static FormatableChat playerNameText(String legacyText) { public static FormattableChat playerNameText(String legacyText) {
FormatableChat fc = legacyText(legacyText); FormattableChat fc = legacyText(legacyText);
fc.builder.colorIfAbsent(NamedTextColor.WHITE); fc.builder.colorIfAbsent(NamedTextColor.WHITE);
return fc; return fc;
} }
/** /**
* Creates a {@link FormatableChat} from the provided {@link Component}, coloring in white the generated parent * Creates a {@link FormattableChat} from the provided {@link Component}, coloring in white the generated parent
* component in case there is no color defined. * component in case there is no color defined.
* If the provided component is an instance of {@link Chat}, its content will be duplicated, and the provided one * If the provided component is an instance of {@link Chat}, its content will be duplicated, and the provided one
* will be untouched. * will be untouched.
* @param c the {@link Component}. * @param c the {@link Component}.
* @return a new {@link FormatableChat}. * @return a new {@link FormattableChat}.
*/ */
public static FormatableChat playerNameComponent(ComponentLike c) { public static FormattableChat playerNameComponent(ComponentLike c) {
FormatableChat fc = chatComponent(c); FormattableChat fc = chatComponent(c);
fc.builder.colorIfAbsent(NamedTextColor.WHITE); fc.builder.colorIfAbsent(NamedTextColor.WHITE);
return fc; return fc;
} }
@ -238,32 +238,32 @@ public abstract class ChatStatic {
/** /**
* Creates a {@link FormatableChat} with the provided translation key and parameters. * Creates a {@link FormattableChat} with the provided translation key and parameters.
* @param key the translation key. * @param key the translation key.
* @param with the translation parameters. * @param with the translation parameters.
* @return a new {@link FormatableChat} with the provided translation key and parameters. * @return a new {@link FormattableChat} with the provided translation key and parameters.
*/ */
public static FormatableChat translation(String key, Object... with) { public static FormattableChat translation(String key, Object... with) {
return new FormatableChat(Component.translatable().key(key).arguments(Chat.filterObjToTranslationArgumentLike(with))); return new FormattableChat(Component.translatable().key(key).arguments(Chat.filterObjToTranslationArgumentLike(with)));
} }
/** /**
* Creates a {@link FormatableChat} with the provided keybinding. * Creates a {@link FormattableChat} with the provided keybinding.
* @param key the keybinding to display. * @param key the keybinding to display.
* @return a new {@link FormatableChat} with the provided keybinding. * @return a new {@link FormattableChat} with the provided keybinding.
*/ */
public static FormatableChat keybind(String key) { public static FormattableChat keyBind(String key) {
return new FormatableChat(Component.keybind().keybind(key)); return new FormattableChat(Component.keybind().keybind(key));
} }
/** /**
* Creates a {@link FormatableChat} with the provided score name and objective. * Creates a {@link FormattableChat} with the provided score name and objective.
* @param name the score name. * @param name the score name.
* @param objective the score objective. * @param objective the score objective.
* @return a new {@link FormatableChat} with the provided score name and objective. * @return a new {@link FormattableChat} with the provided score name and objective.
*/ */
public static FormatableChat score(String name, String objective) { public static FormattableChat score(String name, String objective) {
return new FormatableChat(Component.score().name(name).objective(objective)); return new FormattableChat(Component.score().name(name).objective(objective));
} }
@ -272,49 +272,49 @@ public abstract class ChatStatic {
/** /**
* Creates a {@link FormatableChat} that leads to a URL when clicked. * Creates a {@link FormattableChat} that leads to a URL when clicked.
* @param inner the component to make clickable. * @param inner the component to make clickable.
* @param url the target url. Must start with {@code "http://"} or {@code "https://"}. * @param url the target url. Must start with {@code "http://"} or {@code "https://"}.
* @param hover the content to display when hovering the component. * @param hover the content to display when hovering the component.
* @return a new {@link FormatableChat} that leads to a URL when clicked. * @return a new {@link FormattableChat} that leads to a URL when clicked.
*/ */
public static FormatableChat clickableURL(ComponentLike inner, String url, HoverEventSource<?> hover) { public static FormattableChat clickableURL(ComponentLike inner, String url, HoverEventSource<?> hover) {
Objects.requireNonNull(url, "url"); Objects.requireNonNull(url, "url");
if (inner == null) if (inner == null)
inner = text(url); inner = text(url);
if (hover == null) if (hover == null)
hover = text(ChatUtil.wrapInLimitedPixels(url, 240)); hover = text(ChatUtil.wrapInLimitedPixels(url, 240));
return (FormatableChat) chat().clickURL(url).urlColor().hover(hover).then(inner); return (FormattableChat) chat().clickURL(url).urlColor().hover(hover).then(inner);
} }
/** /**
* Creates a {@link FormatableChat} that leads to a URL when clicked. * Creates a {@link FormattableChat} that leads to a URL when clicked.
* <p> * <p>
* When hovered, the component will display the url. To customize the hover content, use * When hovered, the component will display the url. To customize the hover content, use
* {@link #clickableURL(ComponentLike, String, HoverEventSource)}. * {@link #clickableURL(ComponentLike, String, HoverEventSource)}.
* @param inner the component to make clickable. * @param inner the component to make clickable.
* @param url the target url. Must start with {@code "http://"} or {@code "https://"}. * @param url the target url. Must start with {@code "http://"} or {@code "https://"}.
* @return a new {@link FormatableChat} that leads to a URL when clicked. * @return a new {@link FormattableChat} that leads to a URL when clicked.
*/ */
public static FormatableChat clickableURL(ComponentLike inner, String url) { public static FormattableChat clickableURL(ComponentLike inner, String url) {
return clickableURL(inner, url, null); return clickableURL(inner, url, null);
} }
/** /**
* Creates a {@link FormatableChat} that leads to a URL when clicked. * Creates a {@link FormattableChat} that leads to a URL when clicked.
* <p> * <p>
* The text on which to click will be the URL itself. To configure the clicked text, use * The text on which to click will be the URL itself. To configure the clicked text, use
* {@link #clickableURL(ComponentLike, String, HoverEventSource)}. * {@link #clickableURL(ComponentLike, String, HoverEventSource)}.
* @param url the target url. Must start with {@code "http://"} or {@code "https://"}. * @param url the target url. Must start with {@code "http://"} or {@code "https://"}.
* @param hover the content to display when hovering the component. * @param hover the content to display when hovering the component.
* @return a new {@link FormatableChat} that leads to a URL when clicked. * @return a new {@link FormattableChat} that leads to a URL when clicked.
*/ */
public static FormatableChat clickableURL(String url, HoverEventSource<?> hover) { public static FormattableChat clickableURL(String url, HoverEventSource<?> hover) {
return clickableURL(null, url, hover); return clickableURL(null, url, hover);
} }
/** /**
* Creates a {@link FormatableChat} that leads to a URL when clicked. * Creates a {@link FormattableChat} that leads to a URL when clicked.
* <p> * <p>
* The text on which to click will be the URL itself. To configure the clicked text, use * The text on which to click will be the URL itself. To configure the clicked text, use
* {@link #clickableURL(ComponentLike, String)}. * {@link #clickableURL(ComponentLike, String)}.
@ -322,9 +322,9 @@ public abstract class ChatStatic {
* When hovered, the component will display the url. To customize the hover content, use * When hovered, the component will display the url. To customize the hover content, use
* {@link #clickableURL(String, HoverEventSource)}. * {@link #clickableURL(String, HoverEventSource)}.
* @param url the target url. Must start with {@code "http://"} or {@code "https://"}. * @param url the target url. Must start with {@code "http://"} or {@code "https://"}.
* @return a new {@link FormatableChat} that leads to a URL when clicked. * @return a new {@link FormattableChat} that leads to a URL when clicked.
*/ */
public static FormatableChat clickableURL(String url) { public static FormattableChat clickableURL(String url) {
return clickableURL(null, url, null); return clickableURL(null, url, null);
} }
@ -334,14 +334,14 @@ public abstract class ChatStatic {
/** /**
* Creates a {@link FormatableChat} that runs a command when clicked. * Creates a {@link FormattableChat} that runs a command when clicked.
* @param inner the component to make clickable. * @param inner the component to make clickable.
* @param commandWithSlash the command to run. Must start with {@code "/"}. * @param commandWithSlash the command to run. Must start with {@code "/"}.
* @param hover the content to display when hovering the component. * @param hover the content to display when hovering the component.
* @return a new {@link FormatableChat} that runs a command when clicked. * @return a new {@link FormattableChat} that runs a command when clicked.
* @throws IllegalArgumentException if {@code commandWithSlash} does not start with a {@code "/"}. * @throws IllegalArgumentException if {@code commandWithSlash} does not start with a {@code "/"}.
*/ */
public static FormatableChat clickableCommand(ComponentLike inner, String commandWithSlash, HoverEventSource<?> hover) { public static FormattableChat clickableCommand(ComponentLike inner, String commandWithSlash, HoverEventSource<?> hover) {
Objects.requireNonNull(commandWithSlash, "commandWithSlash"); Objects.requireNonNull(commandWithSlash, "commandWithSlash");
if (!commandWithSlash.startsWith("/")) if (!commandWithSlash.startsWith("/"))
throw new IllegalArgumentException("commandWithSlash must start with a '/' character."); throw new IllegalArgumentException("commandWithSlash must start with a '/' character.");
@ -349,39 +349,39 @@ public abstract class ChatStatic {
inner = text(commandWithSlash); inner = text(commandWithSlash);
if (hover == null) if (hover == null)
hover = text(ChatUtil.wrapInLimitedPixels(commandWithSlash, 240)); hover = text(ChatUtil.wrapInLimitedPixels(commandWithSlash, 240));
return (FormatableChat) chat().clickCommand(commandWithSlash).commandColor().hover(hover).then(inner); return (FormattableChat) chat().clickCommand(commandWithSlash).commandColor().hover(hover).then(inner);
} }
/** /**
* Creates a {@link FormatableChat} that runs a command when clicked. * Creates a {@link FormattableChat} that runs a command when clicked.
* <p> * <p>
* When hovered, the component will display the command itself. To customize the hover content, use * When hovered, the component will display the command itself. To customize the hover content, use
* {@link #clickableCommand(ComponentLike, String, HoverEventSource)}. * {@link #clickableCommand(ComponentLike, String, HoverEventSource)}.
* @param inner the component to make clickable. * @param inner the component to make clickable.
* @param commandWithSlash the command to run. Must start with {@code "/"}. * @param commandWithSlash the command to run. Must start with {@code "/"}.
* @return a new {@link FormatableChat} that runs a command when clicked. * @return a new {@link FormattableChat} that runs a command when clicked.
* @throws IllegalArgumentException if {@code commandWithSlash} does not start with a {@code "/"}. * @throws IllegalArgumentException if {@code commandWithSlash} does not start with a {@code "/"}.
*/ */
public static FormatableChat clickableCommand(ComponentLike inner, String commandWithSlash) { public static FormattableChat clickableCommand(ComponentLike inner, String commandWithSlash) {
return clickableCommand(inner, commandWithSlash, null); return clickableCommand(inner, commandWithSlash, null);
} }
/** /**
* Creates a {@link FormatableChat} that runs a command when clicked. * Creates a {@link FormattableChat} that runs a command when clicked.
* <p> * <p>
* The text on which to click will be the command itself. To configure the clicked text, use * The text on which to click will be the command itself. To configure the clicked text, use
* {@link #clickableCommand(ComponentLike, String, HoverEventSource)}. * {@link #clickableCommand(ComponentLike, String, HoverEventSource)}.
* @param commandWithSlash the command to run. Must start with {@code "/"}. * @param commandWithSlash the command to run. Must start with {@code "/"}.
* @param hover the content to display when hovering the component. * @param hover the content to display when hovering the component.
* @return a new {@link FormatableChat} that runs a command when clicked. * @return a new {@link FormattableChat} that runs a command when clicked.
* @throws IllegalArgumentException if {@code commandWithSlash} does not start with a {@code "/"}. * @throws IllegalArgumentException if {@code commandWithSlash} does not start with a {@code "/"}.
*/ */
public static FormatableChat clickableCommand(String commandWithSlash, HoverEventSource<?> hover) { public static FormattableChat clickableCommand(String commandWithSlash, HoverEventSource<?> hover) {
return clickableCommand(null, commandWithSlash, hover); return clickableCommand(null, commandWithSlash, hover);
} }
/** /**
* Creates a {@link FormatableChat} that runs a command when clicked. * Creates a {@link FormattableChat} that runs a command when clicked.
* <p> * <p>
* The text on which to click will be the command itself. To configure the clicked text, use * The text on which to click will be the command itself. To configure the clicked text, use
* {@link #clickableCommand(ComponentLike, String)}. * {@link #clickableCommand(ComponentLike, String)}.
@ -389,10 +389,10 @@ public abstract class ChatStatic {
* When hovered, the component will display the command itself. To customize the hover content, use * When hovered, the component will display the command itself. To customize the hover content, use
* {@link #clickableCommand(String, HoverEventSource)}. * {@link #clickableCommand(String, HoverEventSource)}.
* @param commandWithSlash the command to run. Must start with {@code "/"}. * @param commandWithSlash the command to run. Must start with {@code "/"}.
* @return a new {@link FormatableChat} that runs a command when clicked. * @return a new {@link FormattableChat} that runs a command when clicked.
* @throws IllegalArgumentException if {@code commandWithSlash} does not start with a {@code "/"}. * @throws IllegalArgumentException if {@code commandWithSlash} does not start with a {@code "/"}.
*/ */
public static FormatableChat clickableCommand(String commandWithSlash) { public static FormattableChat clickableCommand(String commandWithSlash) {
return clickableCommand(null, commandWithSlash, null); return clickableCommand(null, commandWithSlash, null);
} }
@ -402,14 +402,14 @@ public abstract class ChatStatic {
/** /**
* Creates a {@link FormatableChat} that pre-fill the chat box with a command when clicked. * Creates a {@link FormattableChat} that pre-fill the chat box with a command when clicked.
* @param inner the component to make clickable. * @param inner the component to make clickable.
* @param commandWithSlash the command to suggest. Must start with {@code "/"}. * @param commandWithSlash the command to suggest. Must start with {@code "/"}.
* @param hover the content to display when hovering the component. * @param hover the content to display when hovering the component.
* @return a new {@link FormatableChat} that pre-fill the chat box with a command when clicked. * @return a new {@link FormattableChat} that pre-fill the chat box with a command when clicked.
* @throws IllegalArgumentException if {@code commandWithSlash} does not start with a {@code "/"}. * @throws IllegalArgumentException if {@code commandWithSlash} does not start with a {@code "/"}.
*/ */
public static FormatableChat clickableSuggest(ComponentLike inner, String commandWithSlash, HoverEventSource<?> hover) { public static FormattableChat clickableSuggest(ComponentLike inner, String commandWithSlash, HoverEventSource<?> hover) {
Objects.requireNonNull(commandWithSlash, "commandWithSlash"); Objects.requireNonNull(commandWithSlash, "commandWithSlash");
if (!commandWithSlash.startsWith("/")) if (!commandWithSlash.startsWith("/"))
throw new IllegalArgumentException("commandWithSlash must start with a '/' character."); throw new IllegalArgumentException("commandWithSlash must start with a '/' character.");
@ -417,39 +417,39 @@ public abstract class ChatStatic {
inner = text(commandWithSlash); inner = text(commandWithSlash);
if (hover == null) if (hover == null)
hover = text(ChatUtil.wrapInLimitedPixels(commandWithSlash, 240)); hover = text(ChatUtil.wrapInLimitedPixels(commandWithSlash, 240));
return (FormatableChat) chat().clickSuggest(commandWithSlash).commandColor().hover(hover).then(inner); return (FormattableChat) chat().clickSuggest(commandWithSlash).commandColor().hover(hover).then(inner);
} }
/** /**
* Creates a {@link FormatableChat} that pre-fill the chat box with a command when clicked. * Creates a {@link FormattableChat} that pre-fill the chat box with a command when clicked.
* <p> * <p>
* When hovered, the component will display the command itself. To customize the hover content, use * When hovered, the component will display the command itself. To customize the hover content, use
* {@link #clickableSuggest(ComponentLike, String, HoverEventSource)}. * {@link #clickableSuggest(ComponentLike, String, HoverEventSource)}.
* @param inner the component to make clickable. * @param inner the component to make clickable.
* @param commandWithSlash the command to suggest. Must start with {@code "/"}. * @param commandWithSlash the command to suggest. Must start with {@code "/"}.
* @return a new {@link FormatableChat} that pre-fill the chat box with a command when clicked. * @return a new {@link FormattableChat} that pre-fill the chat box with a command when clicked.
* @throws IllegalArgumentException if {@code commandWithSlash} does not start with a {@code "/"}. * @throws IllegalArgumentException if {@code commandWithSlash} does not start with a {@code "/"}.
*/ */
public static FormatableChat clickableSuggest(ComponentLike inner, String commandWithSlash) { public static FormattableChat clickableSuggest(ComponentLike inner, String commandWithSlash) {
return clickableSuggest(inner, commandWithSlash, null); return clickableSuggest(inner, commandWithSlash, null);
} }
/** /**
* Creates a {@link FormatableChat} that pre-fill the chat box with a command when clicked. * Creates a {@link FormattableChat} that pre-fill the chat box with a command when clicked.
* <p> * <p>
* The text on which to click will be the command itself. To configure the clicked text, use * The text on which to click will be the command itself. To configure the clicked text, use
* {@link #clickableSuggest(ComponentLike, String, HoverEventSource)}. * {@link #clickableSuggest(ComponentLike, String, HoverEventSource)}.
* @param commandWithSlash the command to suggest. Must start with {@code "/"}. * @param commandWithSlash the command to suggest. Must start with {@code "/"}.
* @param hover the content to display when hovering the component. * @param hover the content to display when hovering the component.
* @return a new {@link FormatableChat} that pre-fill the chat box with a command when clicked. * @return a new {@link FormattableChat} that pre-fill the chat box with a command when clicked.
* @throws IllegalArgumentException if {@code commandWithSlash} does not start with a {@code "/"}. * @throws IllegalArgumentException if {@code commandWithSlash} does not start with a {@code "/"}.
*/ */
public static FormatableChat clickableSuggest(String commandWithSlash, HoverEventSource<?> hover) { public static FormattableChat clickableSuggest(String commandWithSlash, HoverEventSource<?> hover) {
return clickableSuggest(null, commandWithSlash, hover); return clickableSuggest(null, commandWithSlash, hover);
} }
/** /**
* Creates a {@link FormatableChat} that pre-fill the chat box with a command when clicked. * Creates a {@link FormattableChat} that pre-fill the chat box with a command when clicked.
* <p> * <p>
* The text on which to click will be the command itself. To configure the clicked text, use * The text on which to click will be the command itself. To configure the clicked text, use
* {@link #clickableSuggest(ComponentLike, String)}. * {@link #clickableSuggest(ComponentLike, String)}.
@ -457,10 +457,10 @@ public abstract class ChatStatic {
* When hovered, the component will display the command itself. To customize the hover content, use * When hovered, the component will display the command itself. To customize the hover content, use
* {@link #clickableSuggest(String, HoverEventSource)}. * {@link #clickableSuggest(String, HoverEventSource)}.
* @param commandWithSlash the command to suggest. Must start with {@code "/"}. * @param commandWithSlash the command to suggest. Must start with {@code "/"}.
* @return a new {@link FormatableChat} that pre-fill the chat box with a command when clicked. * @return a new {@link FormattableChat} that pre-fill the chat box with a command when clicked.
* @throws IllegalArgumentException if {@code commandWithSlash} does not start with a {@code "/"}. * @throws IllegalArgumentException if {@code commandWithSlash} does not start with a {@code "/"}.
*/ */
public static FormatableChat clickableSuggest(String commandWithSlash) { public static FormattableChat clickableSuggest(String commandWithSlash) {
return clickableSuggest(null, commandWithSlash, null); return clickableSuggest(null, commandWithSlash, null);
} }
@ -472,112 +472,112 @@ public abstract class ChatStatic {
/** /**
* Creates a {@link FormatableChat} filling a chat line with decoration and a left-aligned text. * Creates a {@link FormattableChat} filling a chat line with decoration and a left-aligned text.
* @param text the text aligned to the left. * @param text the text aligned to the left.
* @param decorationChar the character used for decoration around the text. * @param decorationChar the character used for decoration around the text.
* @param decorationColor the color used for the decoration characters. * @param decorationColor the color used for the decoration characters.
* @param console if the line is rendered on console (true) or IG (false). * @param console if the line is rendered on console (true) or IG (false).
* @return a new {@link FormatableChat} filling a chat line with decoration and a left-aligned text. * @return a new {@link FormattableChat} filling a chat line with decoration and a left-aligned text.
* @see ChatFilledLine#leftText(ComponentLike) * @see ChatFilledLine#leftText(ComponentLike)
*/ */
public static FormatableChat leftText(ComponentLike text, char decorationChar, TextColor decorationColor, boolean console) { public static FormattableChat leftText(ComponentLike text, char decorationChar, TextColor decorationColor, boolean console) {
return ChatFilledLine.leftText(text).decoChar(decorationChar).decoColor(decorationColor).spacesAroundText().console(console).toChat(); return ChatFilledLine.leftText(text).decoChar(decorationChar).decoColor(decorationColor).spacesAroundText().console(console).toChat();
} }
/** /**
* Creates a {@link FormatableChat} filling a chat line with the configured decoration character and * Creates a {@link FormattableChat} filling a chat line with the configured decoration character and
* color and a left-aligned text. * color and a left-aligned text.
* @param text the text aligned to the left. * @param text the text aligned to the left.
* @param console if the line is rendered on console (true) or IG (false). * @param console if the line is rendered on console (true) or IG (false).
* @return a new {@link FormatableChat} filling a chat line with the configured decoration character * @return a new {@link FormattableChat} filling a chat line with the configured decoration character
* and color and a left-aligned text. * and color and a left-aligned text.
* @see ChatFilledLine#leftText(ComponentLike) * @see ChatFilledLine#leftText(ComponentLike)
* @see ChatConfig#decorationChar * @see ChatConfig#decorationChar
* @see ChatConfig#decorationColor * @see ChatConfig#decorationColor
*/ */
public static FormatableChat leftText(ComponentLike text, boolean console) { public static FormattableChat leftText(ComponentLike text, boolean console) {
return ChatFilledLine.leftText(text).spacesAroundText().console(console).toChat(); return ChatFilledLine.leftText(text).spacesAroundText().console(console).toChat();
} }
/** /**
* Creates a {@link FormatableChat} filling a chat line with decoration and a right-aligned text. * Creates a {@link FormattableChat} filling a chat line with decoration and a right-aligned text.
* @param text the text aligned to the right. * @param text the text aligned to the right.
* @param decorationChar the character used for decoration around the text. * @param decorationChar the character used for decoration around the text.
* @param decorationColor the color used for the decoration characters. * @param decorationColor the color used for the decoration characters.
* @param console if the line is rendered on console (true) or IG (false). * @param console if the line is rendered on console (true) or IG (false).
* @return a new {@link FormatableChat} filling a chat line with decoration and a right-aligned * @return a new {@link FormattableChat} filling a chat line with decoration and a right-aligned
* text. * text.
* @see ChatFilledLine#rightText(ComponentLike) * @see ChatFilledLine#rightText(ComponentLike)
*/ */
public static FormatableChat rightText(ComponentLike text, char decorationChar, TextColor decorationColor, boolean console) { public static FormattableChat rightText(ComponentLike text, char decorationChar, TextColor decorationColor, boolean console) {
return ChatFilledLine.rightText(text).decoChar(decorationChar).decoColor(decorationColor).spacesAroundText().console(console).toChat(); return ChatFilledLine.rightText(text).decoChar(decorationChar).decoColor(decorationColor).spacesAroundText().console(console).toChat();
} }
/** /**
* Creates a {@link FormatableChat} filling a chat line with the configured decoration character and * Creates a {@link FormattableChat} filling a chat line with the configured decoration character and
* color and a right-aligned text. * color and a right-aligned text.
* @param text the text aligned to the right. * @param text the text aligned to the right.
* @param console if the line is rendered on console (true) or IG (false). * @param console if the line is rendered on console (true) or IG (false).
* @return a new {@link FormatableChat} filling a chat line with the configured decoration character * @return a new {@link FormattableChat} filling a chat line with the configured decoration character
* and color and a right-aligned text. * and color and a right-aligned text.
* @see ChatFilledLine#rightText(ComponentLike) * @see ChatFilledLine#rightText(ComponentLike)
* @see ChatConfig#decorationChar * @see ChatConfig#decorationChar
* @see ChatConfig#decorationColor * @see ChatConfig#decorationColor
*/ */
public static FormatableChat rightText(ComponentLike text, boolean console) { public static FormattableChat rightText(ComponentLike text, boolean console) {
return ChatFilledLine.rightText(text).spacesAroundText().console(console).toChat(); return ChatFilledLine.rightText(text).spacesAroundText().console(console).toChat();
} }
/** /**
* Creates a {@link FormatableChat} filling a chat line with decoration and a centered text. * Creates a {@link FormattableChat} filling a chat line with decoration and a centered text.
* @param text the text aligned to the center. * @param text the text aligned to the center.
* @param decorationChar the character used for decoration around the text. * @param decorationChar the character used for decoration around the text.
* @param decorationColor the color used for the decoration characters. * @param decorationColor the color used for the decoration characters.
* @param console if the line is rendered on console (true) or IG (false). * @param console if the line is rendered on console (true) or IG (false).
* @return a new {@link FormatableChat} filling a chat line with decoration and a centered text. * @return a new {@link FormattableChat} filling a chat line with decoration and a centered text.
* @see ChatFilledLine#centerText(ComponentLike) * @see ChatFilledLine#centerText(ComponentLike)
*/ */
public static FormatableChat centerText(ComponentLike text, char decorationChar, TextColor decorationColor, boolean console) { public static FormattableChat centerText(ComponentLike text, char decorationChar, TextColor decorationColor, boolean console) {
return ChatFilledLine.centerText(text).decoChar(decorationChar).decoColor(decorationColor).spacesAroundText().console(console).toChat(); return ChatFilledLine.centerText(text).decoChar(decorationChar).decoColor(decorationColor).spacesAroundText().console(console).toChat();
} }
/** /**
* Creates a {@link FormatableChat} filling a chat line with the configured decoration character and * Creates a {@link FormattableChat} filling a chat line with the configured decoration character and
* color and a centered text. * color and a centered text.
* @param text the text aligned to the center. * @param text the text aligned to the center.
* @param console if the line is rendered on console (true) or IG (false). * @param console if the line is rendered on console (true) or IG (false).
* @return a new {@link FormatableChat} filling a chat line with the configured decoration character * @return a new {@link FormattableChat} filling a chat line with the configured decoration character
* and color and a centered text. * and color and a centered text.
* @see ChatFilledLine#centerText(ComponentLike) * @see ChatFilledLine#centerText(ComponentLike)
* @see ChatConfig#decorationChar * @see ChatConfig#decorationChar
* @see ChatConfig#decorationColor * @see ChatConfig#decorationColor
*/ */
public static FormatableChat centerText(ComponentLike text, boolean console) { public static FormattableChat centerText(ComponentLike text, boolean console) {
return ChatFilledLine.centerText(text).spacesAroundText().console(console).toChat(); return ChatFilledLine.centerText(text).spacesAroundText().console(console).toChat();
} }
/** /**
* Creates a {@link FormatableChat} filling a chat line with a decoration character and color. * Creates a {@link FormattableChat} filling a chat line with a decoration character and color.
* @param decorationChar the character used for decoration. * @param decorationChar the character used for decoration.
* @param decorationColor the color used for the decoration characters. * @param decorationColor the color used for the decoration characters.
* @param console if the line is rendered on console (true) or IG (false). * @param console if the line is rendered on console (true) or IG (false).
* @return a new {@link FormatableChat} filling a chat line with a decoration character and color. * @return a new {@link FormattableChat} filling a chat line with a decoration character and color.
* @see ChatFilledLine#filled() * @see ChatFilledLine#filled()
*/ */
public static FormatableChat filledLine(char decorationChar, TextColor decorationColor, boolean console) { public static FormattableChat filledLine(char decorationChar, TextColor decorationColor, boolean console) {
return ChatFilledLine.filled().decoChar(decorationChar).decoColor(decorationColor).console(console).toChat(); return ChatFilledLine.filled().decoChar(decorationChar).decoColor(decorationColor).console(console).toChat();
} }
/** /**
* Creates a {@link FormatableChat} filling a chat line with the configured decoration character and * Creates a {@link FormattableChat} filling a chat line with the configured decoration character and
* color. * color.
* @param console if the line is rendered on console (true) or IG (false). * @param console if the line is rendered on console (true) or IG (false).
* @return a new {@link FormatableChat} filling a chat line with a decoration character and color. * @return a new {@link FormattableChat} filling a chat line with a decoration character and color.
* @see ChatFilledLine#filled() * @see ChatFilledLine#filled()
* @see ChatConfig#decorationChar * @see ChatConfig#decorationChar
* @see ChatConfig#decorationColor * @see ChatConfig#decorationColor
*/ */
public static FormatableChat filledLine(boolean console) { public static FormattableChat filledLine(boolean console) {
return ChatFilledLine.filled().console(console).toChat(); return ChatFilledLine.filled().console(console).toChat();
} }

View File

@ -1,6 +1,6 @@
package fr.pandacube.lib.chat; package fr.pandacube.lib.chat;
import fr.pandacube.lib.chat.Chat.FormatableChat; import fr.pandacube.lib.chat.Chat.FormattableChat;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.ComponentLike; import net.kyori.adventure.text.ComponentLike;
import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.TextComponent;
@ -152,7 +152,7 @@ public class ChatUtil {
else else
first = false; first = false;
FormatableChat pDisplay = Chat.clickableCommand(Chat.text(page), String.format(cmdFormat, page), Chat.text("Aller à la page " + page)); FormattableChat pDisplay = Chat.clickableCommand(Chat.text(page), String.format(cmdFormat, page), Chat.text("Aller à la page " + page));
if (page == currentPage) { if (page == currentPage) {
pDisplay.highlightedCommandColor(); pDisplay.highlightedCommandColor();
} }
@ -180,12 +180,12 @@ public class ChatUtil {
* @param elements the components to join. * @param elements the components to join.
* @return a new {@link Chat} instance with all the provided {@code component} joined using the separators. * @return a new {@link Chat} instance with all the provided {@code component} joined using the separators.
*/ */
public static FormatableChat joinGrammatically(ComponentLike regularSeparator, ComponentLike finalSeparator, List<? extends ComponentLike> elements) { public static FormattableChat joinGrammatically(ComponentLike regularSeparator, ComponentLike finalSeparator, List<? extends ComponentLike> elements) {
int size = elements == null ? 0 : elements.size(); int size = elements == null ? 0 : elements.size();
int last = size - 1; int last = size - 1;
return switch (size) { return switch (size) {
case 0, 1, 2 -> join(finalSeparator, elements); case 0, 1, 2 -> join(finalSeparator, elements);
default -> (FormatableChat) join(regularSeparator, elements.subList(0, last)) default -> (FormattableChat) join(regularSeparator, elements.subList(0, last))
.then(finalSeparator) .then(finalSeparator)
.then(elements.get(last)); .then(elements.get(last));
}; };
@ -202,8 +202,8 @@ public class ChatUtil {
* @param elements the components to join. * @param elements the components to join.
* @return a new {@link Chat} instance with all the provided {@code component} joined using the separators. * @return a new {@link Chat} instance with all the provided {@code component} joined using the separators.
*/ */
public static FormatableChat join(ComponentLike separator, Iterable<? extends ComponentLike> elements) { public static FormattableChat join(ComponentLike separator, Iterable<? extends ComponentLike> elements) {
FormatableChat c = chat(); FormattableChat c = chat();
if (elements == null) if (elements == null)
return c; return c;
boolean first = true; boolean first = true;
@ -596,7 +596,7 @@ public class ChatUtil {
for (int i = 0; i < sizes.length; i++) { for (int i = 0; i < sizes.length; i++) {
sumSizes += sizes[i]; sumSizes += sizes[i];
FormatableChat subC = ChatStatic.text(repeatedChar(PROGRESS_BAR_FULL_CHAR, sizes[i])); FormattableChat subC = ChatStatic.text(repeatedChar(PROGRESS_BAR_FULL_CHAR, sizes[i]));
if (colors != null && i < colors.length && colors[i] != null) if (colors != null && i < colors.length && colors[i] != null)
subC.color(colors[i]); subC.color(colors[i]);

View File

@ -27,21 +27,11 @@
<artifactId>pandalib-core</artifactId> <artifactId>pandalib-core</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency>
<groupId>fr.pandacube.lib</groupId>
<artifactId>pandalib-reflect</artifactId>
<version>${project.version}</version>
</dependency>
<dependency> <dependency>
<groupId>fr.pandacube.lib</groupId> <groupId>fr.pandacube.lib</groupId>
<artifactId>pandalib-commands</artifactId> <artifactId>pandalib-commands</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency>
<groupId>fr.pandacube.lib</groupId>
<artifactId>pandalib-config</artifactId>
<version>${project.version}</version>
</dependency>
<dependency> <dependency>
<groupId>net.md-5</groupId> <groupId>net.md-5</groupId>
<artifactId>bungeecord-log</artifactId> <artifactId>bungeecord-log</artifactId>

View File

@ -66,7 +66,7 @@ public class CLI extends Thread {
String line; String line;
try { try {
while((line = reader.readLine()) != null) { while((line = reader.readLine()) != null) {
if (line.trim().equals("")) if (line.trim().isEmpty())
continue; continue;
String cmdLine = line; String cmdLine = line;
new Thread(() -> CLIBrigadierDispatcher.instance.execute(cmdLine), "CLICmdThread #"+(i++)).start(); new Thread(() -> CLIBrigadierDispatcher.instance.execute(cmdLine), "CLICmdThread #"+(i++)).start();

View File

@ -32,6 +32,7 @@ public abstract class CLIApplication {
/** /**
* Creates a new application instance. * Creates a new application instance.
*/ */
@SuppressWarnings("CallToPrintStackTrace")
protected CLIApplication() { protected CLIApplication() {
instance = this; instance = this;
CLI tmpCLI = null; CLI tmpCLI = null;

View File

@ -38,16 +38,9 @@ public abstract class CLIBrigadierCommand extends BrigadierCommand<CLICommandSen
} }
protected abstract LiteralArgumentBuilder<CLICommandSender> buildCommand(); protected abstract LiteralArgumentBuilder<CLICommandSender> buildCommand();
protected String[] getAliases() {
return new String[0];
}
public boolean isPlayer(CLICommandSender sender) {
public boolean isPlayer(CLICommandSender sender) {
return sender.isPlayer(); return sender.isPlayer();
} }

View File

@ -41,6 +41,9 @@ public interface CLICommandSender extends Audience {
*/ */
void sendMessage(String message); void sendMessage(String message);
@SuppressWarnings({"UnstableApiUsage", "deprecation"})
@Override // force implementation of super-interface default method @Override // force implementation of super-interface default method
void sendMessage(@NotNull Identity source, @NotNull Component message, @NotNull MessageType type); void sendMessage(@NotNull Identity source, @NotNull Component message, @NotNull MessageType type);
} }

View File

@ -38,7 +38,7 @@ public class CLIConsoleCommandSender implements CLICommandSender {
} }
@Override @Override
public void sendMessage(@NotNull Identity source, @NotNull Component message, @NotNull MessageType type) { public void sendMessage(@NotNull Identity source, @NotNull Component message, @SuppressWarnings({"UnstableApiUsage", "deprecation"}) @NotNull MessageType type) {
sendMessage(Chat.chatComponent(message).getLegacyText()); sendMessage(Chat.chatComponent(message).getLegacyText());
} }
} }

View File

@ -14,7 +14,7 @@ import com.mojang.brigadier.tree.CommandNode;
import com.mojang.brigadier.tree.LiteralCommandNode; import com.mojang.brigadier.tree.LiteralCommandNode;
import com.mojang.brigadier.tree.RootCommandNode; import com.mojang.brigadier.tree.RootCommandNode;
import fr.pandacube.lib.chat.Chat; import fr.pandacube.lib.chat.Chat;
import fr.pandacube.lib.chat.Chat.FormatableChat; import fr.pandacube.lib.chat.Chat.FormattableChat;
import fr.pandacube.lib.chat.ChatTreeNode; import fr.pandacube.lib.chat.ChatTreeNode;
import fr.pandacube.lib.cli.CLIApplication; import fr.pandacube.lib.cli.CLIApplication;
import fr.pandacube.lib.util.log.Log; import fr.pandacube.lib.util.log.Log;
@ -195,13 +195,13 @@ public class CommandAdmin extends CLIBrigadierCommand {
private Component displayCurrentNode(CommandNode<CLICommandSender> node, boolean redirectTarget, CLICommandSender sender) { private Component displayCurrentNode(CommandNode<CLICommandSender> node, boolean redirectTarget, CLICommandSender sender) {
if (node == null) if (node == null)
throw new IllegalArgumentException("node must not be null"); throw new IllegalArgumentException("node must not be null");
FormatableChat d; FormattableChat d;
if (node instanceof RootCommandNode) { if (node instanceof RootCommandNode) {
d = text("(root)").italic() d = text("(root)").italic()
.hover("Root command node"); .hover("Root command node");
} }
else if (node instanceof ArgumentCommandNode) { else if (node instanceof ArgumentCommandNode<?, ?> argNode) {
ArgumentType<?> type = ((ArgumentCommandNode<?, ?>) node).getType(); ArgumentType<?> type = argNode.getType();
String typeStr = type.getClass().getSimpleName(); String typeStr = type.getClass().getSimpleName();
if (type instanceof IntegerArgumentType if (type instanceof IntegerArgumentType
|| type instanceof LongArgumentType || type instanceof LongArgumentType
@ -260,10 +260,10 @@ public class CommandAdmin extends CLIBrigadierCommand {
return d.get(); return d.get();
} }
private static class DisplayCommandNode { private static class DisplayCommandNode {
final List<CommandNode<CLICommandSender>> nodes = new ArrayList<>(); final List<CommandNode<CLICommandSender>> nodes = new ArrayList<>();
final List<DisplayCommandNode> children = new ArrayList<>(); final List<DisplayCommandNode> children = new ArrayList<>();

View File

@ -3,8 +3,8 @@ package fr.pandacube.lib.commands;
import java.util.logging.Logger; import java.util.logging.Logger;
/** /**
* Throw an instance of this exception to indicate to the plugin command handler that the user has missused the command. * Throw an instance of this exception to indicate to the plugin command handler that the user has badly used the command.
* The message, if provided, must indicate the reason of the mussusage of the command. It will be displayed on the * The message, if provided, must indicate the reason of the bad usage of the command. It will be displayed on the
* screen with eventual indications of how to use the command (help command for example). * screen with eventual indications of how to use the command (help command for example).
* If a {@link Throwable} cause is provided, it will be relayed to the plugin {@link Logger}. * If a {@link Throwable} cause is provided, it will be relayed to the plugin {@link Logger}.
* *

View File

@ -223,14 +223,14 @@ public abstract class BrigadierCommand<S> {
/** /**
* Wraps the provided {@link SuggestionsSupplier} into a Brigadiers {@link SuggestionProvider}. * Wraps the provided {@link SuggestionsSupplier} into a Brigadiers {@link SuggestionProvider}.
* @param suggestions the suggestions to wrap. * @param suggestions the suggestions to wrap.
* @param senderUnwrapper function to convert the command sender provided by brigadier into the command sender * @param senderUnWrapper function to convert the command sender provided by brigadier into the command sender
* supported by {@link SuggestionsSupplier}. * supported by {@link SuggestionsSupplier}.
* @return a {@link SuggestionProvider} generating the suggestions from the provided {@link SuggestionsSupplier}. * @return a {@link SuggestionProvider} generating the suggestions from the provided {@link SuggestionsSupplier}.
* @param <AS> the type of command sender supported by the {@link SuggestionsSupplier}. * @param <AS> the type of command sender supported by the {@link SuggestionsSupplier}.
*/ */
protected <AS> SuggestionProvider<S> wrapSuggestions(SuggestionsSupplier<AS> suggestions, Function<S, AS> senderUnwrapper) { protected <AS> SuggestionProvider<S> wrapSuggestions(SuggestionsSupplier<AS> suggestions, Function<S, AS> senderUnWrapper) {
return (context, builder) -> { return (context, builder) -> {
AS sender = senderUnwrapper.apply(context.getSource()); AS sender = senderUnWrapper.apply(context.getSource());
String message = builder.getInput(); String message = builder.getInput();
try { try {
int tokenStartPos = builder.getStart(); int tokenStartPos = builder.getStart();

View File

@ -241,7 +241,7 @@ public interface SuggestionsSupplier<S> {
return (s, ti, token, a) -> { return (s, ti, token, a) -> {
try { try {
List<Long> proposedValues = new ArrayList<>(); List<Long> proposedValues = new ArrayList<>();
if (token.length() == 0) { if (token.isEmpty()) {
long start = Math.max(Math.max(Math.min(-4, max - 9), min), -9); long start = Math.max(Math.max(Math.min(-4, max - 9), min), -9);
long end = Math.min(Math.min(start + 9, max), 9); long end = Math.min(Math.min(start + 9, max), 9);
ListUtil.addLongRangeToList(proposedValues, start, end); ListUtil.addLongRangeToList(proposedValues, start, end);
@ -399,7 +399,7 @@ public interface SuggestionsSupplier<S> {
*/ */
default SuggestionsSupplier<S> quotableString() { default SuggestionsSupplier<S> quotableString() {
return (s, ti, token, a) -> { return (s, ti, token, a) -> {
boolean startWithQuote = token.length() > 0 && (token.charAt(0) == '"' || token.charAt(0) == '\''); boolean startWithQuote = !token.isEmpty() && (token.charAt(0) == '"' || token.charAt(0) == '\'');
String realToken = startWithQuote ? unescapeBrigadierQuotable(token.substring(1), token.charAt(0)) : token; String realToken = startWithQuote ? unescapeBrigadierQuotable(token.substring(1), token.charAt(0)) : token;
String[] argsCopy = Arrays.copyOf(a, a.length); String[] argsCopy = Arrays.copyOf(a, a.length);
argsCopy[a.length - 1] = realToken; argsCopy[a.length - 1] = realToken;

View File

@ -32,7 +32,7 @@ public class Json {
boolean isFloat = value.contains("."); boolean isFloat = value.contains(".");
if (isFloat) { if (isFloat) {
// if float, will only parse to Double // if is float, will only parse to Double
// (see org.yaml.snakeyaml.constructor.SafeConstructor.ConstructYamlFloat) // (see org.yaml.snakeyaml.constructor.SafeConstructor.ConstructYamlFloat)
try { try {
Double d = Double.valueOf(value); Double d = Double.valueOf(value);

View File

@ -134,30 +134,30 @@ public class ThrowableAdapter implements JsonSerializer<Throwable>, JsonDeserial
} }
private static <T extends Throwable> ThrowableSubAdapter<T> defaultSubAdapter(Class<T> clazz) { private static <T extends Throwable> ThrowableSubAdapter<T> defaultSubAdapter(Class<T> clazz) {
BiFunction<String, Throwable, T> constructor = null; BiFunction<String, Throwable, T> constructionFunction = null;
// try (String, Throwable) constructor // try (String, Throwable) constructor
try { try {
Constructor<T> constr = clazz.getConstructor(String.class, Throwable.class); Constructor<T> constructor = clazz.getConstructor(String.class, Throwable.class);
if (constr.canAccess(null)) { if (constructor.canAccess(null)) {
constructor = (m, t) -> ThrowableUtil.wrapReflectEx(() -> constr.newInstance(m, t)); constructionFunction = (m, t) -> ThrowableUtil.wrapReflectEx(() -> constructor.newInstance(m, t));
} }
} catch (ReflectiveOperationException ignore) { } } catch (ReflectiveOperationException ignore) { }
// try (String) constructor // try (String) constructor
try { try {
Constructor<T> constr = clazz.getConstructor(String.class); Constructor<T> constructor = clazz.getConstructor(String.class);
if (constr.canAccess(null)) { if (constructor.canAccess(null)) {
constructor = ThrowableSubAdapter.messageOnly((m) -> ThrowableUtil.wrapReflectEx(() -> constr.newInstance(m))); constructionFunction = ThrowableSubAdapter.messageOnly((m) -> ThrowableUtil.wrapReflectEx(() -> constructor.newInstance(m)));
} }
} catch (ReflectiveOperationException ignore) { } } catch (ReflectiveOperationException ignore) { }
if (constructor == null) { if (constructionFunction == null) {
Log.warning("Provided Throwable class '" + clazz + "' does not have any of those constructors or are not accessible: (String, Throwable), (String)."); Log.warning("Provided Throwable class '" + clazz + "' does not have any of those constructors or are not accessible: (String, Throwable), (String).");
return null; return null;
} }
return new ThrowableSubAdapter<>(constructor); return new ThrowableSubAdapter<>(constructionFunction);
} }

View File

@ -37,8 +37,8 @@ public class MinecraftVersionUtil {
/** /**
* Decompose a version string into a series of integers. * Decompose a version string into a series of integers.
* @param v a string representation of a version (eg. 1.19.1). * @param v a string representation of a version (e.g. 1.19.1).
* @return an array of int representing the provided version (eg. [1, 19, 1]). * @return an array of int representing the provided version (e.g. [1, 19, 1]).
*/ */
public static int[] decomposedVersion(String v) { public static int[] decomposedVersion(String v) {
try { try {

View File

@ -68,12 +68,12 @@ public class ProtocolVersion implements Comparable<ProtocolVersion> {
private static void init() { private static void init() {
// try online source first // try online source first
try { try (HttpClient cl = HttpClient.newBuilder()
HttpResponse<String> response = HttpClient.newBuilder() .connectTimeout(Duration.ofSeconds(5))
.connectTimeout(Duration.ofSeconds(5)) .build()) {
.build() HttpResponse<String> response = cl.send(
.send(HttpRequest.newBuilder(URI.create(ONLINE_DATA_URL)).build(), HttpRequest.newBuilder(URI.create(ONLINE_DATA_URL)).build(),
BodyHandlers.ofString() BodyHandlers.ofString()
); );
if (response.statusCode() == 200) { if (response.statusCode() == 200) {
MinecraftVersionList data = Json.gson.fromJson(response.body(), MinecraftVersionList.class); MinecraftVersionList data = Json.gson.fromJson(response.body(), MinecraftVersionList.class);
@ -123,7 +123,7 @@ public class ProtocolVersion implements Comparable<ProtocolVersion> {
/** /**
* Gets the {@link ProtocolVersion} associated with the provided Minecraft version. * Gets the {@link ProtocolVersion} associated with the provided Minecraft version.
* @param version The Minecraft version, in the format "X.X[.X]" (eg. "1.17" or "1.8.8"). * @param version The Minecraft version, in the format "X.X[.X]" (e.g. "1.17" or "1.8.8").
* @return an instance of {@link ProtocolVersion}. * @return an instance of {@link ProtocolVersion}.
*/ */
public static ProtocolVersion ofVersion(String version) { public static ProtocolVersion ofVersion(String version) {

View File

@ -227,7 +227,7 @@ public final class DB {
*/ */
public static <E extends SQLElement<E>> E getFirst(Class<E> elemClass, SQLWhere<E> where, SQLOrderBy<E> orderBy, Integer offset) throws DBException { public static <E extends SQLElement<E>> E getFirst(Class<E> elemClass, SQLWhere<E> where, SQLOrderBy<E> orderBy, Integer offset) throws DBException {
SQLElementList<E> elements = getAll(elemClass, where, orderBy, 1, offset); SQLElementList<E> elements = getAll(elemClass, where, orderBy, 1, offset);
return (elements.size() == 0) ? null : elements.get(0); return (elements.isEmpty()) ? null : elements.get(0);
} }
/** /**

View File

@ -42,7 +42,7 @@ public class SQLType<T> {
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
return obj instanceof SQLType o return obj instanceof SQLType<?> o
&& toString().equals(o.toString()); && toString().equals(o.toString());
} }

View File

@ -39,7 +39,7 @@ public class GUIHotBar implements Listener {
private final List<Player> currentPlayers = new ArrayList<>(); private final List<Player> currentPlayers = new ArrayList<>();
/** /**
* Setup a new gui hot bar. You should not instantiate more than one hot bar. * Set up a new gui hot bar. You should not instantiate more than one hot bar.
* @param defaultSlot the default slot (currently held item) when the player joins the hot bar. * @param defaultSlot the default slot (currently held item) when the player joins the hot bar.
*/ */
public GUIHotBar(int defaultSlot) { public GUIHotBar(int defaultSlot) {

View File

@ -2,9 +2,12 @@ package fr.pandacube.lib.paper.inventory;
import com.google.common.collect.Streams; import com.google.common.collect.Streams;
import fr.pandacube.lib.chat.Chat; import fr.pandacube.lib.chat.Chat;
import io.papermc.paper.datacomponent.DataComponentType;
import io.papermc.paper.datacomponent.DataComponentType.Valued;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.ComponentLike; import net.kyori.adventure.text.ComponentLike;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.enchantments.Enchantment; import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
@ -12,6 +15,7 @@ import org.bukkit.inventory.meta.Damageable;
import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.ItemMeta;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.function.Consumer; import java.util.function.Consumer;
@ -70,15 +74,10 @@ public class ItemStackBuilder {
private final ItemStack stack; private final ItemStack stack;
private ItemMeta cachedMeta;
private ItemStackBuilder(ItemStack base) { private ItemStackBuilder(ItemStack base) {
stack = base; stack = base;
} }
private ItemMeta getOrInitMeta() {
return (cachedMeta != null) ? cachedMeta : (cachedMeta = stack.getItemMeta());
}
/** /**
* Runs the provided updater on the {@link ItemMeta} instance of the built stack. * Runs the provided updater on the {@link ItemMeta} instance of the built stack.
@ -97,10 +96,7 @@ public class ItemStackBuilder {
* @return itself. * @return itself.
*/ */
public <T extends ItemMeta> ItemStackBuilder meta(Consumer<T> metaUpdater, Class<T> metaType) { public <T extends ItemMeta> ItemStackBuilder meta(Consumer<T> metaUpdater, Class<T> metaType) {
stack.editMeta(metaType, m -> { stack.editMeta(metaType, metaUpdater);
metaUpdater.accept(m);
cachedMeta = m;
});
return this; return this;
} }
@ -166,7 +162,7 @@ public class ItemStackBuilder {
*/ */
public ItemStackBuilder addLoreAfter(List<? extends ComponentLike> lores) { public ItemStackBuilder addLoreAfter(List<? extends ComponentLike> lores) {
if (lores != null) { if (lores != null) {
List<Component> baseLore = getOrInitMeta().lore(); List<Component> baseLore = stack.getItemMeta().lore();
if (baseLore == null) baseLore = Collections.emptyList(); if (baseLore == null) baseLore = Collections.emptyList();
return rawLore( return rawLore(
Streams.concat( Streams.concat(
@ -302,6 +298,98 @@ public class ItemStackBuilder {
} }
/**
* Sets a value for a data component of this item.
* @param dataType the data component type.
* @param dataValue the data component value.
* @return itself.
* @param <T> the data component API type.
*/
public <T> ItemStackBuilder data(Valued<T> dataType, T dataValue) {
stack.setData(dataType, dataValue);
return this;
}
/**
* Unset (set to empty) a value for a data component of this item.
* @param dataType the data component type.
* @return itself.
*/
public ItemStackBuilder unsetData(DataComponentType dataType) {
stack.unsetData(dataType);
return this;
}
/**
* Reset (act as default) a value for a data component of this item.
* @param dataType the data component type.
* @return itself.
*/
public ItemStackBuilder resetData(DataComponentType dataType) {
stack.resetData(dataType);
return this;
}
/**
* Sets the {@code can_break} data component to the provided list of {@link Material}.
* @param canBreak a list of {@link Material}.
* @return itself.
*/
public ItemStackBuilder canBreakMaterials(Collection<Material> canBreak) {
return canBreak(canBreak.stream().map(Material::getKey).toList());
}
/**
* Sets the {@code can_break} data component to the provided list of {@link NamespacedKey}.
* @param canBreak a list of block predicate. If empty, unsets the data component. If null, reset to default.
* @return itself.
*/
@SuppressWarnings("removal")
public ItemStackBuilder canBreak(Collection<NamespacedKey> canBreak) {
@SuppressWarnings("unchecked")
Collection<com.destroystokyo.paper.Namespaced> nsCanBreak = (Collection<com.destroystokyo.paper.Namespaced>) (Collection<?>) canBreak;
return meta(m -> m.setPlaceableKeys(nsCanBreak));
/*
if (canBreak == null)
return resetData(DataComponentTypes.CAN_BREAK);
else if (canBreak.isEmpty())
return unsetData(DataComponentTypes.CAN_BREAK);
else
return data(DataComponentTypes.CAN_BREAK, ItemAdventurePredicate.itemAdventurePredicate(canBreak));*/
}
/**
* Sets the {@code can_place_on} data component to the provided list of {@link Material}.
* @param canPlaceOn a list of {@link Material}.
* @return itself.
*/
public ItemStackBuilder canPlaceOnMaterials(Collection<Material> canPlaceOn) {
return canPlaceOn(canPlaceOn.stream().map(Material::getKey).toList());
}
/**
* Sets the {@code can_place_on} data component to the provided list of {@link NamespacedKey}.
* @param canPlaceOn a list of block predicate. If empty, unsets the data component. If null, reset to default.
* @return itself.
*/
@SuppressWarnings("removal")
public ItemStackBuilder canPlaceOn(Collection<NamespacedKey> canPlaceOn) {
@SuppressWarnings("unchecked")
Collection<com.destroystokyo.paper.Namespaced> nsCanPlaceOn = (Collection<com.destroystokyo.paper.Namespaced>) (Collection<?>) canPlaceOn;
return meta(m -> m.setPlaceableKeys(nsCanPlaceOn));
/* if (canPlaceOn == null)
return resetData(DataComponentTypes.CAN_PLACE_ON);
else if (canPlaceOn.isEmpty())
return unsetData(DataComponentTypes.CAN_PLACE_ON);
else
return data(DataComponentTypes.CAN_PLACE_ON, ItemAdventurePredicate.itemAdventurePredicate(canPlaceOn)); */
}
/** /**
* Build the {@link ItemStack}. * Build the {@link ItemStack}.
* @return the build item stack. * @return the build item stack.

View File

@ -23,7 +23,7 @@ import java.util.Map;
/** /**
* Gson adapter for ConfigurationSerializable, an interface implemented by several classes in the Bukkit API to ease * Gson adapter for ConfigurationSerializable, an interface implemented by several classes in the Bukkit API to ease
* serialization to YAML. * serialization to YAML.
* * <p>
* To not reinvent the wheel, this class uses the Bukkits Yaml API to convert the objects from/to json. * To not reinvent the wheel, this class uses the Bukkits Yaml API to convert the objects from/to json.
*/ */
/* package */ class ConfigurationSerializableAdapter implements JsonSerializer<ConfigurationSerializable>, JsonDeserializer<ConfigurationSerializable> { /* package */ class ConfigurationSerializableAdapter implements JsonSerializer<ConfigurationSerializable>, JsonDeserializer<ConfigurationSerializable> {

View File

@ -493,7 +493,7 @@ public class PerformanceAnalysisManager implements Listener {
/** /**
* Runs the garbage collector on the server. * Runs the garbage collector on the server.
* Depending on the server load and the used memory, this can freeze the server for a second. * Depending on the server load and the used memory, this can freeze the server for a second.
* @param sender the command sender that triggers the garbase collector. Can be null (the report will be sent to the * @param sender the command sender that triggers the garbage collector. Can be null (the report will be sent to the
* console) * console)
*/ */
public static void gc(CommandSender sender) { public static void gc(CommandSender sender) {

View File

@ -14,7 +14,7 @@ import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
@ConcreteWrapper(Coordinates.__concrete.class) @ConcreteWrapper(Coordinates.__concrete.class)
public interface Coordinates extends ReflectWrapperI { public interface Coordinates extends ReflectWrapperI {
public static final ReflectClass<?> REFLECT = wrapEx(() -> Reflect.ofClass("net.minecraft.commands.arguments.coordinates.Coordinates")); ReflectClass<?> REFLECT = wrapEx(() -> Reflect.ofClass("net.minecraft.commands.arguments.coordinates.Coordinates"));
ReflectMethod<?> getPosition = wrapEx(() -> REFLECT.method("getPosition", CommandSourceStack.REFLECT.get())); ReflectMethod<?> getPosition = wrapEx(() -> REFLECT.method("getPosition", CommandSourceStack.REFLECT.get()));
default Vec3 getPosition(io.papermc.paper.command.brigadier.CommandSourceStack source) { default Vec3 getPosition(io.papermc.paper.command.brigadier.CommandSourceStack source) {

View File

@ -1,6 +1,5 @@
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.world; package fr.pandacube.lib.paper.reflect.wrapper.minecraft.world;
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.nbt.CompoundTag;
import fr.pandacube.lib.reflect.Reflect; import fr.pandacube.lib.reflect.Reflect;
import fr.pandacube.lib.reflect.ReflectClass; import fr.pandacube.lib.reflect.ReflectClass;
import fr.pandacube.lib.reflect.ReflectMethod; import fr.pandacube.lib.reflect.ReflectMethod;
@ -12,16 +11,11 @@ import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
public class Entity extends ReflectWrapper { public class Entity extends ReflectWrapper {
public static final ReflectClass<?> REFLECT = wrapEx(() -> Reflect.ofClass("net.minecraft.world.entity.Entity")); public static final ReflectClass<?> REFLECT = wrapEx(() -> Reflect.ofClass("net.minecraft.world.entity.Entity"));
public static final ReflectMethod<?> getBukkitEntity = wrapEx(() -> REFLECT.method("getBukkitEntity")); // spigot method public static final ReflectMethod<?> getBukkitEntity = wrapEx(() -> REFLECT.method("getBukkitEntity")); // spigot method
public static final ReflectMethod<?> serializeEntity = wrapEx(() -> REFLECT.method("serializeEntity", CompoundTag.REFLECT.get())); // paper method
public org.bukkit.entity.Entity getBukkitEntity() { public org.bukkit.entity.Entity getBukkitEntity() {
return (org.bukkit.entity.Entity) wrapReflectEx(() -> getBukkitEntity.invoke(__getRuntimeInstance())); return (org.bukkit.entity.Entity) wrapReflectEx(() -> getBukkitEntity.invoke(__getRuntimeInstance()));
} }
public boolean serializeEntity(CompoundTag nbt) {
return wrapReflectEx(() -> (Boolean) serializeEntity.invoke(__getRuntimeInstance(), unwrap(nbt)));
}
protected Entity(Object obj) { protected Entity(Object obj) {
super(obj); super(obj);
} }

View File

@ -7,7 +7,6 @@ import fr.pandacube.lib.reflect.ReflectMethod;
import fr.pandacube.lib.reflect.wrapper.ReflectWrapperTyped; import fr.pandacube.lib.reflect.wrapper.ReflectWrapperTyped;
import io.papermc.paper.command.brigadier.CommandSourceStack; import io.papermc.paper.command.brigadier.CommandSourceStack;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.plugin.Plugin;
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx; import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx; import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;

View File

@ -19,7 +19,7 @@ public class PluginCommandNode extends ReflectWrapperTyped<LiteralCommandNode<Co
public static final ReflectClass<?> REFLECT = wrapEx(() -> Reflect.ofClass("io.papermc.paper.command.brigadier.PluginCommandNode")); public static final ReflectClass<?> REFLECT = wrapEx(() -> Reflect.ofClass("io.papermc.paper.command.brigadier.PluginCommandNode"));
private static final ReflectMethod<?> getPlugin = wrapEx(() -> REFLECT.method("getPlugin")); private static final ReflectMethod<?> getPlugin = wrapEx(() -> REFLECT.method("getPlugin"));
private static final ReflectMethod<?> getDescription = wrapEx(() -> REFLECT.method("getDescription")); private static final ReflectMethod<?> getDescription = wrapEx(() -> REFLECT.method("getDescription"));
private static final ReflectConstructor CONSTRUCTOR = wrapEx(() -> REFLECT.constructor(String.class, PluginMeta.class, LiteralCommandNode.class, String.class)); private static final ReflectConstructor<?> CONSTRUCTOR = wrapEx(() -> REFLECT.constructor(String.class, PluginMeta.class, LiteralCommandNode.class, String.class));
public PluginCommandNode(@NotNull String literal, @NotNull PluginMeta plugin, @NotNull LiteralCommandNode<CommandSourceStack> rootLiteral, @Nullable String description) { public PluginCommandNode(@NotNull String literal, @NotNull PluginMeta plugin, @NotNull LiteralCommandNode<CommandSourceStack> rootLiteral, @Nullable String description) {

View File

@ -57,8 +57,8 @@ public class AutoUpdatedBossBar implements Listener {
* Schedule the update of this boss bar with synchronisation with the system clock. * Schedule the update of this boss bar with synchronisation with the system clock.
* The underlying method called is {@link Timer#schedule(TimerTask, long, long)}. * The underlying method called is {@link Timer#schedule(TimerTask, long, long)}.
* The updater is executed in a separate Thread. * The updater is executed in a separate Thread.
* @param msDelay ms before running the first update of this bossbar * @param msDelay ms before running the first update of this boss bar.
* @param msPeriod ms between each call of the updater * @param msPeriod ms between each call of the updater.
*/ */
public synchronized void scheduleUpdateTimeSyncThreadAsync(long msDelay, long msPeriod) { public synchronized void scheduleUpdateTimeSyncThreadAsync(long msDelay, long msPeriod) {
if (scheduled) if (scheduled)
@ -82,8 +82,8 @@ public class AutoUpdatedBossBar implements Listener {
* Schedule the update of this boss bar with synchronisation with the ticking of this Minecraft server. * Schedule the update of this boss bar with synchronisation with the ticking of this Minecraft server.
* The underlying method called is {@link BukkitScheduler#runTaskTimer(org.bukkit.plugin.Plugin, Runnable, long, long)}. * The underlying method called is {@link BukkitScheduler#runTaskTimer(org.bukkit.plugin.Plugin, Runnable, long, long)}.
* The updater is executed by the main Server Thread. * The updater is executed by the main Server Thread.
* @param tickDelay number of server tick before running the first update of this boss bar * @param tickDelay number of server tick before running the first update of this boss bar.
* @param tickPeriod number of server tick between each call of the updater * @param tickPeriod number of server tick between each call of the updater.
*/ */
public synchronized void scheduleUpdateTickSyncThreadSync(long tickDelay, long tickPeriod) { public synchronized void scheduleUpdateTickSyncThreadSync(long tickDelay, long tickPeriod) {
if (scheduled) if (scheduled)

View File

@ -141,7 +141,7 @@ public class BukkitEvent {
/** /**
* An single executor event listener. Used for the {@link #register(Class, EventListener)} static method and the other variants. * A single executor event listener. Used for the {@link #register(Class, EventListener)} static method and the other variants.
* @param <E> the event type. * @param <E> the event type.
*/ */
public interface EventListener<E extends Event> extends Listener, EventExecutor { public interface EventListener<E extends Event> extends Listener, EventExecutor {

View File

@ -71,9 +71,7 @@ import fr.pandacube.lib.util.log.Log;
try { try {
DB.getAll(SQLPermissions.class, SQLPermissions.type.eq(EntityType.User.getCode())) DB.getAll(SQLPermissions.class, SQLPermissions.type.eq(EntityType.User.getCode()))
.stream() .stream()
.collect(Collectors.groupingBy(el -> el.get(SQLPermissions.name), .collect(Collectors.groupingBy(el -> el.get(SQLPermissions.name))
Collectors.toCollection(() -> new SQLElementList<SQLPermissions>())
)
) )
.forEach((idStr, pData) -> { .forEach((idStr, pData) -> {
try { try {
@ -100,7 +98,7 @@ import fr.pandacube.lib.util.log.Log;
return initPlayer(playerId, playerData); return initPlayer(playerId, playerData);
} }
private CachedPlayer initPlayer(UUID playerId, SQLElementList<SQLPermissions> playerData) { private CachedPlayer initPlayer(UUID playerId, List<SQLPermissions> playerData) {
Map<String, List<SQLPermissions>> playerRawData = playerData.stream() Map<String, List<SQLPermissions>> playerRawData = playerData.stream()
.collect( .collect(

View File

@ -122,9 +122,11 @@ public final class ReflectField<T> extends ReflectMember<T, String, Field, NoSuc
// if the field is final, we have to do some unsafe stuff :/ // if the field is final, we have to do some unsafe stuff :/
if (sunMiscUnsafeInstance != null) { // Java >= 16 if (sunMiscUnsafeInstance != null) { // Java >= 16
// set the value of the field, directly in the memory // set the value of the field, directly in the memory
@SuppressWarnings("deprecation") // no other options yet. VarHandle blocks edition of final fields
Object unsafeObjInstance = Modifier.isStatic(realModifiers) Object unsafeObjInstance = Modifier.isStatic(realModifiers)
? sunMiscUnsafeInstance.staticFieldBase(f) ? sunMiscUnsafeInstance.staticFieldBase(f)
: instance; : instance;
@SuppressWarnings("deprecation") // no other options yet. VarHandle blocks edition of final fields
long offset = Modifier.isStatic(realModifiers) long offset = Modifier.isStatic(realModifiers)
? sunMiscUnsafeInstance.staticFieldOffset(f) ? sunMiscUnsafeInstance.staticFieldOffset(f)
: sunMiscUnsafeInstance.objectFieldOffset(f); : sunMiscUnsafeInstance.objectFieldOffset(f);

View File

@ -39,7 +39,7 @@ public class ReflectListWrapper<W extends ReflectWrapperI> extends MappedListVie
*/ */
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
return o instanceof List l && backend.equals(l instanceof ReflectListWrapper<?> rw ? rw.backend : l); return o instanceof List<?> l && backend.equals(l instanceof ReflectListWrapper<?> rw ? rw.backend : l);
} }
@Override @Override

View File

@ -16,11 +16,6 @@ public abstract class ReflectWrapperTyped<T> extends ReflectWrapper implements R
super(obj); super(obj);
} }
@Override
public Class<? extends T> __getRuntimeClass() {
return ReflectWrapperTypedI.super.__getRuntimeClass();
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public T __getRuntimeInstance() { public T __getRuntimeInstance() {

View File

@ -6,10 +6,10 @@ import java.util.stream.Collectors;
/** /**
* Utility class to track and limit the amount of a specific value for a specified amount of duration. * Utility class to track and limit the amount of a specific value for a specified amount of duration.
* * <p>
* An exemple of application is for rolling expense limit of a debit card: you cannot expense more that {@code $X} * An exemple of application is for rolling expense limit of a debit card: you cannot expense more that {@code $X}
* during a rolling period of {@code $Y} time. * during a rolling period of {@code $Y} time.
* * <p>
* Here is an example usage of this class: * Here is an example usage of this class:
* <pre> * <pre>
* AmountPerTimeLimiter instance = new AmountPerTimeLimiter(X, Y); * AmountPerTimeLimiter instance = new AmountPerTimeLimiter(X, Y);

View File

@ -55,7 +55,7 @@ public class EnumUtil {
* Search for a specific enum entry in the provided enum type, using the case-insensitive search string. * Search for a specific enum entry in the provided enum type, using the case-insensitive search string.
* unlike {@link #searchEnum(Class, String)}, this method does not statically check the enum type, in case it is not * unlike {@link #searchEnum(Class, String)}, this method does not statically check the enum type, in case it is not
* known at compilation time. * known at compilation time.
* * <p>
* For a statically checked enum type, uses {@link #searchEnum(Class, String)} instead. * For a statically checked enum type, uses {@link #searchEnum(Class, String)} instead.
* *
* @param enumType the class of the enum in which to search * @param enumType the class of the enum in which to search

View File

@ -15,7 +15,7 @@ public class IteratorIterator<T> implements Iterator<T> {
/** /**
* Create an {@link IteratorIterator} with the provided {@link Collection} of {@link Iterable}. * Create an {@link IteratorIterator} with the provided {@link Collection} of {@link Iterable}.
* The iterables iterators will be concatenated in the order of the collections iterator. * The iterable's iterators will be concatenated in the order of the collections iterator.
* @param coll the collection of iterables. * @param coll the collection of iterables.
* @return a new instance of {@link IteratorIterator} iterating over the elements of the provided iterables. * @return a new instance of {@link IteratorIterator} iterating over the elements of the provided iterables.
* @param <T> the type of the values in the iterables. * @param <T> the type of the values in the iterables.
@ -37,7 +37,7 @@ public class IteratorIterator<T> implements Iterator<T> {
/** /**
* Create an {@link IteratorIterator} with the provided array of {@link Iterable}. * Create an {@link IteratorIterator} with the provided array of {@link Iterable}.
* The iterables iterators will be concatenated in the order of the array. * The iterable's iterators will be concatenated in the order of the array.
* @param arr the array of iterables. * @param arr the array of iterables.
* @return a new instance of {@link IteratorIterator} iterating over the elements of the provided iterables. * @return a new instance of {@link IteratorIterator} iterating over the elements of the provided iterables.
* @param <T> the type of the values in the iterables. * @param <T> the type of the values in the iterables.

View File

@ -7,7 +7,7 @@ import java.util.logging.Logger;
/** /**
* Utility class to easily log info into a provided logger. This class avoid the needs to fetch the logger everytime it * Utility class to easily log info into a provided logger. This class avoid the needs to fetch the logger everytime it
* is needed. * is needed.
* * <p>
* For instance, this piece of code: * For instance, this piece of code:
* <pre> * <pre>
* getTheLoggerFromSomewhere().info(message); * getTheLoggerFromSomewhere().info(message);
@ -22,7 +22,7 @@ import java.util.logging.Logger;
* Log.info(message); * Log.info(message);
* </pre> * </pre>
* *
* This the {@link #setLogger(Logger)} method is not called, thi class will use the logger returned by * If the {@link #setLogger(Logger)} method is not called, this class will use the logger returned by
* {@link Logger#getGlobal()}. * {@link Logger#getGlobal()}.
*/ */
public final class Log { public final class Log {

View File

@ -23,6 +23,7 @@ public abstract class AbstractClientWS implements AbstractWS {
private final URI uri; private final URI uri;
private boolean autoReconnect; private boolean autoReconnect;
private boolean isConnecting; private boolean isConnecting;
private HttpClient httpClient = HttpClient.newHttpClient();
private final AtomicReference<WebSocket> socket = new AtomicReference<>(); private final AtomicReference<WebSocket> socket = new AtomicReference<>();
@ -114,7 +115,7 @@ public abstract class AbstractClientWS implements AbstractWS {
synchronized (socket) { synchronized (socket) {
if (autoReconnect && !isConnecting && socket.get() == null) { if (autoReconnect && !isConnecting && socket.get() == null) {
try { try {
Thread.sleep(1000); Thread.sleep(2000);
} catch (InterruptedException ignored) { } catch (InterruptedException ignored) {
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
} }
@ -127,8 +128,10 @@ public abstract class AbstractClientWS implements AbstractWS {
private void connect() { private void connect() {
synchronized (socket) { synchronized (socket) {
isConnecting = true; isConnecting = true;
HttpClient.newHttpClient() if (httpClient == null)
.newWebSocketBuilder() httpClient = HttpClient.newHttpClient();
httpClient.newWebSocketBuilder()
.connectTimeout(Duration.ofSeconds(5)) .connectTimeout(Duration.ofSeconds(5))
.buildAsync(uri, receiveListener) .buildAsync(uri, receiveListener)
.whenCompleteAsync((ws, ex) -> { .whenCompleteAsync((ws, ex) -> {
@ -145,13 +148,15 @@ public abstract class AbstractClientWS implements AbstractWS {
ex = ex.getCause(); ex = ex.getCause();
if (ex instanceof IOException) { if (ex instanceof IOException) {
reconnectIfNecessary(); reconnectIfNecessary();
log("Unable to connect. Trying again...: " + ex); log("Can't connect. Trying again. " + ex);
} }
else { else {
autoReconnect = false; autoReconnect = false;
logError("Error connecting (not trying to reconnect even if asked)", ex); logError("Error connecting (not trying to reconnect even if asked)", ex);
} }
}); });
} }
} }

View File

@ -61,7 +61,7 @@ public abstract class AbstractServerWS extends WebSocketAdapter implements Abstr
} }
@Override @Override
public final void sendClose(int code, String reason) throws IOException { public final void sendClose(int code, String reason) {
getSession().close(code, reason); getSession().close(code, reason);
isClosed = true; isClosed = true;
} }

View File

@ -56,8 +56,8 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<bungeecord.version>1.21-R0.1-SNAPSHOT</bungeecord.version> <bungeecord.version>1.21-R0.1-SNAPSHOT</bungeecord.version>
<paper.version>1.21.3-R0.1</paper.version> <paper.version>1.21.4-R0.1</paper.version>
<mc.version>1.21.3</mc.version> <mc.version>1.21.4</mc.version>
<guava.version>32.1.2-jre</guava.version> <!-- Match the version imported by Paper API/BungeeCord API if possible --> <guava.version>32.1.2-jre</guava.version> <!-- Match the version imported by Paper API/BungeeCord API if possible -->
</properties> </properties>