Compare commits

..

2 Commits

162 changed files with 909 additions and 2016 deletions

View File

@ -3,7 +3,7 @@
### Development library for Minecraft server applications and plugins ### Development library for Minecraft server applications and plugins
This repository contains a collection of maven modules that are used for the development of our Minecraft server. Those This repository contains a collection of maven modules that are used for the development of our Minecraft server. Those
modules are made open source so they can be used by other developpers. Each of them provides different functionalities modules are made open source, so they can be used by other developers. Each of them provides different functionalities
that are detailed in their respective Readme file (if any). 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;
@ -18,10 +18,9 @@ that are detailed in their respective Readme file (if any).
- `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`;
- `pandalib-netapi` A poorly designed, but working TCP network library; - `pandalib-netapi` A poorly designed, but working TCP network library;
- `pandalib-net` A better-designed, packet-based TCP network library (_still in development_);
- `pandalib-commands` An abstract command manager working on top of [Brigadier](https://github.com/Mojang/brigadier); - `pandalib-commands` An abstract command manager working on top of [Brigadier](https://github.com/Mojang/brigadier);
- `pandalib-cli` Utility and helper classes for a standalone CLI Java application. - `pandalib-cli` Utility and helper classes for a standalone CLI Java application.
- `pandalib-core` A catch-all module for some helper classes that didnt have their own module yet; - `pandalib-core` A catch-all module for some helper classes that didn't have their own module yet;
### Use in your projects ### Use in your projects

View File

@ -6,10 +6,11 @@ import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@SuppressWarnings("CanBeFinal")
public class BungeeBackupConfig { public class BungeeBackupConfig {
public boolean workdirBackupEnabled = true; public boolean workdirBackupEnabled = true;
public boolean logsBackupEnabled = true; public boolean logsBackupEnabled = true;
public String scheduling = "0 2 * * *"; // cron format, here is everyday at 2am public String scheduling = "0 2 * * *"; // cron format, here is every day at 2am
public File backupDirectory = null; public File backupDirectory = null;
public BackupCleaner workdirBackupCleaner = BackupCleaner.KEEPING_1_EVERY_N_MONTH(3).merge(BackupCleaner.KEEPING_N_LAST(5)); public BackupCleaner workdirBackupCleaner = BackupCleaner.KEEPING_1_EVERY_N_MONTH(3).merge(BackupCleaner.KEEPING_N_LAST(5));
public List<String> workdirIgnoreList = new ArrayList<>(); public List<String> workdirIgnoreList = new ArrayList<>();

View File

@ -18,15 +18,12 @@ public class BungeeWorkdirProcess extends BackupProcess {
public BiPredicate<File, String> getFilenameFilter() { public BiPredicate<File, String> getFilenameFilter() {
return new BiPredicate<>() { return (file, path) -> {
@Override
public boolean test(File file, String path) {
if (new File(getSourceDir(), "logs").equals(file)) if (new File(getSourceDir(), "logs").equals(file))
return false; return false;
if (file.isFile() && file.getName().endsWith(".lck")) if (file.isFile() && file.getName().endsWith(".lck"))
return false; return false;
return BungeeWorkdirProcess.super.getFilenameFilter().test(file, path); return BungeeWorkdirProcess.super.getFilenameFilter().test(file, path);
}
}; };
} }

View File

@ -28,10 +28,10 @@ public abstract class BungeeBrigadierCommand extends BrigadierCommand<CommandSen
/** /**
* The command dispatcher. * The command dispatcher.
*/ */
protected BungeeBrigadierDispatcher dispatcher = BungeeBrigadierDispatcher.getInstance(); protected final BungeeBrigadierDispatcher dispatcher = BungeeBrigadierDispatcher.getInstance();
/** /**
* Instanciate this command instance. * Instantiate this command instance.
*/ */
public BungeeBrigadierCommand() { public BungeeBrigadierCommand() {
LiteralCommandNode<CommandSender> commandNode; LiteralCommandNode<CommandSender> commandNode;

View File

@ -39,7 +39,7 @@ public class BungeeBrigadierDispatcher extends BrigadierDispatcher<CommandSender
*/ */
public BungeeBrigadierDispatcher(Plugin pl) { public BungeeBrigadierDispatcher(Plugin pl) {
if (instance != null) if (instance != null)
throw new IllegalStateException("Cannot instanciante more than one BungeeBrigadierDispatcher"); throw new IllegalStateException("Cannot instantiate more than one BungeeBrigadierDispatcher");
instance = this; instance = this;
plugin = pl; plugin = pl;
ProxyServer.getInstance().getPluginManager().registerListener(plugin, this); ProxyServer.getInstance().getPluginManager().registerListener(plugin, this);
@ -47,7 +47,7 @@ public class BungeeBrigadierDispatcher extends BrigadierDispatcher<CommandSender
/** /**
* Called when a player sends a chat message. Used to gets the typed command and execute it. * Called when a player sends a chat message. Used to get the typed command and execute it.
* @param event the event. * @param event the event.
*/ */
@EventHandler @EventHandler

View File

@ -4,7 +4,6 @@ import fr.pandacube.lib.chat.Chat;
import fr.pandacube.lib.core.mc_version.ProtocolVersion; import fr.pandacube.lib.core.mc_version.ProtocolVersion;
import fr.pandacube.lib.players.standalone.AbstractOnlinePlayer; import fr.pandacube.lib.players.standalone.AbstractOnlinePlayer;
import fr.pandacube.lib.reflect.Reflect; import fr.pandacube.lib.reflect.Reflect;
import fr.pandacube.lib.util.MinecraftVersion;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufAllocator;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
@ -49,16 +48,6 @@ public interface BungeeOnlinePlayer extends BungeeOffPlayer, AbstractOnlinePlaye
return getBungeeProxiedPlayer().getServer(); return getBungeeProxiedPlayer().getServer();
} }
/**
* Gets the minecraft version of this players client.
* @return the minecraft version of this players client.
* @deprecated use {@link #getProtocolVersion()} instead.
*/
@Deprecated(forRemoval = true)
default MinecraftVersion getMinecraftVersion() {
return MinecraftVersion.getVersion(getBungeeProxiedPlayer().getPendingConnection().getVersion());
}
/** /**
* Gets the protocol version of this players client. * Gets the protocol version of this players client.
* @return the protocol version of this players client. * @return the protocol version of this players client.

View File

@ -9,7 +9,7 @@ import java.util.logging.Level;
import java.util.logging.LogRecord; import java.util.logging.LogRecord;
/** /**
* A log rotate that extends the functionnalities of {@link DailyLogRotateFileHandler} * A log rotate that extends the functionalities of {@link DailyLogRotateFileHandler}
* to adapt with bungee specificities. * to adapt with bungee specificities.
*/ */
public class BungeeDailyLogRotateFileHandler extends DailyLogRotateFileHandler { public class BungeeDailyLogRotateFileHandler extends DailyLogRotateFileHandler {
@ -35,9 +35,10 @@ public class BungeeDailyLogRotateFileHandler extends DailyLogRotateFileHandler {
@Override @Override
public boolean isLoggable(LogRecord record) { public boolean isLoggable(LogRecord record) {
String formattedRecord = getFormatter().format(record); String formattedRecord = getFormatter().format(record);
if (formattedRecord.contains("<-> InitialHandler has connected")) return false; return !(
if (formattedRecord.contains("<-> InitialHandler has pinged")) return false; formattedRecord.contains("<-> InitialHandler has connected")
return true; || formattedRecord.contains("<-> InitialHandler has pinged")
);
} }
} }

View File

@ -23,6 +23,7 @@ import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.chat.BaseComponent;
import org.jetbrains.annotations.NotNull;
/** /**
* A builder for chat components. * A builder for chat components.
@ -30,10 +31,10 @@ import net.md_5.bungee.api.chat.BaseComponent;
* Use one of the provided static methods to create a new instance. * Use one of the provided static methods to create a new instance.
* <p> * <p>
* 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 implentation 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 formating of the * The unique possible concrete subclass of this class, {@link FormatableChat}, takes care of the formatting of the
* builded 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 FormatableChat}.
*/ */
public abstract sealed class Chat extends ChatStatic implements HoverEventSource<Component>, ComponentLike { public abstract sealed class Chat extends ChatStatic implements HoverEventSource<Component>, ComponentLike {
@ -60,7 +61,7 @@ public abstract sealed class Chat extends ChatStatic implements HoverEventSource
/** /**
* Builds the component into Adventure Component instance. * Builds the component into Adventure Component instance.
* @return the {@link Component} builded from this {@link Chat} component. * @return the {@link Component} built from this {@link Chat} component.
*/ */
public Component getAdv() { public Component getAdv() {
return builder.build(); return builder.build();
@ -68,7 +69,7 @@ public abstract sealed class Chat extends ChatStatic implements HoverEventSource
/** /**
* Builds the component into BungeeCord {@link BaseComponent} instance. * Builds the component into BungeeCord {@link BaseComponent} instance.
* @return the {@link BaseComponent} builded from this {@link Chat} component. * @return the {@link BaseComponent} built from this {@link Chat} component.
*/ */
public BaseComponent get() { public BaseComponent get() {
return toBungee(getAdv()); return toBungee(getAdv());
@ -76,27 +77,27 @@ public abstract sealed class Chat extends ChatStatic implements HoverEventSource
/** /**
* Builds the component into BungeeCord {@link BaseComponent} array. * Builds the component into BungeeCord {@link BaseComponent} array.
* @return the {@link BaseComponent} array builded from this {@link Chat} component. * @return the {@link BaseComponent} array built from this {@link Chat} component.
*/ */
public BaseComponent[] getAsArray() { public BaseComponent[] getAsArray() {
return toBungeeArray(getAdv()); return toBungeeArray(getAdv());
} }
private static final LegacyComponentSerializer LEGACY_SERIALIZER_BUNGEE_FIENDLY = LegacyComponentSerializer.builder() private static final LegacyComponentSerializer LEGACY_SERIALIZER_BUNGEE_FRIENDLY = LegacyComponentSerializer.builder()
.hexColors() .hexColors()
.useUnusualXRepeatedCharacterHexFormat() .useUnusualXRepeatedCharacterHexFormat()
.build(); .build();
/** /**
* Converts the builded component into legacy text. * Converts the built component into legacy text.
* @return the legacy text. RGB colors are in BungeeCord format. * @return the legacy text. RGB colors are in BungeeCord format.
*/ */
public String getLegacyText() { public String getLegacyText() {
return LEGACY_SERIALIZER_BUNGEE_FIENDLY.serialize(getAdv()); return LEGACY_SERIALIZER_BUNGEE_FRIENDLY.serialize(getAdv());
} }
/** /**
* Converts the builded component into plain text. * Converts the built component into plain text.
* @return the plain text of this component. * @return the plain text of this component.
*/ */
public String getPlainText() { public String getPlainText() {
@ -104,16 +105,16 @@ public abstract sealed class Chat extends ChatStatic implements HoverEventSource
} }
@Override @Override
public HoverEvent<Component> asHoverEvent(UnaryOperator<Component> op) { public @NotNull HoverEvent<Component> asHoverEvent(@NotNull UnaryOperator<Component> op) {
return HoverEvent.showText(op.apply(getAdv())); return HoverEvent.showText(op.apply(getAdv()));
} }
/** /**
* Builds the component into Adventure Component instance. * Builds the component into Adventure Component instance.
* @return the {@link Component} builded from this {@link Chat} component. * @return the {@link Component} built from this {@link Chat} component.
*/ */
@Override @Override
public Component asComponent() { public @NotNull Component asComponent() {
return getAdv(); return getAdv();
} }
@ -284,8 +285,8 @@ public abstract sealed class Chat extends ChatStatic implements HoverEventSource
public Chat thenTranslation(String key, Object... with) { return then(translation(key, with)); } public Chat thenTranslation(String key, Object... with) { return then(translation(key, with)); }
/** /**
* Appends a component with the provided keybind. * Appends a component with the provided keybinding.
* @param key the keybind 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)); }
@ -443,19 +444,19 @@ public abstract sealed class Chat extends ChatStatic implements HoverEventSource
/** /**
* Appends a component filling a line of chat (or console) 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 line of chat (or console) with the configured decoration character * @return a new {@link FormatableChat} 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)); }
/** /**
* Appends a component filling a line of chat (or console) 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 line of chat (or console) with the configured decoration character * @return a new {@link FormatableChat} filling a chat line with the configured decoration character
* and color and a left-aligned text. * and color and a left-aligned text.
* @deprecated uses Bungeecord chat API. * @deprecated uses Bungeecord chat API.
*/ */
@ -463,19 +464,19 @@ public abstract sealed class Chat extends ChatStatic implements HoverEventSource
public Chat thenLeftText(BaseComponent leftText) { return thenLeftText(chatComponent(leftText)); } public Chat thenLeftText(BaseComponent leftText) { return thenLeftText(chatComponent(leftText)); }
/** /**
* Appends a component filling a line of chat (or console) 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 line of chat (or console) with the configured decoration character * @return a new {@link FormatableChat} 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)); }
/** /**
* Appends a component filling a line of chat (or console) 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 line of chat (or console) with the configured decoration character * @return a new {@link FormatableChat} filling a chat line with the configured decoration character
* and color and a right-aligned text. * and color and a right-aligned text.
* @deprecated uses Bungeecord chat API. * @deprecated uses Bungeecord chat API.
*/ */
@ -483,10 +484,10 @@ public abstract sealed class Chat extends ChatStatic implements HoverEventSource
public Chat thenRightText(BaseComponent rightText) { return thenRightText(chatComponent(rightText)); } public Chat thenRightText(BaseComponent rightText) { return thenRightText(chatComponent(rightText)); }
/** /**
* Appends a component filling a line of chat (or console) 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 line of chat (or console) with the configured decoration character * @return a new {@link FormatableChat} 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) {
@ -494,10 +495,10 @@ public abstract sealed class Chat extends ChatStatic implements HoverEventSource
} }
/** /**
* Appends a component filling a line of chat (or console) 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 line of chat (or console) with the configured decoration character * @return a new {@link FormatableChat} filling a chat line with the configured decoration character
* and color and a centered text. * and color and a centered text.
* @deprecated uses Bungeecord chat API. * @deprecated uses Bungeecord chat API.
*/ */
@ -507,8 +508,8 @@ public abstract sealed class Chat extends ChatStatic implements HoverEventSource
} }
/** /**
* Appends a component filling a line of chat (or console) 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 line of chat (or console) with a decoration character and color. * @return a new {@link FormatableChat} filling a chat line with a decoration character and color.
*/ */
public Chat thenFilledLine() { return then(filledLine(console)); } public Chat thenFilledLine() { return then(filledLine(console)); }
@ -534,11 +535,11 @@ public abstract sealed class Chat extends ChatStatic implements HoverEventSource
* .append("!").color(ChatColor.RED) * .append("!").color(ChatColor.RED)
* .create(); * .create();
* }</pre> * }</pre>
* Here, when you call a formating method (like {@code bold(boolean)} or {@code color(ChatColor)}) after the * Here, when you call a formatting method (like {@code bold(boolean)} or {@code color(ChatColor)}) after the
* {@code append(String)} method, the formating apply to the last sub-component appended. * {@code append(String)} method, the formatting apply to the last subcomponent appended.
* <p> * <p>
* In our design, we want the formating to apply to the currently builded component, not the last appended one. * In our design, we want the formatting to apply to the currently built component, not the last appended one.
* The purpose is to make the component structure clearer and have better control of the formating over the * The purpose is to make the component structure clearer and have better control of the formatting over the
* component hierarchy. * component hierarchy.
* Here is the equivalent of the above code, with the {@link Chat} API: * Here is the equivalent of the above code, with the {@link Chat} API:
* <pre>{@code * <pre>{@code
@ -547,9 +548,9 @@ 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, casted * When calling {@link #then(Component) #then(...)} on a {@link FormatableChat}, the method returns itself, cast
* to {@link Chat}, to prevent future formating (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
* sub-component). If the formatting of the currently builded 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 FormatableChat}, 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()
@ -986,7 +987,7 @@ public abstract sealed class Chat extends ChatStatic implements HoverEventSource
} }
/** /**
* Force the italic formating to be set to false if it is not explicitely 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 lores 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.

View File

@ -6,7 +6,7 @@ import java.util.List;
import net.kyori.adventure.text.format.TextColor; import net.kyori.adventure.text.format.TextColor;
/** /**
* A custom gradient with a least 2 colors in it. * A custom gradient with at least 2 colors in it.
*/ */
public class ChatColorGradient { public class ChatColorGradient {
private record GradientColor(float location, TextColor color) { } private record GradientColor(float location, TextColor color) { }

View File

@ -14,7 +14,7 @@ public class ChatColorUtil {
/** /**
* All characters that represent a colorcode. * All characters that represent a color code.
*/ */
public static final String ALL_COLORS = "0123456789AaBbCcDdEeFf"; public static final String ALL_COLORS = "0123456789AaBbCcDdEeFf";
/** /**
@ -30,7 +30,7 @@ public class ChatColorUtil {
* Returns the legacy format needed to reproduce the format at the end of the provided legacy text. * Returns the legacy format needed to reproduce the format at the end of the provided legacy text.
* Supports standard chat colors and formats, BungeeCord Chat rgb format and EssentialsX rgb format. * Supports standard chat colors and formats, BungeeCord Chat rgb format and EssentialsX rgb format.
* The RGB value from EssentialsX format is converted to BungeeCord Chat when included in the returned value. * The RGB value from EssentialsX format is converted to BungeeCord Chat when included in the returned value.
* @param legacyText the legacy formated text. * @param legacyText the legacy formatted text.
* @return the active format at the end of the provided text. * @return the active format at the end of the provided text.
*/ */
public static String getLastColors(String legacyText) { public static String getLastColors(String legacyText) {
@ -84,8 +84,8 @@ public class ChatColorUtil {
} }
/** /**
* Returns the {@link ChatColor} associated with the provided char, case insensitive. * Returns the {@link ChatColor} associated with the provided char, case-insensitive.
* @param code the case insensitive char code. * @param code the case-insensitive char code.
* @return the corresponding {@link ChatColor}. * @return the corresponding {@link ChatColor}.
*/ */
public static ChatColor getChatColorByChar(char code) { public static ChatColor getChatColorByChar(char code) {

View File

@ -8,6 +8,7 @@ import net.kyori.adventure.text.format.TextColor;
/** /**
* Class holding static configuration values for chat component rendering. * Class holding static configuration values for chat component rendering.
*/ */
@SuppressWarnings("CanBeFinal")
public class ChatConfig { public class ChatConfig {
/** /**
@ -29,7 +30,7 @@ public class ChatConfig {
/** /**
* The color used for successful messages. * The color used for successful messages.
*/ */
public static TextColor successColor = PandaTheme.CHAT_GREEN_SATMAX; public static TextColor successColor = PandaTheme.CHAT_GREEN_MAX_SAT;
/** /**
* The color used for error/failure messages. * The color used for error/failure messages.
@ -67,14 +68,14 @@ public class ChatConfig {
public static TextColor highlightedCommandColor = NamedTextColor.WHITE; public static TextColor highlightedCommandColor = NamedTextColor.WHITE;
/** /**
* The color used for broadcasted messages. * The color used for broadcast messages.
* It is often used in combination with {@link #prefix}. * It is often used in combination with {@link #prefix}.
*/ */
public static TextColor broadcastColor = NamedTextColor.YELLOW; public static TextColor broadcastColor = NamedTextColor.YELLOW;
/** /**
* The prefix used for prefixed messages. * The prefix used for prefixed messages.
* It can be a sylized name of the server, like {@code "[Pandacube] "}. * It can be a stylized name of the server, like {@code "[Pandacube] "}.
* It is often used in combination with {@link #broadcastColor}. * It is often used in combination with {@link #broadcastColor}.
*/ */
public static Supplier<Chat> prefix = PandaTheme::CHAT_MESSAGE_PREFIX; public static Supplier<Chat> prefix = PandaTheme::CHAT_MESSAGE_PREFIX;
@ -104,7 +105,7 @@ public class ChatConfig {
public static final TextColor CHAT_GREEN_4 = TextColor.fromHexString("#abe3b0"); // h=126 s=50 l=78 public static final TextColor CHAT_GREEN_4 = TextColor.fromHexString("#abe3b0"); // h=126 s=50 l=78
/** Green max saturation color. */ /** Green max saturation color. */
public static final TextColor CHAT_GREEN_SATMAX = TextColor.fromHexString("#00ff19"); // h=126 s=100 l=50 public static final TextColor CHAT_GREEN_MAX_SAT = TextColor.fromHexString("#00ff19"); // h=126 s=100 l=50
/** Green 1 saturated color. */ /** Green 1 saturated color. */
public static final TextColor CHAT_GREEN_1_SAT = TextColor.fromHexString("#20d532"); // h=126 s=50 l=48 public static final TextColor CHAT_GREEN_1_SAT = TextColor.fromHexString("#20d532"); // h=126 s=50 l=48
/** Green 2 saturated color. */ /** Green 2 saturated color. */

View File

@ -140,7 +140,7 @@ public class ChatFilledLine implements ComponentLike {
/** /**
* Renders this line to a {@link FormatableChat}. * Renders this line to a {@link FormatableChat}.
* @return a new {@link FormatableChat} builded by this {@link ChatFilledLine}. * @return a new {@link FormatableChat} built by this {@link ChatFilledLine}.
*/ */
public FormatableChat toChat() { public FormatableChat toChat() {
int maxWidth = (this.maxWidth != null) int maxWidth = (this.maxWidth != null)

View File

@ -227,9 +227,9 @@ public abstract class ChatStatic {
} }
/** /**
* Creates a {@link FormatableChat} with the provided keybind. * Creates a {@link FormatableChat} with the provided keybinding.
* @param key the keybind to display. * @param key the keybinding to display.
* @return a new {@link FormatableChat} with the provided keybind. * @return a new {@link FormatableChat} with the provided keybinding.
*/ */
public static FormatableChat keybind(String key) { public static FormatableChat keybind(String key) {
return new FormatableChat(Component.keybind().keybind(key)); return new FormatableChat(Component.keybind().keybind(key));
@ -451,12 +451,12 @@ public abstract class ChatStatic {
/** /**
* Creates a {@link FormatableChat} filling a line of chat (or console) with decoration and a left-aligned text. * Creates a {@link FormatableChat} 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 line of chat (or console) with decoration and a left-aligned text. * @return a new {@link FormatableChat} 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 FormatableChat leftText(ComponentLike text, char decorationChar, TextColor decorationColor, boolean console) {
@ -464,11 +464,11 @@ public abstract class ChatStatic {
} }
/** /**
* Creates a {@link FormatableChat} filling a line of chat (or console) with the configured decoration character and * Creates a {@link FormatableChat} 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 line of chat (or console) with the configured decoration character * @return a new {@link FormatableChat} 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
@ -479,12 +479,12 @@ public abstract class ChatStatic {
} }
/** /**
* Creates a {@link FormatableChat} filling a line of chat (or console) with decoration and a right-aligned text. * Creates a {@link FormatableChat} 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 line of chat (or console) with decoration and a right-aligned * @return a new {@link FormatableChat} filling a chat line with decoration and a right-aligned
* text. * text.
* @see ChatFilledLine#rightText(ComponentLike) * @see ChatFilledLine#rightText(ComponentLike)
*/ */
@ -493,11 +493,11 @@ public abstract class ChatStatic {
} }
/** /**
* Creates a {@link FormatableChat} filling a line of chat (or console) with the configured decoration character and * Creates a {@link FormatableChat} 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 line of chat (or console) with the configured decoration character * @return a new {@link FormatableChat} 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
@ -508,12 +508,12 @@ public abstract class ChatStatic {
} }
/** /**
* Creates a {@link FormatableChat} filling a line of chat (or console) with decoration and a centered text. * Creates a {@link FormatableChat} 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 line of chat (or console) with decoration and a centered text. * @return a new {@link FormatableChat} 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 FormatableChat centerText(ComponentLike text, char decorationChar, TextColor decorationColor, boolean console) {
@ -521,11 +521,11 @@ public abstract class ChatStatic {
} }
/** /**
* Creates a {@link FormatableChat} filling a line of chat (or console) with the configured decoration character and * Creates a {@link FormatableChat} 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 line of chat (or console) with the configured decoration character * @return a new {@link FormatableChat} 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
@ -536,11 +536,11 @@ public abstract class ChatStatic {
} }
/** /**
* Creates a {@link FormatableChat} filling a line of chat (or console) with a decoration character and color. * Creates a {@link FormatableChat} 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 line of chat (or console) with a decoration character and color. * @return a new {@link FormatableChat} 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 FormatableChat filledLine(char decorationChar, TextColor decorationColor, boolean console) {
@ -548,10 +548,10 @@ public abstract class ChatStatic {
} }
/** /**
* Creates a {@link FormatableChat} filling a line of chat (or console) with the configured decoration character and * Creates a {@link FormatableChat} 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 line of chat (or console) with a decoration character and color. * @return a new {@link FormatableChat} 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
@ -633,7 +633,7 @@ public abstract class ChatStatic {
.storage(((StorageNBTComponent) c).storage()); .storage(((StorageNBTComponent) c).storage());
} }
else { else {
throw new IllegalArgumentException("Unknows component type " + c.getClass()); throw new IllegalArgumentException("Unknown component type " + c.getClass());
} }
return builder.style(c.style()).append(c.children()); return builder.style(c.style()).append(c.children());
} }

View File

@ -27,7 +27,7 @@ public class ChatTreeNode {
public final List<ChatTreeNode> children = new ArrayList<>(); public final List<ChatTreeNode> children = new ArrayList<>();
/** /**
* Construct an new {@link ChatTreeNode}. * Construct a new {@link ChatTreeNode}.
* @param cmp the component for the current node. * @param cmp the component for the current node.
*/ */
public ChatTreeNode(Chat cmp) { public ChatTreeNode(Chat cmp) {
@ -48,7 +48,7 @@ public class ChatTreeNode {
* Generate a tree view based on this tree structure. * Generate a tree view based on this tree structure.
* <p> * <p>
* Each element in the returned list represent 1 line of this tree view. * Each element in the returned list represent 1 line of this tree view.
* Thus, the caller may send each line separately or at once depending of the quantity of data. * Thus, the caller may send each line separately or at once, depending on the quantity of data.
* @param console true to render for console, false otherwise. * @param console true to render for console, false otherwise.
* @return an array of component, each element being a single line. * @return an array of component, each element being a single line.
*/ */

View File

@ -22,7 +22,7 @@ import net.md_5.bungee.api.ChatColor;
import fr.pandacube.lib.chat.Chat.FormatableChat; import fr.pandacube.lib.chat.Chat.FormatableChat;
/** /**
* Provides various methods and properties to manipulate text displayed in chat an other parts of the game. * Provides various methods and properties to manipulate text displayed in chat and other parts of the game.
*/ */
public class ChatUtil { public class ChatUtil {
@ -48,7 +48,7 @@ public class ChatUtil {
/** /**
* Mapping indicating the text pixel with for specific characters in the default Minecraft font. * Mapping indicating the text pixel with for specific characters in the default Minecraft font.
* If a character doesnt have a mapping in this map, then its width is {@link #DEFAULT_CHAR_SIZE}. * If a character doesn't have a mapping in this map, then its width is {@link #DEFAULT_CHAR_SIZE}.
*/ */
public static final Map<Character, Integer> CHAR_SIZES; public static final Map<Character, Integer> CHAR_SIZES;
static { static {
@ -112,7 +112,7 @@ public class ChatUtil {
* @param nbPages the number of pages. * @param nbPages the number of pages.
* @param nbPagesToDisplay the number of pages to display around the first page, the last page and the * @param nbPagesToDisplay the number of pages to display around the first page, the last page and the
* {@code currentPage}. * {@code currentPage}.
* @return a {@link Chat} containging the created page navigator. * @return a {@link Chat} containing the created page navigator.
*/ */
public static Chat createPagination(String prefix, String cmdFormat, int currentPage, int nbPages, int nbPagesToDisplay) { public static Chat createPagination(String prefix, String cmdFormat, int currentPage, int nbPages, int nbPagesToDisplay) {
Set<Integer> pagesToDisplay = new TreeSet<>(); Set<Integer> pagesToDisplay = new TreeSet<>();
@ -149,11 +149,11 @@ public class ChatUtil {
else else
first = false; first = false;
FormatableChat pDisp = Chat.clickableCommand(Chat.text(page), String.format(cmdFormat, page), Chat.text("Aller à la page " + page)); FormatableChat pDisplay = Chat.clickableCommand(Chat.text(page), String.format(cmdFormat, page), Chat.text("Aller à la page " + page));
if (page == currentPage) { if (page == currentPage) {
pDisp.highlightedCommandColor(); pDisplay.highlightedCommandColor();
} }
d.then(pDisp); d.then(pDisplay);
previous = page; previous = page;
} }
@ -258,7 +258,7 @@ public class ChatUtil {
/** /**
* Wraps the provided text in multiple lines, taking into account the legacy formating. * Wraps the provided text in multiple lines, taking into account the legacy formatting.
* <p> * <p>
* This method only takes into account IG text width. Use a regular text-wrapper for console instead. * This method only takes into account IG text width. Use a regular text-wrapper for console instead.
* @param legacyText the text to wrap. * @param legacyText the text to wrap.
@ -272,7 +272,7 @@ public class ChatUtil {
} }
/** /**
* Wraps the provided text in multiple lines, taking into account the legacy formating. * Wraps the provided text in multiple lines, taking into account the legacy formatting.
* <p> * <p>
* This method only takes into account IG text width. Use a regular text-wrapper for console instead. * This method only takes into account IG text width. Use a regular text-wrapper for console instead.
* @param legacyText the text to wrap. * @param legacyText the text to wrap.
@ -369,7 +369,7 @@ public class ChatUtil {
/** /**
* Try to render a matrix of {@link Chat} components into a table in the chat or console. * Try to render a matrix of {@link Chat} components into a table in the chat or console.
* @param data the component, in the form of {@link List} of {@link List} of {@link Chat}. The englobing list holds * @param data the component, in the form of {@link List} of {@link List} of {@link Chat}. The parent list holds
* the table lines (line 0 being the top line). Each sublist holds the cells content (element 0 is the * the table lines (line 0 being the top line). Each sublist holds the cells content (element 0 is the
* leftText one). The row lengths can be different. * leftText one). The row lengths can be different.
* @param space a spacer to put between columns. * @param space a spacer to put between columns.
@ -392,7 +392,7 @@ public class ChatUtil {
/** /**
* Try to render a matrix of {@link Component} components into a table in the chat or console. * Try to render a matrix of {@link Component} components into a table in the chat or console.
* @param data the component, in the form of {@link List} of {@link List} of {@link Component}. The englobing list holds * @param data the component, in the form of {@link List} of {@link List} of {@link Component}. The parent list holds
* the table lines (line 0 being the top line). Each sublist holds the cells content (element 0 is the * the table lines (line 0 being the top line). Each sublist holds the cells content (element 0 is the
* leftText one). The row lengths can be different. * leftText one). The row lengths can be different.
* @param space a spacer to put between columns. * @param space a spacer to put between columns.
@ -505,9 +505,9 @@ public class ChatUtil {
private static final char PROGRESS_BAR_FULL_CHAR = '|'; private static final char PROGRESS_BAR_FULL_CHAR = '|';
/** /**
* Generate a (eventually multi-part) progress bar using text. * Generate a (eventually multipart) progress bar using text.
* @param values the values to render in the progress bar. * @param values the values to render in the progress bar.
* @param colors the colors attributed to each values. * @param colors the colors attributed to each value.
* @param total the total value of the progress bar. * @param total the total value of the progress bar.
* @param width the width in which the progress bar should fit (in pixel for IG, in character count for console) * @param width the width in which the progress bar should fit (in pixel for IG, in character count for console)
* @param console true if the progress bar is intended to be displayed on the console, false if its in game chat. * @param console true if the progress bar is intended to be displayed on the console, false if its in game chat.

View File

@ -11,7 +11,7 @@ import org.fusesource.jansi.AnsiConsole;
import fr.pandacube.lib.util.Log; import fr.pandacube.lib.util.Log;
/** /**
* Class to hangle general standard IO operation for a CLI application. It uses Jlines {@link ConsoleReader} for the * Class to handle general standard IO operation for a CLI application. It uses Jlines {@link ConsoleReader} for the
* console rendering, a JUL {@link Logger} for logging, and Brigadier to handle commands. * console rendering, a JUL {@link Logger} for logging, and Brigadier to handle commands.
*/ */
public class CLI extends Thread { public class CLI extends Thread {
@ -33,7 +33,7 @@ public class CLI extends Thread {
reader.setPrompt(">"); reader.setPrompt(">");
reader.addCompleter(CLIBrigadierDispatcher.instance); reader.addCompleter(CLIBrigadierDispatcher.instance);
// configuration du formatteur pour le logger // configure logger's formatter
System.setProperty("net.md_5.bungee.log-date-format", "yyyy-MM-dd HH:mm:ss"); System.setProperty("net.md_5.bungee.log-date-format", "yyyy-MM-dd HH:mm:ss");
logger = CLILogger.getLogger(this); logger = CLILogger.getLogger(this);
} }

View File

@ -64,6 +64,7 @@ public abstract class CLIApplication {
private final Object stopLock = new Object(); private final Object stopLock = new Object();
private final AtomicBoolean stopping = new AtomicBoolean(false); private final AtomicBoolean stopping = new AtomicBoolean(false);
@SuppressWarnings("finally")
public final void stop() { public final void stop() {
synchronized (stopLock) { synchronized (stopLock) {
synchronized (stopping) { synchronized (stopping) {

View File

@ -15,7 +15,7 @@ import java.util.function.Predicate;
public abstract class CLIBrigadierCommand extends BrigadierCommand<CLICommandSender> { public abstract class CLIBrigadierCommand extends BrigadierCommand<CLICommandSender> {
/** /**
* Instanciate this command instance. * Instantiate this command instance.
*/ */
public CLIBrigadierCommand() { public CLIBrigadierCommand() {
LiteralCommandNode<CLICommandSender> commandNode = buildCommand().build(); LiteralCommandNode<CLICommandSender> commandNode = buildCommand().build();

View File

@ -27,7 +27,7 @@ public class CLIBrigadierDispatcher extends BrigadierDispatcher<CLICommandSender
/** /**
* Executes the provided command as the console. * Executes the provided command as the console.
* @param commandWithoutSlash the command, without the eventual slash at the begining. * @param commandWithoutSlash the command, without the eventual slash at the beginning.
* @return the value returned by the executed command. * @return the value returned by the executed command.
*/ */
public int execute(String commandWithoutSlash) { public int execute(String commandWithoutSlash) {

View File

@ -4,6 +4,7 @@ import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.audience.MessageType; import net.kyori.adventure.audience.MessageType;
import net.kyori.adventure.identity.Identity; import net.kyori.adventure.identity.Identity;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import org.jetbrains.annotations.NotNull;
/** /**
* A command sender. * A command sender.
@ -41,5 +42,5 @@ public interface CLICommandSender extends Audience {
void sendMessage(String message); void sendMessage(String message);
@Override // force implementation of super-interface default method @Override // force implementation of super-interface default method
void sendMessage(Identity source, Component message, MessageType type); void sendMessage(@NotNull Identity source, @NotNull Component message, @NotNull MessageType type);
} }

View File

@ -5,6 +5,7 @@ import fr.pandacube.lib.util.Log;
import net.kyori.adventure.audience.MessageType; import net.kyori.adventure.audience.MessageType;
import net.kyori.adventure.identity.Identity; import net.kyori.adventure.identity.Identity;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import org.jetbrains.annotations.NotNull;
/** /**
* The console command sender. * The console command sender.
@ -31,7 +32,7 @@ public class CLIConsoleCommandSender implements CLICommandSender {
} }
@Override @Override
public void sendMessage(Identity source, Component message, MessageType type) { public void sendMessage(@NotNull Identity source, @NotNull Component message, @NotNull MessageType type) {
sendMessage(Chat.chatComponent(message).getLegacyText()); sendMessage(Chat.chatComponent(message).getLegacyText());
} }
} }

View File

@ -170,13 +170,13 @@ public class CommandAdmin extends CLIBrigadierCommand {
} }
ChatTreeNode dispTree = new ChatTreeNode(d); ChatTreeNode displayTree = new ChatTreeNode(d);
for (DisplayCommandNode child : displayNode.children) { for (DisplayCommandNode child : displayNode.children) {
dispTree.addChild(buildDisplayTree(child, sender)); displayTree.addChild(buildDisplayTree(child, sender));
} }
return dispTree; return displayTree;
} }
@ -257,8 +257,8 @@ public class CommandAdmin extends CLIBrigadierCommand {
private static class DisplayCommandNode { private static class DisplayCommandNode {
List<CommandNode<CLICommandSender>> nodes = new ArrayList<>(); final List<CommandNode<CLICommandSender>> nodes = new ArrayList<>();
List<DisplayCommandNode> children = new ArrayList<>(); final List<DisplayCommandNode> children = new ArrayList<>();
void addInline(CommandNode<CLICommandSender> node) { void addInline(CommandNode<CLICommandSender> node) {
nodes.add(node); nodes.add(node);

View File

@ -25,7 +25,7 @@ public class CLILogger {
/** /**
* Initialize and return the logger for this application. * Initialize and return the logger for this application.
* @param cli the CLI instance to use * @param cli the CLI instance to use
* @return the logger of this application. * @return the logger for this application.
*/ */
public static synchronized Logger getLogger(CLI cli) { public static synchronized Logger getLogger(CLI cli) {
if (logger == null) { if (logger == null) {

View File

@ -29,7 +29,7 @@ public abstract class BrigadierCommand<S> {
* Returns a builder for this command. * Returns a builder for this command.
* Concrete class should include any element in the builder that is needed to build the command (sub-commands and * Concrete class should include any element in the builder that is needed to build the command (sub-commands and
* arguments, requirements, redirection, ...). * arguments, requirements, redirection, ...).
* If any of the sub-commands and arguments needs to know the {@link LiteralCommandNode} builded from the returned * If any of the sub-commands and arguments needs to know the {@link LiteralCommandNode} built from the returned
* {@link LiteralArgumentBuilder}, this can be done by overriding {@link #postBuildCommand(LiteralCommandNode)}. * {@link LiteralArgumentBuilder}, this can be done by overriding {@link #postBuildCommand(LiteralCommandNode)}.
* @return a builder for this command. * @return a builder for this command.
*/ */
@ -37,16 +37,16 @@ public abstract class BrigadierCommand<S> {
/** /**
* Method to override if the reference to the command node has to be known when building the subcommands. * Method to override if the reference to the command node has to be known when building the subcommands.
* @param commandNode the command node builded from {@link #buildCommand()}. * @param commandNode the command node built from {@link #buildCommand()}.
*/ */
protected void postBuildCommand(LiteralCommandNode<S> commandNode) { protected void postBuildCommand(LiteralCommandNode<S> commandNode) {
// default implementation does nothing. // default implementation does nothing.
} }
/** /**
* Method to override if this command have any aliases. * Method to override if this command has any aliases.
* @return an array of string corresponding to the aliases. This must not include the orignal command name (that * @return an array of string corresponding to the aliases. This must not include the orignal command name (that
* is the name of the literal command node builded from {@link #buildCommand()}). * is the name of the literal command node built from {@link #buildCommand()}).
*/ */
protected String[] getAliases() { protected String[] getAliases() {
return new String[0]; return new String[0];

View File

@ -13,7 +13,7 @@ import java.util.concurrent.CompletableFuture;
/** /**
* Abstract class that holds a Brigadier {@link CommandDispatcher} instance. * Abstract class that holds a Brigadier {@link CommandDispatcher} instance.
* Subclasses contains logic to integrate this commands dispatcher into their environment (like Bungee or CLI app). * Subclasses contain logic to integrate this commands dispatcher into their environment (like Bungee or CLI app).
* @param <S> the command source (or command sender) type. * @param <S> the command source (or command sender) type.
*/ */
public abstract class BrigadierDispatcher<S> { public abstract class BrigadierDispatcher<S> {
@ -43,7 +43,7 @@ public abstract class BrigadierDispatcher<S> {
/** /**
* Executes the provided command as the provided sender. * Executes the provided command as the provided sender.
* @param sender the command sender. * @param sender the command sender.
* @param commandWithoutSlash the command, without the eventual slash at the begining. * @param commandWithoutSlash the command, without the eventual slash at the beginning.
* @return the value returned by the executed command. * @return the value returned by the executed command.
*/ */
public int execute(S sender, String commandWithoutSlash) { public int execute(S sender, String commandWithoutSlash) {

View File

@ -18,7 +18,7 @@ import java.util.List;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
/** /**
* Utility methods to replace some functionalities of Brigadier, especialy suggestion sorting that we dont like. * Utility methods to replace some functionalities of Brigadier, especially suggestion sorting that we dont like.
*/ */
public class BrigadierSuggestionsUtil { public class BrigadierSuggestionsUtil {

View File

@ -14,7 +14,7 @@ import java.util.stream.LongStream;
import java.util.stream.Stream; import java.util.stream.Stream;
/** /**
* Functionnal interface providing suggestions for an argument of a command. * Functional interface providing suggestions for an argument of a command.
* @param <S> the type of the command sender. * @param <S> the type of the command sender.
*/ */
@FunctionalInterface @FunctionalInterface
@ -66,7 +66,7 @@ public interface SuggestionsSupplier<S> {
* Filter the provided {@link Stream} of string according to the provided token, using the filter returned by {@link #filter(String)}, * Filter the provided {@link Stream} of string according to the provided token, using the filter returned by {@link #filter(String)},
* then returns the strings collected into a {@link List}. * then returns the strings collected into a {@link List}.
* <p> * <p>
* This methods consume the provided stream, so will not be usable anymore. * This method consume the provided stream, so will not be usable anymore.
* @param stream the stream to filter and collet. * @param stream the stream to filter and collet.
* @param token the token to consider for filtering. * @param token the token to consider for filtering.
* @return the stream, filtered and collected into a {@link List}. * @return the stream, filtered and collected into a {@link List}.
@ -505,7 +505,7 @@ public interface SuggestionsSupplier<S> {
/** /**
* Creates a new {@link SuggestionsSupplier} containing all the suggestions of this instance, * Creates a new {@link SuggestionsSupplier} containing all the suggestions of this instance,
* but if this list is still empty, returns the suggestions from the provided one. * but if this list is still empty, returns the suggestions from the provided one.
* @param other another {@link SuggestionsSupplier} to fallback to. * @param other another {@link SuggestionsSupplier} to fall back to.
* @return a new {@link SuggestionsSupplier}. * @return a new {@link SuggestionsSupplier}.
*/ */
default SuggestionsSupplier<S> orIfEmpty(SuggestionsSupplier<S> other) { default SuggestionsSupplier<S> orIfEmpty(SuggestionsSupplier<S> other) {

View File

@ -18,7 +18,7 @@ import static fr.pandacube.lib.chat.ChatStatic.text;
/** /**
* Cleanup a backup directory (i.e. removes old backup archives). * Cleanup a backup directory (i.e. removes old backup archives).
* It is possible to combine differents instances to affect which archive to keep or delete. * It is possible to combine different instances to affect which archive to keep or delete.
*/ */
public abstract class BackupCleaner implements UnaryOperator<TreeSet<LocalDateTime>> { public abstract class BackupCleaner implements UnaryOperator<TreeSet<LocalDateTime>> {
@ -48,7 +48,7 @@ public abstract class BackupCleaner implements UnaryOperator<TreeSet<LocalDateTi
* formula <code><i>YEAR</i> * (12 / <i>n</i>) + <i>MONTH</i> / <i>n</i></code>. It then keeps the first archive * formula <code><i>YEAR</i> * (12 / <i>n</i>) + <i>MONTH</i> / <i>n</i></code>. It then keeps the first archive
* found in each section. * found in each section.
* *
* @param n the interval in month between each kept archives. Must be a dividor of 12 (1, 2, 3, 4, 6 or 12). * @param n the interval in month between each kept archives. Must be a divider of 12 (1, 2, 3, 4, 6 or 12).
* @return a {@link BackupCleaner} that keeps one archive every n month. * @return a {@link BackupCleaner} that keeps one archive every n month.
*/ */
public static BackupCleaner KEEPING_1_EVERY_N_MONTH(int n) { public static BackupCleaner KEEPING_1_EVERY_N_MONTH(int n) {
@ -94,11 +94,13 @@ public abstract class BackupCleaner implements UnaryOperator<TreeSet<LocalDateTi
/** /**
* Performs the cleanup operation on the provided directory. * Performs the cleanup operation on the provided directory.
* @param archiveDir the backup directory to cleanup. * @param archiveDir the backup directory to clean up.
* @param compressDisplayName the displayname of the backup process that manages the backup directory. Used for logs. * @param compressDisplayName the display name of the backup process that manages the backup directory. Used for logs.
*/ */
public void cleanupArchives(File archiveDir, String compressDisplayName) { public void cleanupArchives(File archiveDir, String compressDisplayName) {
String[] files = archiveDir.list(); String[] files = archiveDir.list();
if (files == null)
return;
Log.info("[Backup] Cleaning up backup directory " + ChatColor.GRAY + compressDisplayName + ChatColor.RESET + "..."); Log.info("[Backup] Cleaning up backup directory " + ChatColor.GRAY + compressDisplayName + ChatColor.RESET + "...");

View File

@ -33,7 +33,7 @@ public class BackupManager extends TimerTask {
private final Timer schedulerTimer = new Timer(); private final Timer schedulerTimer = new Timer();
/** /**
* Instanciate a new backup manager. * Instantiate a new backup manager.
* @param backupDirectory the root backup directory. * @param backupDirectory the root backup directory.
*/ */
public BackupManager(File backupDirectory) { public BackupManager(File backupDirectory) {

View File

@ -35,12 +35,12 @@ public abstract class BackupProcess implements Comparable<BackupProcess>, Runnab
private boolean enabled = true; private boolean enabled = true;
private String scheduling = "0 2 * * *"; // cron format, here is everyday at 2am private String scheduling = "0 2 * * *"; // cron format, here is every day at 2am
private BackupCleaner backupCleaner = null; private BackupCleaner backupCleaner = null;
private List<String> ignoreList = new ArrayList<>(); private List<String> ignoreList = new ArrayList<>();
/** /**
* Instanciates a new backup process. * Instantiates a new backup process.
* @param bm the associated backup manager. * @param bm the associated backup manager.
* @param n the process identifier. * @param n the process identifier.
*/ */
@ -66,9 +66,9 @@ public abstract class BackupProcess implements Comparable<BackupProcess>, Runnab
} }
/** /**
* Gets the displayname of this process. * Gets the display name of this process.
* Default implementation returns {@link #getIdentifier()}. * Default implementation returns {@link #getIdentifier()}.
* @return the displayname of this process. * @return the display name of this process.
*/ */
protected String getDisplayName() { protected String getDisplayName() {
return getIdentifier(); return getIdentifier();
@ -105,8 +105,8 @@ public abstract class BackupProcess implements Comparable<BackupProcess>, Runnab
} }
/** /**
* Gets the source directory to backup. * Gets the source directory to back up.
* @return the source directory to backup. * @return the source directory to back up.
*/ */
public abstract File getSourceDir(); public abstract File getSourceDir();
@ -123,7 +123,7 @@ public abstract class BackupProcess implements Comparable<BackupProcess>, Runnab
/** /**
* Called when the backup ends. * Called when the backup ends.
* @param success true if the backup ended successfuly. * @param success true if the backup ended successfully.
*/ */
protected abstract void onBackupEnd(boolean success); protected abstract void onBackupEnd(boolean success);
@ -209,7 +209,7 @@ public abstract class BackupProcess implements Comparable<BackupProcess>, Runnab
File sourceDir = getSourceDir(); File sourceDir = getSourceDir();
if (!sourceDir.exists()) { if (!sourceDir.exists()) {
Log.warning("[Backup] Unable to compress " + ChatColor.GRAY + getDisplayName() + ChatColor.RESET + ": source directory " + sourceDir + " doesnt exist"); Log.warning("[Backup] Unable to compress " + ChatColor.GRAY + getDisplayName() + ChatColor.RESET + ": source directory " + sourceDir + " doesn't exist");
return; return;
} }

View File

@ -26,7 +26,7 @@ public class Persist {
// private final Set<String> dirtyWorldsSave = new HashSet<>(); // private final Set<String> dirtyWorldsSave = new HashSet<>();
/** /**
* Creates a new instance, immediatly loading the data from the file if it exists, or creating an empty one if not. * Creates a new instance, immediately loading the data from the file if it exists, or creating an empty one if not.
* @param bm the associated backup manager. * @param bm the associated backup manager.
*/ */
public Persist(BackupManager bm) { public Persist(BackupManager bm) {

View File

@ -24,7 +24,8 @@ public class RotatedLogsBackupProcess extends BackupProcess {
* @param inNewThread tells if this process should be run in a separate thread (true) or in the same thread handling * @param inNewThread tells if this process should be run in a separate thread (true) or in the same thread handling
* the backup manager (false). * the backup manager (false).
* @param sourceLogDir the directory where the rotated log files are stored, usually {@code ./logs/}. * @param sourceLogDir the directory where the rotated log files are stored, usually {@code ./logs/}.
* @param logFileRegexPattern the pattern to match the rotated log files (usually dated log files, excuding the current log file). * @param logFileRegexPattern the pattern to match the rotated log files (usually dated log files, excluding the
* current log file).
*/ */
public RotatedLogsBackupProcess(BackupManager bm, boolean inNewThread, File sourceLogDir, String logFileRegexPattern) { public RotatedLogsBackupProcess(BackupManager bm, boolean inNewThread, File sourceLogDir, String logFileRegexPattern) {
super(bm, "logs"); super(bm, "logs");

View File

@ -158,8 +158,8 @@ public class ZipCompressor {
} }
private class Entry { private class Entry {
File file; final File file;
String entry; final String entry;
Entry(File f, String e) { Entry(File f, String e) {
file = f; file = f;
entry = e; entry = e;

View File

@ -1,23 +1,22 @@
package fr.pandacube.lib.core.config; package fr.pandacube.lib.core.config;
import fr.pandacube.lib.chat.ChatColorUtil;
import fr.pandacube.lib.util.Log;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.File; import java.io.File;
import java.io.FileReader; import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import fr.pandacube.lib.chat.ChatColorUtil;
import fr.pandacube.lib.util.Log;
/** /**
* Class that loads a specific config file or directory. * Class that loads a specific config file or directory.
*/ */
public abstract class AbstractConfig { public abstract class AbstractConfig {
/** /**
* The {@link File} corresponging to this config file or directory. * The {@link File} corresponding to this config file or directory.
*/ */
protected final File configFile; protected final File configFile;
@ -94,7 +93,8 @@ public abstract class AbstractConfig {
* @return the list of files in the config directory, or null if this config is not a directory. * @return the list of files in the config directory, or null if this config is not a directory.
*/ */
protected List<File> getFileList() { protected List<File> getFileList() {
return configFile.isDirectory() ? Arrays.asList(configFile.listFiles()) : null; File[] arr = configFile.listFiles();
return arr != null ? List.of(arr) : null;
} }
@ -105,7 +105,7 @@ public abstract class AbstractConfig {
* Splits the provided string into a list of permission nodes. * Splits the provided string into a list of permission nodes.
* The permission nodes must be separated by {@code ";"}. * The permission nodes must be separated by {@code ";"}.
* @param perms one or more permissions nodes, separated by {@code ";"}. * @param perms one or more permissions nodes, separated by {@code ";"}.
* @return {@code null} if the parameter is null or is equal to {@code "*"}, or the string splitted using {@code ";"}. * @return {@code null} if the parameter is null or is equal to {@code "*"}, or the string split using {@code ";"}.
*/ */
public static List<String> splitPermissionsString(String perms) { public static List<String> splitPermissionsString(String perms) {
if (perms == null || perms.equals("*")) if (perms == null || perms.equals("*"))
@ -115,9 +115,9 @@ public abstract class AbstractConfig {
/** /**
* Utility method to that translate the {@code '&'} formated string to the legacy format. * Utility method to that translate the {@code '&'} formatted string to the legacy format.
* @param string the string to convert. * @param string the string to convert.
* @return a legacy formated string (using {@code '§'}). * @return a legacy formatted string (using {@code '§'}).
*/ */
public static String getTranslatedColorCode(String string) { public static String getTranslatedColorCode(String string) {
return ChatColorUtil.translateAlternateColorCodes('&', string); return ChatColorUtil.translateAlternateColorCodes('&', string);

View File

@ -5,13 +5,13 @@ import java.io.IOException;
/** /**
* An abstract manager for a set of configuration files and folders. * An abstract manager for a set of configuration files and folders.
* Its uses is to manage the loading/reloading of the configuration of a plugin. * It's uses to manage the loading/reloading of the configuration of a plugin.
*/ */
public abstract class AbstractConfigManager { public abstract class AbstractConfigManager {
/** /**
* The global configuration directory. * The global configuration directory.
* May be the one provided by the environmenet API (like Plugin.getPluginFolder() in Bukkit). * It may be the one provided by the environment API (like Plugin.getPluginFolder() in Bukkit).
*/ */
protected final File configDir; protected final File configDir;

View File

@ -102,7 +102,7 @@ public class CronScheduler {
/** /**
* Cancel a scheduled task. * Cancel a scheduled task.
* Will not stop a current execution of the task. If the task does not exists, it will not do anything. * Will not stop a current execution of the task. If the task does not exist, it will not do anything.
* @param taskId the id of the task to cancel. * @param taskId the id of the task to cancel.
*/ */
public static void unSchedule(String taskId) { public static void unSchedule(String taskId) {

View File

@ -12,34 +12,34 @@ import java.util.List;
import java.util.function.Function; import java.util.function.Function;
/** /**
* Provides pre-instanciated {@link Gson} instances, all with support for Java records and additionnal * Provides pre-instanced {@link Gson} objects, all with support for Java records and additional
* {@link TypeAdapterFactory} provided with {@link #registerTypeAdapterFactory(TypeAdapterFactory)}. * {@link TypeAdapterFactory} provided with {@link #registerTypeAdapterFactory(TypeAdapterFactory)}.
*/ */
public class Json { public class Json {
/** /**
* {@link Gson} instance with {@link GsonBuilder#setLenient()} and support for Java records and additionnal * {@link Gson} instance with {@link GsonBuilder#setLenient()} and support for Java records and additional
* {@link TypeAdapterFactory} provided with {@link #registerTypeAdapterFactory(TypeAdapterFactory)}. * {@link TypeAdapterFactory} provided with {@link #registerTypeAdapterFactory(TypeAdapterFactory)}.
*/ */
public static final Gson gson = build(Function.identity()); public static final Gson gson = build(Function.identity());
/** /**
* {@link Gson} instance with {@link GsonBuilder#setLenient()}, {@link GsonBuilder#setPrettyPrinting()} and support * {@link Gson} instance with {@link GsonBuilder#setLenient()}, {@link GsonBuilder#setPrettyPrinting()} and support
* for Java records and additionnal {@link TypeAdapterFactory} provided with * for Java records and additional {@link TypeAdapterFactory} provided with
* {@link #registerTypeAdapterFactory(TypeAdapterFactory)}. * {@link #registerTypeAdapterFactory(TypeAdapterFactory)}.
*/ */
public static final Gson gsonPrettyPrinting = build(GsonBuilder::setPrettyPrinting); public static final Gson gsonPrettyPrinting = build(GsonBuilder::setPrettyPrinting);
/** /**
* {@link Gson} instance with {@link GsonBuilder#setLenient()}, {@link GsonBuilder#serializeNulls()} and support for * {@link Gson} instance with {@link GsonBuilder#setLenient()}, {@link GsonBuilder#serializeNulls()} and support for
* Java records and additionnal {@link TypeAdapterFactory} provided with * Java records and additional {@link TypeAdapterFactory} provided with
* {@link #registerTypeAdapterFactory(TypeAdapterFactory)}. * {@link #registerTypeAdapterFactory(TypeAdapterFactory)}.
*/ */
public static final Gson gsonSerializeNulls = build(GsonBuilder::serializeNulls); public static final Gson gsonSerializeNulls = build(GsonBuilder::serializeNulls);
/** /**
* {@link Gson} instance with {@link GsonBuilder#setLenient()}, {@link GsonBuilder#serializeNulls()}, * {@link Gson} instance with {@link GsonBuilder#setLenient()}, {@link GsonBuilder#serializeNulls()},
* {@link GsonBuilder#setPrettyPrinting()} and support for Java records and additionnal {@link TypeAdapterFactory} * {@link GsonBuilder#setPrettyPrinting()} and support for Java records and additional {@link TypeAdapterFactory}
* provided with {@link #registerTypeAdapterFactory(TypeAdapterFactory)}. * provided with {@link #registerTypeAdapterFactory(TypeAdapterFactory)}.
*/ */
public static final Gson gsonSerializeNullsPrettyPrinting = build(b -> b.serializeNulls().setPrettyPrinting()); public static final Gson gsonSerializeNullsPrettyPrinting = build(b -> b.serializeNulls().setPrettyPrinting());

View File

@ -43,7 +43,7 @@ public class ThrowableAdapter implements JsonSerializer<Throwable>, JsonDeserial
// handle types // handle types
Throwable t = null; Throwable t = null;
if (obj.has("types") && obj.get("types").isJsonArray()) { if (obj.has("types") && obj.get("types").isJsonArray()) {
t = instanciate(obj.getAsJsonArray("types"), message, cause); t = instantiate(obj.getAsJsonArray("types"), message, cause);
} }
if (t == null) { if (t == null) {
t = new Throwable(message, cause); t = new Throwable(message, cause);
@ -53,8 +53,8 @@ public class ThrowableAdapter implements JsonSerializer<Throwable>, JsonDeserial
JsonArray suppressed = obj.has("suppressed") && !obj.get("suppressed").isJsonNull() JsonArray suppressed = obj.has("suppressed") && !obj.get("suppressed").isJsonNull()
? obj.get("suppressed").getAsJsonArray() : null; ? obj.get("suppressed").getAsJsonArray() : null;
if (suppressed != null) { if (suppressed != null) {
for (JsonElement jsonel : suppressed) { for (JsonElement jsonEl : suppressed) {
t.addSuppressed(context.deserialize(jsonel, Throwable.class)); t.addSuppressed(context.deserialize(jsonEl, Throwable.class));
} }
} }
@ -63,8 +63,8 @@ public class ThrowableAdapter implements JsonSerializer<Throwable>, JsonDeserial
? obj.get("stacktrace").getAsJsonArray() : null; ? obj.get("stacktrace").getAsJsonArray() : null;
if (stacktrace != null) { if (stacktrace != null) {
List<StackTraceElement> els = new ArrayList<>(); List<StackTraceElement> els = new ArrayList<>();
for (JsonElement jsonel : stacktrace) { for (JsonElement jsonEl : stacktrace) {
els.add(context.deserialize(jsonel, StackTraceElement.class)); els.add(context.deserialize(jsonEl, StackTraceElement.class));
} }
t.setStackTrace(els.toArray(new StackTraceElement[0])); t.setStackTrace(els.toArray(new StackTraceElement[0]));
} }
@ -159,7 +159,7 @@ public class ThrowableAdapter implements JsonSerializer<Throwable>, JsonDeserial
} }
private Throwable instanciate(JsonArray types, String message, Throwable cause) { private Throwable instantiate(JsonArray types, String message, Throwable cause) {
Throwable t = null; Throwable t = null;
for (JsonElement clNameEl : types) { for (JsonElement clNameEl : types) {
String clName = clNameEl.getAsString(); String clName = clNameEl.getAsString();
@ -196,7 +196,7 @@ public class ThrowableAdapter implements JsonSerializer<Throwable>, JsonDeserial
} }
/** /**
* Utiliy method to use on {@link Throwable} class that only have a message (no cause) constructor. * Utility method to use on {@link Throwable} class that only have a message (no cause) constructor.
* @param constructorWithMessage function that will construct a new throwable, with prefilled message. * @param constructorWithMessage function that will construct a new throwable, with prefilled message.
* @return a function that will construct a throwable using the provided function, then will try to init the cause of the throwable. * @return a function that will construct a throwable using the provided function, then will try to init the cause of the throwable.
* @param <T> the type of the constructed {@link Throwable}. * @param <T> the type of the constructed {@link Throwable}.

View File

@ -15,8 +15,8 @@ public class TypeConverter {
/** /**
* Converts the provided object to an {@link Integer}. * Converts the provided object to an {@link Integer}.
* @param o the object to convert. * @param o the object to convert.
* @return a the object converted to an {@link Integer}. * @return the object converted to an {@link Integer}.
* @throws ConvertionException is a conversion error occurs. * @throws ConversionException is a conversion error occurs.
*/ */
public static Integer toInteger(Object o) { public static Integer toInteger(Object o) {
if (o == null) { if (o == null) {
@ -27,7 +27,7 @@ public class TypeConverter {
try { try {
return ((JsonElement)o).getAsInt(); return ((JsonElement)o).getAsInt();
} catch(UnsupportedOperationException e) { } catch(UnsupportedOperationException e) {
throw new ConvertionException(e); throw new ConversionException(e);
} }
} }
@ -38,34 +38,34 @@ public class TypeConverter {
try { try {
return Integer.parseInt((String)o); return Integer.parseInt((String)o);
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
throw new ConvertionException(e); throw new ConversionException(e);
} }
} }
if (o instanceof Boolean) { if (o instanceof Boolean) {
return ((Boolean)o) ? 1 : 0; return ((Boolean)o) ? 1 : 0;
} }
throw new ConvertionException("No integer convertion available for an instance of "+o.getClass()); throw new ConversionException("No integer conversion available for an instance of "+o.getClass());
} }
/** /**
* Converts the provided object to a primitive int. * Converts the provided object to a primitive int.
* @param o the object to convert. * @param o the object to convert.
* @return a the object converted to a primitive int. * @return the object converted to a primitive int.
* @throws ConvertionException is a conversion error occurs. * @throws ConversionException is a conversion error occurs.
*/ */
public static int toPrimInt(Object o) { public static int toPrimInt(Object o) {
Integer val = toInteger(o); Integer val = toInteger(o);
if (val == null) if (val == null)
throw new ConvertionException("null values can't be converted to primitive int"); throw new ConversionException("null values can't be converted to primitive int");
return val; return val;
} }
/** /**
* Converts the provided object to a {@link Double}. * Converts the provided object to a {@link Double}.
* @param o the object to convert. * @param o the object to convert.
* @return a the object converted to a {@link Double}. * @return the object converted to a {@link Double}.
* @throws ConvertionException is a conversion error occurs. * @throws ConversionException is a conversion error occurs.
*/ */
public static Double toDouble(Object o) { public static Double toDouble(Object o) {
if (o == null) { if (o == null) {
@ -76,7 +76,7 @@ public class TypeConverter {
try { try {
return ((JsonElement)o).getAsDouble(); return ((JsonElement)o).getAsDouble();
} catch(UnsupportedOperationException e) { } catch(UnsupportedOperationException e) {
throw new ConvertionException(e); throw new ConversionException(e);
} }
} }
@ -87,35 +87,35 @@ public class TypeConverter {
try { try {
return Double.parseDouble((String)o); return Double.parseDouble((String)o);
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
throw new ConvertionException(e); throw new ConversionException(e);
} }
} }
if (o instanceof Boolean) { if (o instanceof Boolean) {
return ((Boolean)o) ? 1d : 0d; return ((Boolean)o) ? 1d : 0d;
} }
throw new ConvertionException("No double convertion available for an instance of "+o.getClass()); throw new ConversionException("No double conversion available for an instance of "+o.getClass());
} }
/** /**
* Converts the provided object to a primitive double. * Converts the provided object to a primitive double.
* @param o the object to convert. * @param o the object to convert.
* @return a the object converted to a primitive double. * @return the object converted to a primitive double.
* @throws ConvertionException is a conversion error occurs. * @throws ConversionException is a conversion error occurs.
*/ */
public static double toPrimDouble(Object o) { public static double toPrimDouble(Object o) {
Double val = toDouble(o); Double val = toDouble(o);
if (val == null) if (val == null)
throw new ConvertionException("null values can't converted to primitive int"); throw new ConversionException("null values can't converted to primitive int");
return val; return val;
} }
/** /**
* Converts the provided object to a {@link String}. * Converts the provided object to a {@link String}.
* @param o the object to convert. * @param o the object to convert.
* @return a the object converted to a {@link String}. * @return the object converted to a {@link String}.
* @throws ConvertionException is a conversion error occurs. * @throws ConversionException is a conversion error occurs.
*/ */
public static String toString(Object o) { public static String toString(Object o) {
if (o == null) { if (o == null) {
@ -126,7 +126,7 @@ public class TypeConverter {
try { try {
return ((JsonElement)o).getAsString(); return ((JsonElement)o).getAsString();
} catch(UnsupportedOperationException e) { } catch(UnsupportedOperationException e) {
throw new ConvertionException(e); throw new ConversionException(e);
} }
} }
@ -134,7 +134,7 @@ public class TypeConverter {
return o.toString(); return o.toString();
} }
throw new ConvertionException("No string convertion available for an instance of "+o.getClass()); throw new ConversionException("No string conversion available for an instance of "+o.getClass());
} }
@ -144,8 +144,8 @@ public class TypeConverter {
* @param mapIntKeys if the String key representing an int should be duplicated as integer type, * @param mapIntKeys if the String key representing an int should be duplicated as integer type,
* which map to the same value as the original String key. For example, if a key is "12" and map * which map to the same value as the original String key. For example, if a key is "12" and map
* to the object <i>o</i>, an integer key 12 will be added and map to the same object <i>o</i>. * to the object <i>o</i>, an integer key 12 will be added and map to the same object <i>o</i>.
* @return a the object converted to a {@link Map}. * @return the object converted to a {@link Map}.
* @throws ConvertionException is a conversion error occurs. * @throws ConversionException is a conversion error occurs.
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static Map<Object, Object> toMap(Object o, boolean mapIntKeys) { public static Map<Object, Object> toMap(Object o, boolean mapIntKeys) {
@ -186,15 +186,15 @@ public class TypeConverter {
return map; return map;
} }
throw new ConvertionException("No Map convertion available for an instance of "+o.getClass()); throw new ConversionException("No Map conversion available for an instance of "+o.getClass());
} }
/** /**
* Converts the provided object to a {@link List}. * Converts the provided object to a {@link List}.
* @param o the object to convert. * @param o the object to convert.
* @return a the object converted to a {@link List}. * @return the object converted to a {@link List}.
* @throws ConvertionException is a conversion error occurs. * @throws ConversionException is a conversion error occurs.
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static List<Object> toList(Object o) { public static List<Object> toList(Object o) {
@ -217,7 +217,7 @@ public class TypeConverter {
} }
throw new ConvertionException("No Map convertion available for an instance of "+o.getClass()); throw new ConversionException("No Map conversion available for an instance of "+o.getClass());
@ -225,14 +225,14 @@ public class TypeConverter {
/** /**
* Thrown when a convertion error occurs. * Thrown when a conversion error occurs.
*/ */
public static class ConvertionException extends RuntimeException { public static class ConversionException extends RuntimeException {
private ConvertionException(String m) { private ConversionException(String m) {
super(m); super(m);
} }
private ConvertionException(Throwable t) { private ConversionException(Throwable t) {
super(t); super(t);
} }

View File

@ -1,8 +1,6 @@
package fr.pandacube.lib.core.mc_version; package fr.pandacube.lib.core.mc_version;
import java.io.InputStreamReader;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.TreeMap; import java.util.TreeMap;

View File

@ -16,7 +16,7 @@ public class MinecraftVersionUtil {
/** /**
* Compare two Minecraft version strings. It uses the rules of semantic * Compare two Minecraft version strings. It uses the rules of semantic
* versionning to compare the versions. * versioning to compare the versions.
* @param v1 the first version to compare. * @param v1 the first version to compare.
* @param v2 the second version to compare. * @param v2 the second version to compare.
* @return 0 if they are equal, &lt;0 if v1&lt;v2 and vice-versa. * @return 0 if they are equal, &lt;0 if v1&lt;v2 and vice-versa.
@ -49,20 +49,20 @@ public class MinecraftVersionUtil {
} }
/** /**
* Tells if the two provided Minecraft versions are consecutives. * Tells if the two provided Minecraft versions are consecutive.
* <p> * <p>
* Two versions are consecutives if (considering {@code 1.X[.Y]}): * Two versions are consecutive if (considering {@code 1.X[.Y]}):
* <ul> * <ul>
* <li>They are part of the same main version (X value)</li> * <li>They are part of the same main version (X value)</li>
* <li>v1 has no Y value, and v2 has Y = 1 (eg. 1.19 and 1.19.1) OR * <li>v1 has no Y value, and v2 has Y = 1 (eg. 1.19 and 1.19.1) OR
* both v1 and v2 has a Y value and those values are consecutives. * both v1 and v2 has a Y value and those values are consecutive.
* </li> * </li>
* </ul> * </ul>
* @param v1 the first version. * @param v1 the first version.
* @param v2 the second version. * @param v2 the second version.
* @return thue if the second version is consecutive to the first one. * @return thue if the second version is consecutive to the first one.
*/ */
public static boolean areConsecutives(String v1, String v2) { public static boolean areConsecutive(String v1, String v2) {
int[] v1Int = decomposedVersion(v1); int[] v1Int = decomposedVersion(v1);
int[] v2Int = decomposedVersion(v2); int[] v2Int = decomposedVersion(v2);
@ -105,21 +105,21 @@ public class MinecraftVersionUtil {
versions = new ArrayList<>(toOrderedSet(versions)); versions = new ArrayList<>(toOrderedSet(versions));
List<String> keptVersions = new ArrayList<>(versions.size()); List<String> keptVersions = new ArrayList<>(versions.size());
for (int i = 0, firstConsec = 0; i < versions.size(); i++) { for (int i = 0, firstConsecutive = 0; i < versions.size(); i++) {
if (i == versions.size() - 1 || !areConsecutives(versions.get(i), versions.get(i + 1))) { if (i == versions.size() - 1 || !areConsecutive(versions.get(i), versions.get(i + 1))) {
if (firstConsec == i) { if (firstConsecutive == i) {
keptVersions.add(versions.get(i)); keptVersions.add(versions.get(i));
firstConsec++; firstConsecutive++;
} }
else { else {
// merge // merge
if (i - firstConsec > 1) if (i - firstConsecutive > 1)
keptVersions.add(versions.get(firstConsec) + "-" + versions.get(i)); keptVersions.add(versions.get(firstConsecutive) + "-" + versions.get(i));
else { else {
keptVersions.add(versions.get(firstConsec)); keptVersions.add(versions.get(firstConsecutive));
keptVersions.add(versions.get(i)); keptVersions.add(versions.get(i));
} }
firstConsec = i + 1; firstConsecutive = i + 1;
} }
} }
} }

View File

@ -23,8 +23,8 @@ import java.util.concurrent.atomic.AtomicReference;
* The data if fetch updated data from an external API on startup. If it fails, * The data if fetch updated data from an external API on startup. If it fails,
* it uses the data stored in the current package at build time. * it uses the data stored in the current package at build time.
* <p> * <p>
* The public static methos are used to fetch an instance of {@link ProtocolVersion} * The public static methods are used to fetch an instance of {@link ProtocolVersion}
* based on the provided protocol version (eg. 763) or Minecraft version (eg. "1.20.1"). * based on the provided protocol version (e.g. 763) or Minecraft version (e.g. "1.20.1").
* An instance of this class provides information related to a protocol version * An instance of this class provides information related to a protocol version
* (the protocol version number and all the corresponding Minecraft versions). * (the protocol version number and all the corresponding Minecraft versions).
*/ */
@ -89,15 +89,24 @@ public class ProtocolVersion implements Comparable<ProtocolVersion> {
Log.warning("Unable to get minecraft version data from API. Using local data instead."); Log.warning("Unable to get minecraft version data from API. Using local data instead.");
// try local source // try local source
try (InputStream is = ProtocolVersion.class.getResourceAsStream("mcversion.json"); try (InputStream is = ProtocolVersion.class.getResourceAsStream("mcversion.json")) {
InputStreamReader isr = new InputStreamReader(is)) { if (is != null) {
try (InputStreamReader isr = new InputStreamReader(is)) {
MinecraftVersionList data = Json.gson.fromJson(isr, MinecraftVersionList.class); MinecraftVersionList data = Json.gson.fromJson(isr, MinecraftVersionList.class);
versionList.set(data); versionList.set(data);
}
}
} catch (Exception e) { } catch (Exception e) {
Log.severe("Unable to get Minecraft versions data from classpath. Using empty data instead."); Log.warning(e);
versionList.set(new MinecraftVersionList());
} }
if (versionList.get() != null) {
return;
}
Log.severe("Unable to get Minecraft versions data from classpath. Using empty data instead.");
versionList.set(new MinecraftVersionList());
} }

View File

@ -15,7 +15,7 @@ import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
* Utility class to manage searching among a set of {@link SearchResult} instances, using case insensitive keywords. * Utility class to manage searching among a set of {@link SearchResult} instances, using case-insensitive keywords.
* The search engine is responsible for storing a database of entries ({@link SearchResult}) that can be searched using * The search engine is responsible for storing a database of entries ({@link SearchResult}) that can be searched using
* keywords. This class provides methods to returns a list of results for provided keywords, a list of keyword * keywords. This class provides methods to returns a list of results for provided keywords, a list of keyword
* suggestions based on pre-typed keywords. * suggestions based on pre-typed keywords.

View File

@ -52,10 +52,10 @@ public final class DB {
} }
/** /**
* Initialialize the table represented by the provided class. * Initialize the table represented by the provided class.
* @param elemClass the class representing a table. * @param elemClass the class representing a table.
* @param <E> the type representing the table. * @param <E> the type representing the table.
* @throws DBInitTableException if the table failed to initialized. * @throws DBInitTableException if the table failed to initialize.
*/ */
public static synchronized <E extends SQLElement<E>> void initTable(Class<E> elemClass) throws DBInitTableException { public static synchronized <E extends SQLElement<E>> void initTable(Class<E> elemClass) throws DBInitTableException {
if (connection == null) { if (connection == null) {
@ -111,7 +111,7 @@ public final class DB {
* @param elemClass the class representing a table. * @param elemClass the class representing a table.
* @return a table name. * @return a table name.
* @param <E> the type representing the table. * @param <E> the type representing the table.
* @throws DBInitTableException if the provided table had to be initialized and it failed to do so. * @throws DBInitTableException if the provided table had to be initialized and failed to do so.
*/ */
public static <E extends SQLElement<E>> String getTableName(Class<E> elemClass) throws DBInitTableException { public static <E extends SQLElement<E>> String getTableName(Class<E> elemClass) throws DBInitTableException {
initTable(elemClass); initTable(elemClass);
@ -130,7 +130,7 @@ public final class DB {
* @param elemClass the class representing a table. * @param elemClass the class representing a table.
* @return the {@code id} field of the provided table. * @return the {@code id} field of the provided table.
* @param <E> the type representing the table. * @param <E> the type representing the table.
* @throws DBInitTableException if the provided table had to be initialized and it failed to do so. * @throws DBInitTableException if the provided table had to be initialized and failed to do so.
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static <E extends SQLElement<E>> SQLField<E, Integer> getSQLIdField(Class<E> elemClass) throws DBInitTableException { public static <E extends SQLElement<E>> SQLField<E, Integer> getSQLIdField(Class<E> elemClass) throws DBInitTableException {
@ -226,8 +226,8 @@ public final class DB {
* @throws DBException if an error occurs when interacting with the database. * @throws DBException if an error occurs when interacting with the database.
*/ */
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> elts = getAll(elemClass, where, orderBy, 1, offset); SQLElementList<E> elements = getAll(elemClass, where, orderBy, 1, offset);
return (elts.size() == 0) ? null : elts.get(0); return (elements.size() == 0) ? null : elements.get(0);
} }
/** /**
@ -294,15 +294,15 @@ public final class DB {
* @throws DBException if an error occurs when interacting with the database. * @throws DBException if an error occurs when interacting with the database.
*/ */
public static <E extends SQLElement<E>> SQLElementList<E> getAll(Class<E> elemClass, SQLWhere<E> where, SQLOrderBy<E> orderBy, Integer limit, Integer offset) throws DBException { public static <E extends SQLElement<E>> SQLElementList<E> getAll(Class<E> elemClass, SQLWhere<E> where, SQLOrderBy<E> orderBy, Integer limit, Integer offset) throws DBException {
SQLElementList<E> elmts = new SQLElementList<>(); SQLElementList<E> elements = new SQLElementList<>();
forEach(elemClass, where, orderBy, limit, offset, elmts::add); forEach(elemClass, where, orderBy, limit, offset, elements::add);
return elmts; return elements;
} }
/** /**
* Iterate through all the entries from the provided table. * Iterate through all the entries from the provided table.
* @param elemClass the class representing a table. * @param elemClass the class representing a table.
* @param action the action to perform on each entries. * @param action the action to perform on each entry.
* @param <E> the type representing the table. * @param <E> the type representing the table.
* @throws DBException if an error occurs when interacting with the database. * @throws DBException if an error occurs when interacting with the database.
*/ */
@ -314,7 +314,7 @@ public final class DB {
* Iterate through the entries from the provided table, using the provided {@code WHERE} clause. * Iterate through the entries from the provided table, using the provided {@code WHERE} clause.
* @param elemClass the class representing a table. * @param elemClass the class representing a table.
* @param where the {@code WHERE} clause of the query. * @param where the {@code WHERE} clause of the query.
* @param action the action to perform on each entries. * @param action the action to perform on each entry.
* @param <E> the type representing the table. * @param <E> the type representing the table.
* @throws DBException if an error occurs when interacting with the database. * @throws DBException if an error occurs when interacting with the database.
*/ */
@ -328,7 +328,7 @@ public final class DB {
* @param elemClass the class representing a table. * @param elemClass the class representing a table.
* @param where the {@code WHERE} clause of the query. * @param where the {@code WHERE} clause of the query.
* @param orderBy the {@code ORDER BY} clause of the query. * @param orderBy the {@code ORDER BY} clause of the query.
* @param action the action to perform on each entries. * @param action the action to perform on each entry.
* @param <E> the type representing the table. * @param <E> the type representing the table.
* @throws DBException if an error occurs when interacting with the database. * @throws DBException if an error occurs when interacting with the database.
*/ */
@ -343,7 +343,7 @@ public final class DB {
* @param where the {@code WHERE} clause of the query. * @param where the {@code WHERE} clause of the query.
* @param orderBy the {@code ORDER BY} clause of the query. * @param orderBy the {@code ORDER BY} clause of the query.
* @param limit the {@code LIMIT} clause of the query. * @param limit the {@code LIMIT} clause of the query.
* @param action the action to perform on each entries. * @param action the action to perform on each entry.
* @param <E> the type representing the table. * @param <E> the type representing the table.
* @throws DBException if an error occurs when interacting with the database. * @throws DBException if an error occurs when interacting with the database.
*/ */
@ -359,7 +359,7 @@ public final class DB {
* @param orderBy the {@code ORDER BY} clause of the query. * @param orderBy the {@code ORDER BY} clause of the query.
* @param limit the {@code LIMIT} clause of the query. * @param limit the {@code LIMIT} clause of the query.
* @param offset the {@code OFFSET} clause of the query. * @param offset the {@code OFFSET} clause of the query.
* @param action the action to perform on each entries. * @param action the action to perform on each entry.
* @param <E> the type representing the table. * @param <E> the type representing the table.
* @throws DBException if an error occurs when interacting with the database. * @throws DBException if an error occurs when interacting with the database.
*/ */
@ -577,7 +577,7 @@ public final class DB {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private static <E extends SQLElement<E>> E getElementInstance(ResultSet set, Class<E> elemClass) throws DBException { private static <E extends SQLElement<E>> E getElementInstance(ResultSet set, Class<E> elemClass) throws DBException {
try { try {
E instance = Reflect.ofClass(elemClass).constructor(int.class).instanciate(set.getInt("id")); E instance = Reflect.ofClass(elemClass).constructor(int.class).instantiate(set.getInt("id"));
int fieldCount = set.getMetaData().getColumnCount(); int fieldCount = set.getMetaData().getColumnCount();
@ -623,7 +623,7 @@ public final class DB {
return instance; return instance;
} catch (ReflectiveOperationException | IllegalArgumentException | SecurityException | SQLException e) { } catch (ReflectiveOperationException | IllegalArgumentException | SecurityException | SQLException e) {
throw new DBException("Can't instanciate " + elemClass.getName(), e); throw new DBException("Can't instantiate " + elemClass.getName(), e);
} }
} }

View File

@ -1,7 +1,7 @@
package fr.pandacube.lib.db; package fr.pandacube.lib.db;
/** /**
* Exception thrown when something bad happends when using the {@link DB} API. * Exception thrown when something bad happens when using the {@link DB} API.
*/ */
public class DBException extends Exception { public class DBException extends Exception {

View File

@ -1,7 +1,7 @@
package fr.pandacube.lib.db; package fr.pandacube.lib.db;
/** /**
* Exception thrown when something bad happends when initializing a new table using {@link DB#initTable(Class)}. * Exception thrown when something bad happens when initializing a new table using {@link DB#initTable(Class)}.
*/ */
public class DBInitTableException extends DBException { public class DBInitTableException extends DBException {

View File

@ -119,7 +119,7 @@ public abstract class SQLElement<E extends SQLElement<E>> {
/** /**
* Gets the name of the table in the database, without the prefix defined by {@link DB#init(DBConnection, String)}. * Gets the name of the table in the database, without the prefix defined by {@link DB#init(DBConnection, String)}.
* @return The unprefixed name of the table in the database. * @return The non-prefixed name of the table in the database.
*/ */
protected abstract String tableName(); protected abstract String tableName();
@ -133,7 +133,7 @@ public abstract class SQLElement<E extends SQLElement<E>> {
} }
/** /**
* Fills the values of this entry that are known to be nullable or have a default value. * Fills the entries values that are known to be nullable or have a default value.
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private void initDefaultValues() { private void initDefaultValues() {
@ -193,7 +193,7 @@ public abstract class SQLElement<E extends SQLElement<E>> {
/** /**
* Sets a value in this entry. * Sets a value in this entry.
* <p> * <p>
* This is not good practice to set the {@code id} field of any entry, because its an unique auto-incremented * This is not good practice to set the {@code id} field of any entry, because its a unique auto-incremented
* value. Use {@link #save()} and {@link #delete()} to set or unset the {@code id} instead, in consistence with the * value. Use {@link #save()} and {@link #delete()} to set or unset the {@code id} instead, in consistence with the
* database. * database.
* @param field the field to set. * @param field the field to set.
@ -255,11 +255,11 @@ public abstract class SQLElement<E extends SQLElement<E>> {
} }
/** /**
* Gets the foreign table entry targeted by the provided foreignkey of this table. * Gets the foreign table entry targeted by the provided foreign key of this table.
* @param field a foreignkey of this table. * @param field a foreign key of this table.
* @param <T> the type of the foreignkey field. * @param <T> the type of the foreign key field.
* @param <P> the targeted foreign table type. * @param <P> the targeted foreign table type.
* @return the foreign table entry targeted by the provided foreignkey of this table. * @return the foreign table entry targeted by the provided foreign key of this table.
* @throws DBException if an error occurs when interacting with the database. * @throws DBException if an error occurs when interacting with the database.
*/ */
public <T, P extends SQLElement<P>> P getReferencedEntry(SQLFKField<E, T, P> field) throws DBException { public <T, P extends SQLElement<P>> P getReferencedEntry(SQLFKField<E, T, P> field) throws DBException {
@ -271,11 +271,11 @@ public abstract class SQLElement<E extends SQLElement<E>> {
/** /**
* Gets the original table entry which the provided foreign key is targeting this entry, and following the provided * Gets the original table entry which the provided foreign key is targeting this entry, and following the provided
* {@code ORDER BY}, {@code LIMIT} and {@code OFFSET} clauses. * {@code ORDER BY}, {@code LIMIT} and {@code OFFSET} clauses.
* @param field a foreignkey in the original table. * @param field a foreign key in the original table.
* @param orderBy the {@code ORDER BY} clause of the query. * @param orderBy the {@code ORDER BY} clause of the query.
* @param limit the {@code LIMIT} clause of the query. * @param limit the {@code LIMIT} clause of the query.
* @param offset the {@code OFFSET} clause of the query. * @param offset the {@code OFFSET} clause of the query.
* @param <T> the type of the foreignkey field. * @param <T> the type of the foreign key field.
* @param <F> the table class of the foreign key that reference a field of this entry. * @param <F> the table class of the foreign key that reference a field of this entry.
* @return the original table entry which the provided foreign key is targeting this entry. * @return the original table entry which the provided foreign key is targeting this entry.
* @throws DBException if an error occurs when interacting with the database. * @throws DBException if an error occurs when interacting with the database.
@ -314,7 +314,7 @@ public abstract class SQLElement<E extends SQLElement<E>> {
/** /**
* Saves this entry into the database, either by updating the already existing entry in it, or by creating a new * Saves this entry into the database, either by updating the already existing entry in it, or by creating a new
* entry if it doesnt exist yet. * entry if it doesn't exist yet.
* @return this. * @return this.
* @throws DBException if an error occurs when interacting with the database. * @throws DBException if an error occurs when interacting with the database.
*/ */
@ -474,14 +474,14 @@ public abstract class SQLElement<E extends SQLElement<E>> {
* Creates a new SQL field. * Creates a new SQL field.
* @param type the type of the field. * @param type the type of the field.
* @param nullable true if nullable, false if {@code NOT NULL}. * @param nullable true if nullable, false if {@code NOT NULL}.
* @param autoIncr if {@code AUTO_INCREMENT}. * @param autoIncrement if {@code AUTO_INCREMENT}.
* @param deflt a default value for this field. A null value indicate that this has no default value. * @param deflt a default value for this field. A null value indicate that this has no default value.
* @return the new SQL field. * @return the new SQL field.
* @param <E> the table type. * @param <E> the table type.
* @param <T> the Java type of this field. * @param <T> the Java type of this field.
*/ */
protected static <E extends SQLElement<E>, T> SQLField<E, T> field(SQLType<T> type, boolean nullable, boolean autoIncr, T deflt) { protected static <E extends SQLElement<E>, T> SQLField<E, T> field(SQLType<T> type, boolean nullable, boolean autoIncrement, T deflt) {
return new SQLField<>(type, nullable, autoIncr, deflt); return new SQLField<>(type, nullable, autoIncrement, deflt);
} }
/** /**
@ -500,13 +500,13 @@ public abstract class SQLElement<E extends SQLElement<E>> {
* Creates a new SQL field. * Creates a new SQL field.
* @param type the type of the field. * @param type the type of the field.
* @param nullable true if nullable, false if {@code NOT NULL}. * @param nullable true if nullable, false if {@code NOT NULL}.
* @param autoIncr if {@code AUTO_INCREMENT}. * @param autoIncrement if {@code AUTO_INCREMENT}.
* @return the new SQL field. * @return the new SQL field.
* @param <E> the table type. * @param <E> the table type.
* @param <T> the Java type of this field. * @param <T> the Java type of this field.
*/ */
protected static <E extends SQLElement<E>, T> SQLField<E, T> field(SQLType<T> type, boolean nullable, boolean autoIncr) { protected static <E extends SQLElement<E>, T> SQLField<E, T> field(SQLType<T> type, boolean nullable, boolean autoIncrement) {
return new SQLField<>(type, nullable, autoIncr); return new SQLField<>(type, nullable, autoIncrement);
} }
/** /**

View File

@ -46,7 +46,7 @@ public class SQLElementList<E extends SQLElement<E>> extends ArrayList<E> {
E emptyElement = elemClass.getConstructor().newInstance(); E emptyElement = elemClass.getConstructor().newInstance();
emptyElement.set(field, value, false); emptyElement.set(field, value, false);
} catch (Exception e) { } catch (Exception e) {
throw new IllegalArgumentException("Illegal field or value or can't instanciante an empty instance of " throw new IllegalArgumentException("Illegal field or value or can't instantiate an empty instance of "
+ elemClass.getName() + ". (the instance is only created to test validity of field and value)", e); + elemClass.getName() + ". (the instance is only created to test validity of field and value)", e);
} }
@ -83,7 +83,7 @@ public class SQLElementList<E extends SQLElement<E>> extends ArrayList<E> {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private void applyNewValuesToElements(List<E> storedEl) { private void applyNewValuesToElements(List<E> storedEl) {
// applique les valeurs dans chaques objets de la liste // applique les valeurs dans chaque objet de la liste
for (E el : storedEl) { for (E el : storedEl) {
for (@SuppressWarnings("rawtypes") SQLField entry : modifiedValues.keySet()) { for (@SuppressWarnings("rawtypes") SQLField entry : modifiedValues.keySet()) {
if (!el.isModified(entry)) { if (!el.isModified(entry)) {
@ -100,7 +100,7 @@ public class SQLElementList<E extends SQLElement<E>> extends ArrayList<E> {
/** /**
* Removes all the entries of this list from the database. * Removes all the entries of this list from the database.
* This method has the same effect as calling the {@link SQLElement#delete()} method individually on each element, * This method has the same effect as calling the {@link SQLElement#delete()} method individually on each element,
* but with only one SQL query to delete all of the entries. * but with only one SQL query to delete all the entries.
* <p> * <p>
* If you intend to remove the entries from the database just after fetching them, call directly the * If you intend to remove the entries from the database just after fetching them, call directly the
* {@link DB#delete(Class, SQLWhere)} method instead. * {@link DB#delete(Class, SQLWhere)} method instead.
@ -124,9 +124,9 @@ public class SQLElementList<E extends SQLElement<E>> extends ArrayList<E> {
/** /**
* Get all the entries targeted by the foreign key of all the entries in this list. * Get all the entries targeted by the foreign key of all the entries in this list.
* @param foreignKey a foreignkey of this table. * @param foreignKey a foreign key of this table.
* @param orderBy the {@code ORDER BY} clause of the query. * @param orderBy the {@code ORDER BY} clause of the query.
* @return a list of foreign table entries targeted by the provided foreignkey of this table. * @return a list of foreign table entries targeted by the provided foreign key of this table.
* @param <T> the fields Java type. * @param <T> the fields Java type.
* @param <P> the target table type. * @param <P> the target table type.
* @throws DBException if an error occurs when interacting with the database. * @throws DBException if an error occurs when interacting with the database.
@ -144,7 +144,7 @@ public class SQLElementList<E extends SQLElement<E>> extends ArrayList<E> {
/** /**
* Get all the entries targeted by the foreign key of all the entries in this list, mapped from the foreign key value. * Get all the entries targeted by the foreign key of all the entries in this list, mapped from the foreign key value.
* @param foreignKey a foreignkey of this table. * @param foreignKey a foreign key of this table.
* @return a map of the foreign key values, mapped to the foreign tables entries. * @return a map of the foreign key values, mapped to the foreign tables entries.
* @param <T> the fields Java type. * @param <T> the fields Java type.
* @param <P> the target table type. * @param <P> the target table type.
@ -163,11 +163,11 @@ public class SQLElementList<E extends SQLElement<E>> extends ArrayList<E> {
/** /**
* Gets all the original tables entries which the provided foreign key is targeting the entries of this list, and * Gets all the original tables entries which the provided foreign key is targeting the entries of this list, and
* following the provided {@code ORDER BY}, {@code LIMIT} and {@code OFFSET} clauses. * following the provided {@code ORDER BY}, {@code LIMIT} and {@code OFFSET} clauses.
* @param foreignKey a foreignkey in the original table. * @param foreignKey a foreign key in the original table.
* @param orderBy the {@code ORDER BY} clause of the query. * @param orderBy the {@code ORDER BY} clause of the query.
* @param limit the {@code LIMIT} clause of the query. * @param limit the {@code LIMIT} clause of the query.
* @param offset the {@code OFFSET} clause of the query. * @param offset the {@code OFFSET} clause of the query.
* @param <T> the type of the foreignkey field. * @param <T> the type of the foreign key field.
* @param <F> the table class of the foreign key that reference a field of this entry. * @param <F> the table class of the foreign key that reference a field of this entry.
* @return the original tables entries which the provided foreign key is targeting the entries of this list. * @return the original tables entries which the provided foreign key is targeting the entries of this list.
* @throws DBException if an error occurs when interacting with the database. * @throws DBException if an error occurs when interacting with the database.
@ -187,11 +187,11 @@ public class SQLElementList<E extends SQLElement<E>> extends ArrayList<E> {
* Gets all the original tables entries which the provided foreign key is targeting the entries of this list, * Gets all the original tables entries which the provided foreign key is targeting the entries of this list,
* following the provided {@code ORDER BY}, {@code LIMIT} and {@code OFFSET} clauses, and mapped from the foreign * following the provided {@code ORDER BY}, {@code LIMIT} and {@code OFFSET} clauses, and mapped from the foreign
* key value. * key value.
* @param foreignKey a foreignkey in the original table. * @param foreignKey a foreign key in the original table.
* @param orderBy the {@code ORDER BY} clause of the query. * @param orderBy the {@code ORDER BY} clause of the query.
* @param limit the {@code LIMIT} clause of the query. * @param limit the {@code LIMIT} clause of the query.
* @param offset the {@code OFFSET} clause of the query. * @param offset the {@code OFFSET} clause of the query.
* @param <T> the type of the foreignkey field. * @param <T> the type of the foreign key field.
* @param <F> the table class of the foreign key that reference a field of this entry. * @param <F> the table class of the foreign key that reference a field of this entry.
* @return a map of the foreign key values, mapped to the orignal tables entries. * @return a map of the foreign key values, mapped to the orignal tables entries.
* @throws DBException if an error occurs when interacting with the database. * @throws DBException if an error occurs when interacting with the database.

View File

@ -28,7 +28,7 @@ public class SQLFKField<F extends SQLElement<F>, T, P extends SQLElement<P>> ext
SQLField<F, Integer> f = DB.getSQLIdField(fkEl); SQLField<F, Integer> f = DB.getSQLIdField(fkEl);
return new SQLFKField<>(f.type, nul, deflt, fkEl, f); return new SQLFKField<>(f.type, nul, deflt, fkEl, f);
} catch (DBInitTableException e) { } catch (DBInitTableException e) {
Log.severe("Can't create Foreign key Field targetting id field of '"+fkEl+"'", e); Log.severe("Can't create Foreign key Field targeting id field of '"+fkEl+"'", e);
return null; return null;
} }
} }
@ -51,7 +51,7 @@ public class SQLFKField<F extends SQLElement<F>, T, P extends SQLElement<P>> ext
} }
if (fkF.getSQLElementType() == null) if (fkF.getSQLElementType() == null)
throw new RuntimeException("Can't initialize foreign key. The primary key in the table " + fkEl.getName() + " is not properly initialized and can't be targetted by a forein key"); throw new RuntimeException("Can't initialize foreign key. The primary key in the table " + fkEl.getName() + " is not properly initialized and can't be targeted by a foreign key");
sqlPrimaryKeyField = fkF; sqlPrimaryKeyField = fkF;
sqlForeignKeyElemClass = fkEl; sqlForeignKeyElemClass = fkEl;
} }

View File

@ -24,10 +24,10 @@ public class SQLField<E extends SQLElement<E>, T> {
/* package */ final boolean autoIncrement; /* package */ final boolean autoIncrement;
/* package */ final T defaultValue; /* package */ final T defaultValue;
/* package */ SQLField(SQLType<T> type, boolean nullable, boolean autoIncr, T deflt) { /* package */ SQLField(SQLType<T> type, boolean nullable, boolean autoIncrement, T deflt) {
this.type = type; this.type = type;
this.nullable = nullable; this.nullable = nullable;
autoIncrement = autoIncr; this.autoIncrement = autoIncrement;
defaultValue = deflt; defaultValue = deflt;
} }
@ -35,8 +35,8 @@ public class SQLField<E extends SQLElement<E>, T> {
this(type, nullable, false, null); this(type, nullable, false, null);
} }
/* package */ SQLField(SQLType<T> type, boolean nullable, boolean autoIncr) { /* package */ SQLField(SQLType<T> type, boolean nullable, boolean autoIncrement) {
this(type, nullable, autoIncr, null); this(type, nullable, autoIncrement, null);
} }
/* package */ SQLField(SQLType<T> type, boolean nullable, T deflt) { /* package */ SQLField(SQLType<T> type, boolean nullable, T deflt) {

View File

@ -1,12 +0,0 @@
# pandalib-net
A TCP network library that uses the standard Java socket API, to ease the ommunication between the different processes
running the server network Pandacube.
Its still in development (actually not touched since years), and its supposed to be a replacement for the old
`pandalib-netapi`. This module is then marked as Beta using the Google Guava annotation.
- Packet based communication
- Supports Request/Answer packets
- Uses binary packet id and data
* Input streams are handled in separate Threads

View File

@ -1,29 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>pandalib-parent</artifactId>
<groupId>fr.pandacube.lib</groupId>
<version>1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>pandalib-net</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>fr.pandacube.lib</groupId>
<artifactId>pandalib-util</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.0.1-jre</version>
</dependency>
</dependencies>
</project>

View File

@ -1,65 +0,0 @@
package fr.pandacube.lib.net;
import java.util.Arrays;
import com.google.common.annotations.Beta;
@Beta
public class Array8Bit {
public static final int BIT_COUNT = Byte.SIZE;
private boolean[] values = new boolean[BIT_COUNT];
public Array8Bit(byte b) {
fromByte(b);
}
/**
* @param bits (index 0 is the lowest significant bit)
*/
public Array8Bit(boolean[] bits) {
if (bits == null || bits.length != BIT_COUNT)
throw new IllegalArgumentException("bits is null or bits.length != "+BIT_COUNT);
values = Arrays.copyOf(bits, BIT_COUNT);
}
/**
* i = 0 is the lowest significant bit
*/
public boolean getBit(int i) {
return values[i];
}
/**
* i = 0 is the lowest significant bit
*/
public void setBit(int i, boolean b) {
values[i] = b;
}
public void fromByte(byte b) {
int mask = 1;
for (int i = 0; i < BIT_COUNT; i++) {
values[i] = (b & mask) != 0;
mask <<= 1;
}
}
public byte toByte() {
byte b = 0;
for (int i=BIT_COUNT-1; i>=0; i--) {
b <<= 1;
if (values[i]) b |= 1;
}
return b;
}
}

View File

@ -1,275 +0,0 @@
package fr.pandacube.lib.net;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import com.google.common.annotations.Beta;
@Beta
public final class ByteBuffer implements Cloneable {
public static final Charset NETWORK_CHARSET = StandardCharsets.UTF_8;
private java.nio.ByteBuffer buff;
public ByteBuffer() {
this(16);
}
public ByteBuffer(int initSize) {
buff = java.nio.ByteBuffer.allocate(initSize);
}
/**
* Create a ByteBuffer that is initially <b>backed</b> by the provided byte array.
* The position of this buffer will be 0.
* If this ByteBuffer needs a biffer array, the provided array is replaced by a new one,
* making the provided array not related to this ByteBuffer anymore.
* @param data array of byte that serve as a backend for this ByteBuffer.
*/
public ByteBuffer(byte[] data) {
buff = java.nio.ByteBuffer.wrap(data);
}
private void askForBufferExtension(int needed) {
while (buff.remaining() < needed) {
java.nio.ByteBuffer newBuff = java.nio.ByteBuffer.wrap(Arrays.copyOf(buff.array(), buff.array().length * 2));
newBuff.position(buff.position());
buff = newBuff;
}
}
/**
* This clone method also clone the underlying array.
*/
@SuppressWarnings("MethodDoesntCallSuperMethod")
@Override
public ByteBuffer clone() {
return new ByteBuffer(Arrays.copyOf(buff.array(), buff.array().length));
}
/**
* @see java.nio.ByteBuffer#get()
*/
public byte getByte() {
return buff.get();
}
/**
* @see java.nio.ByteBuffer#get(byte[])
*/
public byte[] getByteArray(byte[] b) {
buff.get(b);
return b;
}
/**
* Return the next byte array wich is preceded with his size as integer,
* or null if the founded size is negative.
*/
public byte[] getSizedByteArray() {
int size = getInt();
if (size < 0) return null;
return getByteArray(new byte[size]);
}
/**
* @see java.nio.ByteBuffer#getChar()
*/
public char getChar() {
return buff.getChar();
}
/**
* @see java.nio.ByteBuffer#getShort()
*/
public short getShort() {
return buff.getShort();
}
/**
* @see java.nio.ByteBuffer#getInt()
*/
public int getInt() {
return buff.getInt();
}
/**
* @see java.nio.ByteBuffer#getLong()
*/
public long getLong() {
return buff.getLong();
}
/**
* @see java.nio.ByteBuffer#getFloat()
*/
public float getFloat() {
return buff.getFloat();
}
/**
* @see java.nio.ByteBuffer#getDouble()
*/
public double getDouble() {
return buff.getDouble();
}
/**
* @see java.nio.ByteBuffer#put(byte)
*/
public ByteBuffer putByte(byte b) {
askForBufferExtension(Byte.BYTES);
buff.put(b);
return this;
}
/**
* @see java.nio.ByteBuffer#put(byte[])
*/
public ByteBuffer putByteArray(byte[] b) {
askForBufferExtension(b.length * Byte.BYTES);
buff.put(b);
return this;
}
public ByteBuffer putSizedByteArray(byte[] b) {
if (b == null) {
return putInt(-1);
}
putInt(b.length);
return putByteArray(b);
}
/**
* @see java.nio.ByteBuffer#putChar(char)
*/
public ByteBuffer putChar(char value) {
askForBufferExtension(Character.BYTES);
buff.putChar(value);
return this;
}
/**
* @see java.nio.ByteBuffer#putShort(short)
*/
public ByteBuffer putShort(short value) {
askForBufferExtension(Short.BYTES);
buff.putShort(value);
return this;
}
/**
* @see java.nio.ByteBuffer#putInt(int)
*/
public ByteBuffer putInt(int value) {
askForBufferExtension(Integer.BYTES);
buff.putInt(value);
return this;
}
/**
* @see java.nio.ByteBuffer#putLong(long)
*/
public ByteBuffer putLong(long value) {
askForBufferExtension(Long.BYTES);
buff.putLong(value);
return this;
}
/**
* @see java.nio.ByteBuffer#putFloat(float)
*/
public ByteBuffer putFloat(float value) {
askForBufferExtension(Float.BYTES);
buff.putFloat(value);
return this;
}
/**
* @see java.nio.ByteBuffer#putDouble(double)
*/
public ByteBuffer putDouble(double value) {
askForBufferExtension(Double.BYTES);
buff.putDouble(value);
return this;
}
/**
* @see java.nio.ByteBuffer#position()
*/
public int getPosition() {
return buff.position();
}
/**
* @see java.nio.ByteBuffer#position(int)
*/
public void setPosition(int p) {
buff.position(p);
}
/**
* @see java.nio.ByteBuffer#capacity()
*/
public int capacity() {
return buff.capacity();
}
/**
*
* @param s null String are supported
*/
public ByteBuffer putString(String s) {
if (s == null) {
return putInt(-1);
}
return putSizedByteArray(s.getBytes(NETWORK_CHARSET));
}
/**
* returned string can be null
*/
public String getString() {
byte[] binaryString = getSizedByteArray();
return (binaryString == null) ? null : new String(binaryString, NETWORK_CHARSET);
}
/**
*
* @param list The list can be null, and any String can be null too.
*/
public ByteBuffer putListOfString(List<String> list) {
if (list == null) {
return putInt(-1);
}
putInt(list.size());
for (String str : list)
putString(str);
return this;
}
/**
* @return a List of String. The list can be null, and any element can be null too.
*/
public List<String> getListOfString() {
int size = getInt();
if (size < 0)
return null;
List<String> list = new ArrayList<>();
for (int i = 0; i < size; i++)
list.add(getString());
return list;
}
/**
* @see java.nio.ByteBuffer#array()
*/
public byte[] array() {
return buff.array();
}
}

View File

@ -1,60 +0,0 @@
package fr.pandacube.lib.net;
import java.util.Arrays;
import com.google.common.annotations.Beta;
@Beta
public class PPacket {
public final String name;
/* package */ int id;
public final byte[] content;
/**
* Construct a new PPacket based on the content of the provided buffer before his position.
* @param n the name of the packet.
* @param buff the buffer where the data comes from. Only the content before {@link ByteBuffer#getPosition()} is copied.
*/
public PPacket(String n, ByteBuffer buff) {
this(n, Arrays.copyOf(buff.array(), buff.getPosition()));
}
public PPacket(String n, byte[] c) {
name = n;
content = c;
}
/* package */ PPacket(String n, int i, byte[] c) {
this(n, c);
id = i;
}
public ByteBuffer getContentAsBuffer() {
return new ByteBuffer(content);
}
public static PPacket buildSingleStringContentPacket(String name, String content) {
return new PPacket(name, new ByteBuffer().putString(content));
}
/* package */ static PPacket buildLoginPacket(String password) {
return buildSingleStringContentPacket("login", password);
}
/* package */ static PPacket buildBadFormatPacket(String message) {
return buildSingleStringContentPacket("bad_format", message);
}
/* package */ static PPacket buildLoginBadPacket() {
return new PPacket("login_bad", new byte[0]);
}
}

View File

@ -1,47 +0,0 @@
package fr.pandacube.lib.net;
import java.util.Arrays;
import com.google.common.annotations.Beta;
@Beta
public class PPacketAnswer extends PPacket {
/* package */ final int answer;
/**
* Construct a new PPacketAnswer based on the content of the provided buffer before his position.
* @param n the name of the packet.
* @param buff the buffer where the data comes from. Only the content before {@link ByteBuffer#getPosition()} is copied.
*/
public PPacketAnswer(PPacket answered, String n, ByteBuffer buff) {
this(answered, n, Arrays.copyOf(buff.array(), buff.getPosition()));
}
public PPacketAnswer(PPacket answered, String n, byte[] c) {
super(n, c);
answer = answered.id;
}
/* package */ PPacketAnswer(String n, int i, int a, byte[] c) {
super(n, i, c);
answer = a;
}
public static PPacketAnswer buildSingleStringContentPacketAnswer(PPacket answered, String name, String content) {
ByteBuffer pwBuff = new ByteBuffer().putString(content);
return new PPacketAnswer(answered, name, Arrays.copyOf(pwBuff.array(), pwBuff.getPosition()));
}
/* package */ static PPacketAnswer buildLoginOkPacket(PPacket loginPacket) {
return new PPacketAnswer(loginPacket, "login_ok", new byte[0]);
}
/* package */ static PPacketAnswer buildExceptionPacket(PPacket answered, String message) {
return buildSingleStringContentPacketAnswer(answered, "exception", message);
}
}

View File

@ -1,16 +0,0 @@
package fr.pandacube.lib.net;
import com.google.common.annotations.Beta;
@Beta
@FunctionalInterface
public interface PPacketListener<P extends PPacket> {
/**
* Called when we receive a packet (except responses)
* @param connection the connection from where the packet comes
* @param packet the received packet
*/
void onPacketReceive(PSocket connection, P packet);
}

View File

@ -1,157 +0,0 @@
package fr.pandacube.lib.net;
import java.io.Closeable;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import com.google.common.annotations.Beta;
import fr.pandacube.lib.util.Log;
@Beta
public class PServer extends Thread implements Closeable {
private static final AtomicInteger connectionCounterId = new AtomicInteger(0);
private final int port;
private ServerSocket socket;
private final String socketName;
private final List<TCPServerClientConnection> clients = Collections.synchronizedList(new ArrayList<>());
private final AtomicBoolean isClosed = new AtomicBoolean(false);
private final List<PPacketListener<PPacket>> globalPacketListeners = Collections.synchronizedList(new ArrayList<>());
private final List<PSocketConnectionListener> clientConnectionListeners = Collections.synchronizedList(new ArrayList<>());
private final String password;
public PServer(int port, String sckName, String password) {
super("PServer " + sckName);
setDaemon(true);
if (port <= 0 || port > 65535) throw new IllegalArgumentException("le numéro de port est invalide");
socketName = sckName;
this.port = port;
this.password = password;
}
@Override
public void run() {
try {
socket = new ServerSocket();
socket.setReceiveBufferSize(PSocket.NETWORK_TCP_BUFFER_SIZE);
socket.setPerformancePreferences(0, 1, 0);
socket.bind(new InetSocketAddress(port));
while (true) {
Socket socketClient = socket.accept();
socketClient.setSendBufferSize(PSocket.NETWORK_TCP_BUFFER_SIZE);
socketClient.setSoTimeout(PSocket.NETWORK_TIMEOUT);
TCPServerClientConnection co = new TCPServerClientConnection(socketClient,
connectionCounterId.getAndIncrement());
co.start();
}
} catch (SocketException ignored) {
} catch (Exception e) {
Log.warning("Plus aucune connexion ne peux être acceptée", e);
}
}
public void addPacketListener(PPacketListener<PPacket> l) {
globalPacketListeners.add(l);
}
public boolean removePacketListener(PPacketListener<PPacket> l) {
return globalPacketListeners.remove(l);
}
public void addConnectionListener(PSocketConnectionListener l) {
clientConnectionListeners.add(l);
}
public void removeConnectionListener(PSocketConnectionListener l) {
clientConnectionListeners.remove(l);
}
protected class TCPServerClientConnection extends PSocket {
boolean loggedIn;
private TCPServerClientConnection(Socket s, int coId) {
super(s, "Conn#" + coId + " via PServer " + socketName, password);
addConnectionListener(new PSocketConnectionListener() {
@Override
public void onDisconnect(PSocket connection) {
try {
clientConnectionListeners.forEach(l -> l.onDisconnect(connection));
} finally {
clients.remove((TCPServerClientConnection)connection);
}
}
@Override
public void onConnect(PSocket connection) {
clients.add((TCPServerClientConnection)connection);
clientConnectionListeners.forEach(l -> l.onConnect(connection));
}
});
addPacketListener((conn, packet) ->
globalPacketListeners.forEach(l -> {
try {
l.onPacketReceive(conn, packet);
} catch (Exception e) {
Log.severe("Exception while calling PPacketListener.onPacketReceive().", e);
sendSilently(PPacketAnswer.buildExceptionPacket(packet, e.toString()));
}
})
);
}
}
@Override
public void close() {
try {
if (isClosed.get()) return;
isClosed.set(true);
clients.forEach(PSocket::close);
socket.close();
} catch (IOException ignored) {}
}
public boolean isClosed() {
return isClosed.get() || socket.isClosed();
}
public List<PSocket> getClients() {
synchronized (clients) {
return new ArrayList<>(clients);
}
}
@Override
public String toString() {
return this.getClass().getName() + "{thread=" + getName() + ", socket=" + socket + "}";
}
}

View File

@ -1,350 +0,0 @@
package fr.pandacube.lib.net;
import java.io.BufferedOutputStream;
import java.io.Closeable;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
import com.google.common.annotations.Beta;
import fr.pandacube.lib.util.Log;
/**
* A wrapper for a {@link Socket}. The connection must point to a software using {@link PServer}
* as wrapper for the target {@link ServerSocket}.
* <br>
* This class provides a simple way to exchange data between client and server :
* <ul>
* <li>Maintained connection with the server</li>
* <li>Login with a password (send in the first packet)</li>
* <li>Binary packet id</li>
* <li>Binary data</li>
* <li>Input stream in a separate Thread</li>
* </ul>
*
*/
@Beta
public class PSocket extends Thread implements Closeable {
public static final int NETWORK_TCP_BUFFER_SIZE = 1024 * 1024;
public static final int NETWORK_TIMEOUT = 0; // no timeout (milli-seconds)
private boolean server = false;
private Socket socket;
private final SocketAddress addr;
private DataInputStream in;
private DataOutputStream out;
private final Object outSynchronizer = new Object();
private String password;
private final AtomicBoolean isClosed = new AtomicBoolean(false);
private final List<PPacketListener<PPacket>> packetListeners = Collections.synchronizedList(new ArrayList<>());
private final List<PSocketConnectionListener> connectionListeners = Collections.synchronizedList(new ArrayList<>());
private final Map<Integer, PPacketListener<PPacketAnswer>> answersCallbacks = Collections.synchronizedMap(new HashMap<>());
private int nextSendId = 0;
/**
* Create a new PSocket that will connect to the specified SocketAddress.
* @param a The target server to connect to
* @param connName the name of the connection, used to name the Thread used to receive the packet.
* @param pass the password to send to the server.
*/
public PSocket(SocketAddress a, String connName, String pass) {
super("PSocket " + connName);
setDaemon(true);
if (a == null) throw new IllegalArgumentException("les arguments ne peuvent pas être null");
addr = a;
}
/* package */ PSocket(Socket s, String connName, String pass) {
this(s.getRemoteSocketAddress(), connName, pass);
socket = s;
server = true;
}
@Override
public void run() {
try {
if (socket == null) {
socket = new Socket();
socket.setReceiveBufferSize(NETWORK_TCP_BUFFER_SIZE);
socket.setSendBufferSize(NETWORK_TCP_BUFFER_SIZE);
socket.setSoTimeout(10000); // initial timeout before login
socket.connect(addr);
in = new DataInputStream(socket.getInputStream());
out = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
}
// password check
if (server) {
PPacket packet = readPacket();
if (packet == null || packet instanceof PPacketAnswer || !"login".equals(packet.name)) {
send(PPacket.buildLoginBadPacket());
close();
return;
}
try {
String receivedPassword = new ByteBuffer(packet.content).getString();
if (!Objects.equals(receivedPassword, password)) {
send(PPacket.buildLoginBadPacket());
close();
return;
}
} catch(Exception e) {
send(PPacket.buildLoginBadPacket());
close();
return;
}
send(PPacketAnswer.buildLoginOkPacket(packet));
// login ok at this point
}
else {
send(PPacket.buildLoginPacket(password));
PPacket packet = readPacket();
if (packet == null) {
Log.severe("bad packet received from server. Disconnecting.");
close();
return;
}
if (packet.name.equals("login_bad")) {
Log.severe("Wrong password to connect to server. Disconnecting.");
close();
return;
}
if (!packet.name.equals("login_ok")) {
Log.severe("Unexpected packet from server. Disconnecting.");
close();
return;
}
// login ok at this point
}
password = null;
socket.setSoTimeout(NETWORK_TIMEOUT);
Log.info(getName() + " connected.");
connectionListeners.forEach(l -> {
try {
l.onConnect(this);
} catch (Exception e) {
Log.severe("Exception while calling PSocketConnectionListener.onConnect().", e);
}
});
while (!socket.isClosed()) {
PPacket packet = readPacket();
if (packet == null) {
send(PPacket.buildBadFormatPacket("Bad format for the last packet received. Closing connection."));
break;
}
if (packet instanceof PPacketAnswer) {
try {
answersCallbacks.remove(((PPacketAnswer)packet).answer).onPacketReceive(this, (PPacketAnswer)packet);
} catch (Exception e) {
Log.severe("Exception while calling PPacketListener.onPacketReceive().", e);
send(PPacketAnswer.buildExceptionPacket(packet, e.toString()));
}
}
else {
packetListeners.forEach(l -> {
try {
l.onPacketReceive(this, packet);
} catch (Exception e) {
Log.severe("Exception while calling PPacketListener.onPacketReceive().", e);
sendSilently(PPacketAnswer.buildExceptionPacket(packet, e.toString()));
}
});
}
}
} catch (Exception e) {
Log.severe(e);
}
close();
}
/**
* Return the packet read in the socket, or null if the packet is in a bad format.
* @return the packet
*
*/
private PPacket readPacket() throws IOException {
byte nSize = in.readByte();
if (nSize == 0) {
return null;
}
boolean answer = nSize < 0;
if (answer)
nSize *= -1;
byte[] nBytes = new byte[nSize];
in.readFully(nBytes);
String name = new String(nBytes, ByteBuffer.NETWORK_CHARSET);
int packetId = in.readInt();
int answerId = (answer) ? in.readInt() : -1;
int cSize = in.readInt();
if (cSize < 0 || cSize > 0xFFFFFF) { // can't be more that 16 MiB
return null;
}
byte[] content = new byte[cSize];
in.readFully(content);
return answer ? new PPacketAnswer(name, packetId, answerId, content) : new PPacket(name, packetId, content);
}
/**
* Send the provided packet, without waiting for an answer.
*/
public void send(PPacket packet) throws IOException {
if (packet == null)
throw new IllegalArgumentException("packet can't be null");
if (packet.name == null)
throw new IllegalArgumentException("packet.name can't be null");
if (packet.content == null)
throw new IllegalArgumentException("packet.content can't be null");
byte[] nameBytes = packet.name.getBytes(ByteBuffer.NETWORK_CHARSET);
if (nameBytes.length > 127)
throw new IllegalArgumentException("packet.name must take fewer than 128 bytes when converted to UTF-8");
byte nameSize = (byte)nameBytes.length;
boolean answer = packet instanceof PPacketAnswer;
if (answer) nameSize *= -1;
synchronized (outSynchronizer) {
int packetId = nextSendId++;
packet.id = packetId;
out.write(new byte[] {nameSize});
out.write(nameBytes);
out.write(packetId);
if (answer)
out.write(((PPacketAnswer)packet).answer);
out.write(packet.content.length);
out.write(packet.content);
out.flush();
}
}
public void sendSilently(PPacket packet) {
try {
send(packet);
} catch (IOException ignored) {}
}
public void send(PPacket packet, PPacketListener<PPacketAnswer> answerCallback) throws IOException {
synchronized (answersCallbacks) {
/*
* This synch block ensure that the callback will be put in the listeners Map before
* we receve the answer (in case this is really really fast)
*/
send(packet);
answersCallbacks.put(packet.id, answerCallback);
}
}
public void addPacketListener(PPacketListener<PPacket> l) {
packetListeners.add(l);
}
public boolean removePacketListener(PPacketListener<PPacket> l) {
return packetListeners.remove(l);
}
public void addConnectionListener(PSocketConnectionListener l) {
connectionListeners.add(l);
}
public void removeConnectionListener(PSocketConnectionListener l) {
connectionListeners.remove(l);
}
@Override
public void close() {
try {
synchronized (outSynchronizer) {
if (isClosed.get()) return;
Log.info(getName() + " closing...");
connectionListeners.forEach(l -> {
try {
l.onDisconnect(this);
} catch (Exception e) {
Log.severe("Exception while calling PSocketConnectionListener.onDisconnect().", e);
}
});
socket.close();
isClosed.set(true);
}
} catch (IOException e) {
Log.warning(e);
}
}
public SocketAddress getRemoteAddress() {
return addr;
}
public boolean isClosed() {
return isClosed.get() || socket.isClosed();
}
@Override
public String toString() {
return this.getClass().getName() + "{thread=" + getName() + ", socket=" + socket + "}";
}
}

View File

@ -1,20 +0,0 @@
package fr.pandacube.lib.net;
import com.google.common.annotations.Beta;
@Beta
public interface PSocketConnectionListener {
/**
* Called when a socket is connected
* @param connection the connection
*/
void onConnect(PSocket connection);
/**
* Called just before a socket is disconnected
* @param connection the connection
*/
void onDisconnect(PSocket connection);
}

View File

@ -18,7 +18,7 @@ public class ResponseAnalyser {
if (socket == null || socket.isClosed() || socket.isInputShutdown()) if (socket == null || socket.isClosed() || socket.isInputShutdown())
throw new IllegalArgumentException("le socket doit être non null et doit être ouvert sur le flux d'entrée"); throw new IllegalArgumentException("le socket doit être non null et doit être ouvert sur le flux d'entrée");
// on lis la réponse // on lit la réponse
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line; String line;

View File

@ -11,9 +11,9 @@ public abstract class AbstractRequestExecutor {
public final String command; public final String command;
public AbstractRequestExecutor(String cmd, NetworkAPIListener napiListener) { public AbstractRequestExecutor(String cmd, NetworkAPIListener nAPIListener) {
command = cmd.toLowerCase(); command = cmd.toLowerCase();
napiListener.registerRequestExecutor(command, this); nAPIListener.registerRequestExecutor(command, this);
} }
public void execute(String data, Socket socket) throws IOException { public void execute(String data, Socket socket) throws IOException {
@ -34,9 +34,8 @@ public abstract class AbstractRequestExecutor {
/** /**
* *
* @param data La représentation sous forme de String des données envoyés * @param data The String representation of the request data.
* dans la requête * @return The response to send back to the client.
* @return La réponse à retourner au client
*/ */
protected abstract Response run(InetAddress source, String data); protected abstract Response run(InetAddress source, String data);

View File

@ -18,7 +18,7 @@ public class NetworkAPIListener implements Runnable {
private final String name; private final String name;
/** /**
* Instencie le côté serveur du NetworkAPI. * Instancie le côté serveur du NetworkAPI.
* *
* @param n nom du networkAPI (permet l'identification dans les logs) * @param n nom du networkAPI (permet l'identification dans les logs)
* @param p le port d'écoute * @param p le port d'écoute
@ -29,7 +29,7 @@ public class NetworkAPIListener implements Runnable {
} }
/** /**
* Instencie le côté serveur du NetworkAPI. * Instancie le côté serveur du NetworkAPI.
* *
* @param n nom du networkAPI (permet l'identification dans les logs) * @param n nom du networkAPI (permet l'identification dans les logs)
* @param p le port d'écoute * @param p le port d'écoute
@ -56,7 +56,6 @@ public class NetworkAPIListener implements Runnable {
Log.info("NetworkAPI '" + name + "' à l'écoute sur le socket " + serverSocket.getLocalSocketAddress()); Log.info("NetworkAPI '" + name + "' à l'écoute sur le socket " + serverSocket.getLocalSocketAddress());
try { try {
// réception des connexion client
while (!serverSocket.isClosed()) { while (!serverSocket.isClosed()) {
Thread t = new Thread(new PacketExecutor(serverSocket.accept(), this)); Thread t = new Thread(new PacketExecutor(serverSocket.accept(), this));
t.setDaemon(true); t.setDaemon(true);

View File

@ -20,9 +20,9 @@ public class PacketExecutor implements Runnable {
private final Socket socket; private final Socket socket;
private final NetworkAPIListener networkAPIListener; private final NetworkAPIListener networkAPIListener;
public PacketExecutor(Socket s, NetworkAPIListener napiListener) { public PacketExecutor(Socket s, NetworkAPIListener nAPIListener) {
socket = s; socket = s;
networkAPIListener = napiListener; networkAPIListener = nAPIListener;
} }
@Override @Override

View File

@ -10,23 +10,23 @@ public class RequestAnalyser {
public final String command; public final String command;
public final String data; public final String data;
public RequestAnalyser(Socket socket, NetworkAPIListener napiListener) throws IOException, BadRequestException { public RequestAnalyser(Socket socket, NetworkAPIListener nAPIListener) throws IOException, BadRequestException {
if (socket == null || socket.isClosed() || socket.isInputShutdown() || napiListener == null) if (socket == null || socket.isClosed() || socket.isInputShutdown() || nAPIListener == null)
throw new IllegalArgumentException( throw new IllegalArgumentException(
"le socket doit être non null et doit être ouvert sur le flux d'entrée et napiListener ne doit pas être null"); "le socket doit être non null et doit être ouvert sur le flux d'entrée et nAPIListener ne doit pas être null");
// on lis la réponse // on lit la réponse
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line; String line;
// lecture de la première ligne // lecture de la première ligne
line = in.readLine(); line = in.readLine();
if (line == null || !line.equals(napiListener.pass)) throw new BadRequestException("wrong_password"); if (line == null || !line.equals(nAPIListener.pass)) throw new BadRequestException("wrong_password");
// lecture de la deuxième ligne // lecture de la deuxième ligne
line = in.readLine(); line = in.readLine();
if (line == null || napiListener.getRequestExecutor(line) == null) if (line == null || nAPIListener.getRequestExecutor(line) == null)
throw new BadRequestException("command_not_exists"); throw new BadRequestException("command_not_exists");
command = line; command = line;

View File

@ -25,7 +25,7 @@
<url>https://maven.enginehub.org/repo/</url> <url>https://maven.enginehub.org/repo/</url>
</repository> </repository>
<!-- Vault and maybe other dependecies --> <!-- Vault and maybe other dependencies -->
<repository> <repository>
<id>jitpack.io</id> <id>jitpack.io</id>
<url>https://jitpack.io</url> <url>https://jitpack.io</url>
@ -33,12 +33,12 @@
</repositories> </repositories>
<dependencies> <dependencies>
<dependency> <!-- <dependency>
<groupId>fr.pandacube.lib</groupId> <groupId>fr.pandacube.lib</groupId>
<artifactId>pandalib-players-permissible</artifactId> <artifactId>pandalib-players-permissible</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency> -->
<dependency> <dependency>
<groupId>fr.pandacube.lib</groupId> <groupId>fr.pandacube.lib</groupId>
<artifactId>pandalib-permissions</artifactId> <artifactId>pandalib-permissions</artifactId>

View File

@ -42,7 +42,7 @@ public class PandalibPaperPermissions implements Listener {
* Integrates the {@code pandalib-permissions} system into the Bukkit server. * Integrates the {@code pandalib-permissions} system into the Bukkit server.
* @param plugin a Bukkit plugin. * @param plugin a Bukkit plugin.
* @param serverName the name of the current server, used to fetch server specific permissions. Cannot be null. * @param serverName the name of the current server, used to fetch server specific permissions. Cannot be null.
* If this server in not in a multi-server configuration, use a dummy server name, like * If this server in not in a multiserver configuration, use a dummy server name, like
* {@code ""} (empty string). * {@code ""} (empty string).
*/ */
public static void init(JavaPlugin plugin, String serverName) { public static void init(JavaPlugin plugin, String serverName) {

View File

@ -1,5 +1,23 @@
package fr.pandacube.lib.paper.permissions; package fr.pandacube.lib.paper.permissions;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import fr.pandacube.lib.permissions.Permissions;
import fr.pandacube.lib.reflect.Reflect;
import fr.pandacube.lib.util.Log;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.entity.Player;
import org.bukkit.permissions.Permissible;
import org.bukkit.permissions.PermissibleBase;
import org.bukkit.permissions.Permission;
import org.bukkit.permissions.PermissionAttachment;
import org.bukkit.permissions.PermissionAttachmentInfo;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
@ -11,24 +29,6 @@ import java.util.concurrent.TimeUnit;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.entity.Player;
import org.bukkit.permissions.Permissible;
import org.bukkit.permissions.PermissibleBase;
import org.bukkit.permissions.Permission;
import org.bukkit.permissions.PermissionAttachment;
import org.bukkit.permissions.PermissionAttachmentInfo;
import org.bukkit.plugin.Plugin;
import fr.pandacube.lib.permissions.Permissions;
import fr.pandacube.lib.reflect.Reflect;
import fr.pandacube.lib.util.Log;
/* package */ class PermissionsInjectorBukkit /* package */ class PermissionsInjectorBukkit
{ {
@ -58,26 +58,24 @@ import fr.pandacube.lib.util.Log;
} }
} }
private static void setPermissible(CommandSender sender, Permissible newpermissible) private static void setPermissible(CommandSender sender, Permissible newPermissible)
{ {
try { try {
Field perm = getPermField(sender); Field perm = getPermField(sender);
if (perm == null) if (perm == null)
return; return;
perm.setAccessible(true); perm.setAccessible(true);
perm.set(sender, newpermissible); perm.set(sender, newPermissible);
} }
catch (Exception e) { catch (Exception e) {
Log.severe(e); throw new RuntimeException(e);
} }
} }
/* package */ static Permissible getPermissible(CommandSender sender) /* package */ static Permissible getPermissible(CommandSender sender)
{ {
Field perm = getPermField(sender);
if (perm == null)
return null;
try { try {
Field perm = getPermField(sender);
perm.setAccessible(true); perm.setAccessible(true);
Permissible p = (Permissible) perm.get(sender); Permissible p = (Permissible) perm.get(sender);
if (p == null) { if (p == null) {
@ -86,26 +84,19 @@ import fr.pandacube.lib.util.Log;
return p; return p;
} }
catch (Exception e) { catch (Exception e) {
Log.severe(e); throw new RuntimeException(e);
} }
return null;
} }
private static Field getPermField(CommandSender sender) private static Field getPermField(CommandSender sender) throws NoSuchFieldException {
{
if (sender == null) { if (sender == null) {
throw new IllegalArgumentException("sender cannot be null"); throw new IllegalArgumentException("sender cannot be null");
} }
try {
if (sender instanceof Player || sender instanceof ConsoleCommandSender) if (sender instanceof Player || sender instanceof ConsoleCommandSender)
return Reflect.ofClassOfInstance(sender).field("perm").get(); return Reflect.ofClassOfInstance(sender).field("perm").get();
else else
throw new IllegalArgumentException("Unsupported type for sender: " + sender.getClass()); throw new IllegalArgumentException("Unsupported type for sender: " + sender.getClass());
}
catch (Exception e) {
Log.severe(e);
}
return null;
} }
/* package */ static class PandaPermissible extends PermissibleBase /* package */ static class PandaPermissible extends PermissibleBase
@ -118,7 +109,7 @@ import fr.pandacube.lib.util.Log;
@SuppressWarnings("UnusedAssignment") @SuppressWarnings("UnusedAssignment")
private boolean init = false; private boolean init = false;
/* assigment to false is necessary because of super class constructor calling the method recalculatePermission() /* assignment to false is necessary because of super class constructor calling the method recalculatePermission()
* and we dont want that. * and we dont want that.
*/ */
@ -143,7 +134,7 @@ import fr.pandacube.lib.util.Log;
public boolean hasPermission(String permission) public boolean hasPermission(String permission)
{ {
/* /*
* WARNING: dont call PermissibleOnlinePlayer#hasPermission(String) here or it will result on a stack overflow * WARNING: dont call PermissibleOnlinePlayer#hasPermission(String) here, or it will result on a stack overflow
*/ */
if (permission.toLowerCase().startsWith("minecraft.command.")) if (permission.toLowerCase().startsWith("minecraft.command."))
@ -180,7 +171,7 @@ import fr.pandacube.lib.util.Log;
if (res != null) if (res != null)
return res; return res;
return oldPermissible.hasPermission(permission); // doesnt need to manage negative permission (should not happend) return oldPermissible.hasPermission(permission); // doesn't need to manage negative permission (should not happen)
} }
@Override @Override
@ -214,22 +205,17 @@ import fr.pandacube.lib.util.Log;
.build(); .build();
@Override @Override
public Set<PermissionAttachmentInfo> getEffectivePermissions() public @NotNull Set<PermissionAttachmentInfo> getEffectivePermissions()
{ {
// PlotSquared uses this method to optimize permission range (plots.limit.10 for example) // PlotSquared uses this method to optimize permission range (plots.limit.10 for example)
// MobArena uses this method when a player leave the arena // MobArena uses this method when a player leave the arena
// LibsDisguises uses this method (and only this one) to parse all the permissions // LibsDisguises uses this method (and only this one) to parse all the permissions
//Log.warning("There is a plugin calling CommandSender#getEffectivePermissions(). See the stacktrace to understand the reason for that.", new Throwable());
String world = null;
if (sender instanceof Player player) { if (sender instanceof Player player) {
world = player.getWorld().getName(); String world = player.getWorld().getName();
}
try { try {
return effectivePermissionsListCache.get(world, () -> { return effectivePermissionsListCache.get(world, () -> {
// first get the superperms effective permissions (taht take isOp into accound) // first get the superperms effective permissions (that take isOp into account)
Map<String, PermissionAttachmentInfo> perms = oldPermissible.getEffectivePermissions().stream() Map<String, PermissionAttachmentInfo> perms = oldPermissible.getEffectivePermissions().stream()
.collect(Collectors.toMap(PermissionAttachmentInfo::getPermission, Function.identity())); .collect(Collectors.toMap(PermissionAttachmentInfo::getPermission, Function.identity()));
@ -242,8 +228,11 @@ import fr.pandacube.lib.util.Log;
}); });
} catch (ExecutionException e) { } catch (ExecutionException e) {
Log.severe(e); Log.severe(e);
return oldPermissible.getEffectivePermissions();
} }
}
return oldPermissible.getEffectivePermissions();
} }
@ -260,7 +249,7 @@ import fr.pandacube.lib.util.Log;
} }
@Override @Override
public boolean isPermissionSet(String permission) public boolean isPermissionSet(@NotNull String permission)
{ {
Boolean res = hasPermissionOnServerInWorld(permission); Boolean res = hasPermissionOnServerInWorld(permission);
if (res != null) if (res != null)
@ -278,31 +267,31 @@ import fr.pandacube.lib.util.Log;
} }
@Override @Override
public PermissionAttachment addAttachment(Plugin plugin) public @NotNull PermissionAttachment addAttachment(@NotNull Plugin plugin)
{ {
return oldPermissible.addAttachment(plugin); return oldPermissible.addAttachment(plugin);
} }
@Override @Override
public PermissionAttachment addAttachment(Plugin plugin, int ticks) public PermissionAttachment addAttachment(@NotNull Plugin plugin, int ticks)
{ {
return oldPermissible.addAttachment(plugin, ticks); return oldPermissible.addAttachment(plugin, ticks);
} }
@Override @Override
public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value) public @NotNull PermissionAttachment addAttachment(@NotNull Plugin plugin, @NotNull String name, boolean value)
{ {
return oldPermissible.addAttachment(plugin, name, value); return oldPermissible.addAttachment(plugin, name, value);
} }
@Override @Override
public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value, int ticks) public PermissionAttachment addAttachment(@NotNull Plugin plugin, @NotNull String name, boolean value, int ticks)
{ {
return oldPermissible.addAttachment(plugin, name, value, ticks); return oldPermissible.addAttachment(plugin, name, value, ticks);
} }
@Override @Override
public void removeAttachment(PermissionAttachment attachment) public void removeAttachment(@NotNull PermissionAttachment attachment)
{ {
oldPermissible.removeAttachment(attachment); oldPermissible.removeAttachment(attachment);
} }

View File

@ -6,11 +6,12 @@ import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@SuppressWarnings("CanBeFinal")
public class PaperBackupConfig { public class PaperBackupConfig {
public boolean worldBackupEnabled = true; public boolean worldBackupEnabled = true;
public boolean workdirBackupEnabled = true; public boolean workdirBackupEnabled = true;
public boolean logsBackupEnabled = true; public boolean logsBackupEnabled = true;
public String scheduling = "0 2 * * *"; // cron format, here is everyday at 2am public String scheduling = "0 2 * * *"; // cron format, here is every day at 2am
public File backupDirectory = null; public File backupDirectory = null;
public BackupCleaner worldBackupCleaner = BackupCleaner.KEEPING_1_EVERY_N_MONTH(3).merge(BackupCleaner.KEEPING_N_LAST(5)); public BackupCleaner worldBackupCleaner = BackupCleaner.KEEPING_1_EVERY_N_MONTH(3).merge(BackupCleaner.KEEPING_N_LAST(5));
public BackupCleaner workdirBackupCleaner = BackupCleaner.KEEPING_1_EVERY_N_MONTH(3).merge(BackupCleaner.KEEPING_N_LAST(5)); public BackupCleaner workdirBackupCleaner = BackupCleaner.KEEPING_1_EVERY_N_MONTH(3).merge(BackupCleaner.KEEPING_N_LAST(5));

View File

@ -1,10 +1,6 @@
package fr.pandacube.lib.paper.backup; package fr.pandacube.lib.paper.backup;
import fr.pandacube.lib.util.Log;
import java.io.File; import java.io.File;
import java.text.DateFormat;
import java.util.Date;
import java.util.function.BiPredicate; import java.util.function.BiPredicate;
public class PaperWorkdirProcess extends PaperBackupProcess { public class PaperWorkdirProcess extends PaperBackupProcess {
@ -15,9 +11,7 @@ public class PaperWorkdirProcess extends PaperBackupProcess {
public BiPredicate<File, String> getFilenameFilter() { public BiPredicate<File, String> getFilenameFilter() {
return new BiPredicate<File, String>() { return (file, path) -> {
@Override
public boolean test(File file, String path) {
if (file.isDirectory() && new File(file, "level.dat").exists()) if (file.isDirectory() && new File(file, "level.dat").exists())
return false; return false;
if (new File(getSourceDir(), "logs").equals(file)) if (new File(getSourceDir(), "logs").equals(file))
@ -25,7 +19,6 @@ public class PaperWorkdirProcess extends PaperBackupProcess {
if (file.isFile() && file.getName().endsWith(".lck")) if (file.isFile() && file.getName().endsWith(".lck"))
return false; return false;
return PaperWorkdirProcess.super.getFilenameFilter().test(file, path); return PaperWorkdirProcess.super.getFilenameFilter().test(file, path);
}
}; };
} }

View File

@ -10,7 +10,6 @@ import org.bukkit.World;
import java.io.File; import java.io.File;
import java.text.DateFormat; import java.text.DateFormat;
import java.util.Date; import java.util.Date;
import java.util.function.BiPredicate;
public class PaperWorldProcess extends PaperBackupProcess { public class PaperWorldProcess extends PaperBackupProcess {
private final String worldName; private final String worldName;

View File

@ -77,7 +77,7 @@ public abstract class PaperBrigadierCommand extends BrigadierCommand<BukkitBriga
} }
/** /**
* Removes a plugin command that overrides a vanilla command, so the vanilla command functionnalities are fully * Removes a plugin command that overrides a vanilla command, so the vanilla command functionalities are fully
* restored (so, not only the usage, but also the suggestions and the command structure sent to the client). * restored (so, not only the usage, but also the suggestions and the command structure sent to the client).
* @param name the name of the command to restore. * @param name the name of the command to restore.
*/ */
@ -137,7 +137,7 @@ public abstract class PaperBrigadierCommand extends BrigadierCommand<BukkitBriga
private Set<String> registeredAliases; private Set<String> registeredAliases;
/** /**
* Instanciate this command instance. * Instantiate this command instance.
* *
* @param pl the plugin instance. * @param pl the plugin instance.
* @param regPolicy the registration policy for this command. * @param regPolicy the registration policy for this command.
@ -155,7 +155,7 @@ public abstract class PaperBrigadierCommand extends BrigadierCommand<BukkitBriga
} }
/** /**
* Instanciate this command isntance with a registration policy of {@link RegistrationPolicy#ONLY_BASE_COMMAND}. * Instantiate this command instance with a registration policy of {@link RegistrationPolicy#ONLY_BASE_COMMAND}.
* @param pl the plugin instance. * @param pl the plugin instance.
*/ */
public PaperBrigadierCommand(Plugin pl) { public PaperBrigadierCommand(Plugin pl) {
@ -206,10 +206,10 @@ public abstract class PaperBrigadierCommand extends BrigadierCommand<BukkitBriga
// nmsDispatcher integration and conflit resolution // nmsDispatcher integration and conflit resolution
boolean nmsRegister = false, nmsRegistered = false; boolean nmsRegister = false, nmsRegistered = false;
CommandNode<BukkitBrigadierCommandSource> nmsConflited = root.getChild(name); CommandNode<BukkitBrigadierCommandSource> nmsConflicted = root.getChild(name);
if (nmsConflited != null) { if (nmsConflicted != null) {
if (isFromThisCommand(nmsConflited)) { if (isFromThisCommand(nmsConflicted)) {
// this command is already registered in NMS. Dont need to register again // this command is already registered in NMS. Dont need to register again
nmsRegistered = true; nmsRegistered = true;
} }
@ -221,7 +221,7 @@ public abstract class PaperBrigadierCommand extends BrigadierCommand<BukkitBriga
Log.severe("/" + name + " already in NMS Brigadier instance." Log.severe("/" + name + " already in NMS Brigadier instance."
+ " Wont replace it because registration is not forced for prefixed or initial name of a command."); + " Wont replace it because registration is not forced for prefixed or initial name of a command.");
} }
else { // conflict, wont replace, not forced but only an alias anyway else { // conflict, won't replace, not forced but only an alias anyway
Log.info("/" + name + " already in NMS Brigadier instance." Log.info("/" + name + " already in NMS Brigadier instance."
+ " Wont replace it because registration is not forced for a non-prefixed alias."); + " Wont replace it because registration is not forced for a non-prefixed alias.");
} }
@ -418,7 +418,7 @@ public abstract class PaperBrigadierCommand extends BrigadierCommand<BukkitBriga
/** /**
* A suggestions supplier that suggests the names of the currently connected players (that the command sender can see). * A suggestion supplier that suggests the names of the currently connected players (that the command sender can see).
*/ */
public static final SuggestionsSupplier<CommandSender> TAB_PLAYER_CURRENT_SERVER = (sender, ti, token, a) -> { public static final SuggestionsSupplier<CommandSender> TAB_PLAYER_CURRENT_SERVER = (sender, ti, token, a) -> {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -432,7 +432,7 @@ public abstract class PaperBrigadierCommand extends BrigadierCommand<BukkitBriga
}; };
/** /**
* A suggestions supplier that suggests the names of the worlds currently loaded on this server. * A suggestion supplier that suggests the names of the worlds currently loaded on this server.
*/ */
public static final SuggestionsSupplier<CommandSender> TAB_WORLDS = SuggestionsSupplier.fromStreamSupplier(() -> Bukkit.getWorlds().stream().map(World::getName)); public static final SuggestionsSupplier<CommandSender> TAB_WORLDS = SuggestionsSupplier.fromStreamSupplier(() -> Bukkit.getWorlds().stream().map(World::getName));
@ -477,7 +477,7 @@ public abstract class PaperBrigadierCommand extends BrigadierCommand<BukkitBriga
/* /*
* Minecraft argument type * Minecraft's argument type
*/ */
@ -577,13 +577,13 @@ public abstract class PaperBrigadierCommand extends BrigadierCommand<BukkitBriga
* Gets the value of the provided argument of type {@code minecraft:block_pos}, from the provided context. * Gets the value of the provided argument of type {@code minecraft:block_pos}, from the provided context.
* @param context the command execution context. * @param context the command execution context.
* @param argument the argument name. * @param argument the argument name.
* @param deflt a defualt value if the argument is not found. * @param deflt a default value if the argument is not found.
* @return the value of the argument. * @return the value of the argument.
*/ */
public BlockVector tryGetMinecraftBlockPositionArgument(CommandContext<BukkitBrigadierCommandSource> context, public BlockVector tryGetMinecraftBlockPositionArgument(CommandContext<BukkitBrigadierCommandSource> context,
String argument, BlockVector deflt) { String argument, BlockVector deflt) {
return tryGetArgument(context, argument, Coordinates.MAPPING.runtimeClass(), nmsCoord -> { return tryGetArgument(context, argument, Coordinates.MAPPING.runtimeClass(), nmsCoordinate -> {
BlockPos bp = ReflectWrapper.wrap(nmsCoord, Coordinates.class).getBlockPos(context.getSource()); BlockPos bp = ReflectWrapper.wrap(nmsCoordinate, Coordinates.class).getBlockPos(context.getSource());
return new BlockVector(bp.getX(), bp.getY(), bp.getZ()); return new BlockVector(bp.getX(), bp.getY(), bp.getZ());
}, deflt); }, deflt);
} }
@ -603,14 +603,14 @@ public abstract class PaperBrigadierCommand extends BrigadierCommand<BukkitBriga
* Gets the value of the provided argument of type {@code minecraft:vec3}, from the provided context. * Gets the value of the provided argument of type {@code minecraft:vec3}, from the provided context.
* @param context the command execution context. * @param context the command execution context.
* @param argument the argument name. * @param argument the argument name.
* @param deflt a defualt value if the argument is not found. * @param deflt a default value if the argument is not found.
* @return the value of the argument. * @return the value of the argument.
*/ */
public Vector tryGetMinecraftVec3Argument(CommandContext<BukkitBrigadierCommandSource> context, String argument, public Vector tryGetMinecraftVec3Argument(CommandContext<BukkitBrigadierCommandSource> context, String argument,
Vector deflt) { Vector deflt) {
return tryGetArgument(context, argument, Coordinates.MAPPING.runtimeClass(), return tryGetArgument(context, argument, Coordinates.MAPPING.runtimeClass(),
nmsCoord -> CraftVector.toBukkit( nmsCoordinate -> CraftVector.toBukkit(
ReflectWrapper.wrap(nmsCoord, Coordinates.class).getPosition(context.getSource()) ReflectWrapper.wrap(nmsCoordinate, Coordinates.class).getPosition(context.getSource())
), ),
deflt); deflt);
} }
@ -630,7 +630,7 @@ public abstract class PaperBrigadierCommand extends BrigadierCommand<BukkitBriga
* Gets the value of the provided argument of type {@code minecraft:component}, from the provided context. * Gets the value of the provided argument of type {@code minecraft:component}, from the provided context.
* @param context the command execution context. * @param context the command execution context.
* @param argument the argument name. * @param argument the argument name.
* @param deflt a defualt value if the argument is not found. * @param deflt a default value if the argument is not found.
* @return the value of the argument. * @return the value of the argument.
*/ */
public Component tryGetMinecraftChatComponentArgument(CommandContext<BukkitBrigadierCommandSource> context, public Component tryGetMinecraftChatComponentArgument(CommandContext<BukkitBrigadierCommandSource> context,

View File

@ -24,36 +24,36 @@ import fr.pandacube.lib.util.Log;
import fr.pandacube.lib.paper.util.BukkitEvent; import fr.pandacube.lib.paper.util.BukkitEvent;
/** /**
* Managed a « lobby » type hotbar menu/inventory. It represents items in the player inventory on which you can right click on it. * Managed a "lobby" type hot bar menu/inventory. It represents items in the
* player inventory on which you can right-click on it.
* The player can't move or drop these items. * The player can't move or drop these items.
*
*/ */
public class GUIHotBar implements Listener { public class GUIHotBar implements Listener {
private final Map<ItemStack, BiConsumer<PlayerInventory, ItemStack>> itemsAndSetters = new HashMap<>(); private final Map<ItemStack, BiConsumer<PlayerInventory, ItemStack>> itemsAndSetters = new HashMap<>();
private final Map<ItemStack, Consumer<Player>> itemsAndRunnables = new HashMap<>(); private final Map<ItemStack, Consumer<Player>> itemsAndClickListeners = new HashMap<>();
private final int defltSlot; private final int defaultSlot;
private final List<Player> currentPlayers = new ArrayList<>(); private final List<Player> currentPlayers = new ArrayList<>();
public GUIHotBar(int defaultSlot) { public GUIHotBar(int defaultSlot) {
defltSlot = Math.max(0, Math.min(8, defaultSlot)); this.defaultSlot = Math.max(0, Math.min(8, defaultSlot));
BukkitEvent.register(this); BukkitEvent.register(this);
} }
/** /**
* Add the item to this hotbar menu. if there is already players hooked to this hotbar, the item will be directly added to * Add the item to this hot bar menu. if there is already players hooked to this hot bar, the item will be directly added to
* their inventories. * their inventories.
* @param i the item stack * @param i the item stack
* @param setter code executed to put the item in the inventory. Additionally check for permission before doing the addition. * @param setter code executed to put the item in the inventory. Additionally, check for permission before doing the addition.
* @param run the Runnable to run when the user right click on the item in the hotbar. * @param run the Runnable to run when the user right-click on the item in the hot bar.
*/ */
public GUIHotBar addItem(ItemStack i, BiConsumer<PlayerInventory, ItemStack> setter, Consumer<Player> run) { public GUIHotBar addItem(ItemStack i, BiConsumer<PlayerInventory, ItemStack> setter, Consumer<Player> run) {
itemsAndSetters.put(i, setter); itemsAndSetters.put(i, setter);
itemsAndRunnables.put(i, run); itemsAndClickListeners.put(i, run);
for (Player p : currentPlayers) for (Player p : currentPlayers)
addItemToPlayer(p, i); addItemToPlayer(p, i);
@ -62,9 +62,9 @@ public class GUIHotBar implements Listener {
} }
/** /**
* Add the hotbar elements to this player. * Add the hot bar elements to this player.
* *
* The players is automatically removed when they quit. You can remove it before by calling {@link #removePlayer(Player)}. * The player is automatically removed when they quit. You can remove it before by calling {@link #removePlayer(Player)}.
*/ */
public void addPlayer(Player p) { public void addPlayer(Player p) {
if (!currentPlayers.contains(p)) if (!currentPlayers.contains(p))
@ -74,11 +74,11 @@ public class GUIHotBar implements Listener {
addItemToPlayer(p, is); addItemToPlayer(p, is);
} }
p.getInventory().setHeldItemSlot(defltSlot); p.getInventory().setHeldItemSlot(defaultSlot);
} }
/** /**
* Detach this player from this hotbar manager and removes the managed items from the players inventory. * Detach this player from this hot bar manager and removes the managed items from the players inventory.
*/ */
public void removePlayer(Player p) { public void removePlayer(Player p) {
if (!currentPlayers.contains(p)) if (!currentPlayers.contains(p))
@ -110,9 +110,9 @@ public class GUIHotBar implements Listener {
public void addItemToPlayer(Player p, ItemStack is) { public void addItemToPlayer(Player p, ItemStack is) {
if (!itemsAndSetters.containsKey(is)) if (!itemsAndSetters.containsKey(is))
throw new IllegalArgumentException("The provided ItemStack is not registered in this HotbarMenu"); throw new IllegalArgumentException("The provided ItemStack is not registered in this GUIHotBar");
if (!currentPlayers.contains(p)) if (!currentPlayers.contains(p))
throw new IllegalArgumentException("The provided Player is not registered in this HotbarMenu"); throw new IllegalArgumentException("The provided Player is not registered in this GUIHotBar");
itemsAndSetters.get(is).accept(p.getInventory(), is.clone()); itemsAndSetters.get(is).accept(p.getInventory(), is.clone());
} }
@ -153,10 +153,10 @@ public class GUIHotBar implements Listener {
Player p = event.getPlayer(); Player p = event.getPlayer();
for (ItemStack is : itemsAndRunnables.keySet()) { for (ItemStack is : itemsAndClickListeners.keySet()) {
if (item.isSimilar(is)) { if (item.isSimilar(is)) {
try { try {
itemsAndRunnables.get(is).accept(p); itemsAndClickListeners.get(is).accept(p);
} catch (Exception e) { } catch (Exception e) {
Log.severe(e); Log.severe(e);
} }
@ -181,7 +181,7 @@ public class GUIHotBar implements Listener {
for (ItemStack is : itemsAndSetters.keySet()) { for (ItemStack is : itemsAndSetters.keySet()) {
if (item != null && item.isSimilar(is)) { if (item != null && item.isSimilar(is)) {
try { try {
itemsAndRunnables.get(is).accept((Player) inv.getHolder()); itemsAndClickListeners.get(is).accept((Player) inv.getHolder());
} catch (Exception e) { } catch (Exception e) {
Log.severe(e); Log.severe(e);
} }

View File

@ -31,7 +31,7 @@ public class GUIInventory implements Listener {
/** /**
* Used as parameter of {@link #buildButton(ItemStack, Integer, ComponentLike, List, Map)} to indicate that a button should * Used as parameter of {@link #buildButton(ItemStack, Integer, ComponentLike, List, Map)} to indicate that a button should
* shine like an enchanted object, without showing enchant informations in the hover text. * shine like an enchanted object, without showing enchant information in the hover text.
*/ */
public static final Map<Enchantment, Integer> FAKE_ENCHANT = ImmutableMap.of(Enchantment.DURABILITY, 1); public static final Map<Enchantment, Integer> FAKE_ENCHANT = ImmutableMap.of(Enchantment.DURABILITY, 1);
@ -44,7 +44,7 @@ public class GUIInventory implements Listener {
/** /**
* Create a new inventory based GUI. * Create a new inventory based GUI.
* @param p the player for which to create the GUI. * @param p the player for which to create the GUI.
* @param nbLines the number of invotory lines for the interface. * @param nbLines the number of inventory lines for the interface.
* @param title the title of the GUI (title of the inventory) * @param title the title of the GUI (title of the inventory)
* @param closeEventAction the action to perform when the player closes the GUI inventory * @param closeEventAction the action to perform when the player closes the GUI inventory
*/ */
@ -73,7 +73,7 @@ public class GUIInventory implements Listener {
* @param p the slot index. * @param p the slot index.
* @param iStack the item to put in the slot. * @param iStack the item to put in the slot.
* @param clickEventActions the action to perform when the user clicks that button. The event passed as a parameter * @param clickEventActions the action to perform when the user clicks that button. The event passed as a parameter
* is already cancelled. It is possible to uncancel it if needed. * is already cancelled. It is possible to un-cancel it if needed.
*/ */
public void setButtonIfEmpty(int p, ItemStack iStack, Consumer<InventoryClickEvent> clickEventActions) { public void setButtonIfEmpty(int p, ItemStack iStack, Consumer<InventoryClickEvent> clickEventActions) {
if (inv.getItem(p) == null) if (inv.getItem(p) == null)
@ -85,7 +85,7 @@ public class GUIInventory implements Listener {
* @param p the slot index. * @param p the slot index.
* @param iStack the item to put in the slot. * @param iStack the item to put in the slot.
* @param clickEventActions the action to perform when the user clicks that button. The event passed as a parameter * @param clickEventActions the action to perform when the user clicks that button. The event passed as a parameter
* is already cancelled. It is possible to uncancel it if needed. * is already cancelled. It is possible to un-cancel it if needed.
*/ */
public void setButton(int p, ItemStack iStack, Consumer<InventoryClickEvent> clickEventActions) { public void setButton(int p, ItemStack iStack, Consumer<InventoryClickEvent> clickEventActions) {
inv.setItem(p, iStack); inv.setItem(p, iStack);
@ -96,7 +96,7 @@ public class GUIInventory implements Listener {
* Update/replace the action to perform for a specific slot. * Update/replace the action to perform for a specific slot.
* @param p the slot index. * @param p the slot index.
* @param clickEventActions the action to perform when the user clicks that button. The event passed as a parameter * @param clickEventActions the action to perform when the user clicks that button. The event passed as a parameter
* is already cancelled. It is possible to uncancel it if needed. * is already cancelled. It is possible to un-cancel it if needed.
*/ */
public void changeClickEventAction(int p, Consumer<InventoryClickEvent> clickEventActions) { public void changeClickEventAction(int p, Consumer<InventoryClickEvent> clickEventActions) {
onClickEvents.put(p, clickEventActions); onClickEvents.put(p, clickEventActions);
@ -122,7 +122,7 @@ public class GUIInventory implements Listener {
/** /**
* Force this GUI to be closes, without the intervention of the player. * Force this GUI to be closes, without the intervention of the player.
* The bukkit API will call the {@link InventoryCloseEvent}, trigerring eventual actions associated with this event. * The bukkit API will call the {@link InventoryCloseEvent}, triggering eventual actions associated with this event.
*/ */
public void forceClose() { public void forceClose() {
if (!isOpened) return; if (!isOpened) return;

View File

@ -28,10 +28,11 @@ import java.util.Map;
Map<String, Object> deserializedMap = context.deserialize(json, MAP_STR_OBJ_TYPE.getType()); Map<String, Object> deserializedMap = context.deserialize(json, MAP_STR_OBJ_TYPE.getType());
int itemStackVersion = deserializedMap.containsKey("v") ? ((Number)deserializedMap.get("v")).intValue() : -1; int itemStackVersion = deserializedMap.containsKey("v") ? ((Number)deserializedMap.get("v")).intValue() : -1;
if (itemStackVersion >= 0) { if (itemStackVersion >= 0) {
@SuppressWarnings("deprecation")
int currentDataVersion = Bukkit.getUnsafe().getDataVersion(); int currentDataVersion = Bukkit.getUnsafe().getDataVersion();
if (itemStackVersion > currentDataVersion) { if (itemStackVersion > currentDataVersion) {
/* The itemStack we are deserializing is from a newer MC version, so Bukkit will refuse it. /* The itemStack we are deserializing is from a newer MC version, so Bukkit will refuse it.
* We decide to ignore the provided version and consider that the received itemstack is from current * We decide to ignore the provided version and consider that the received item stack is from current
* version. We let Bukkit handles the deserialization with the data it can interpret, throwing an error * version. We let Bukkit handles the deserialization with the data it can interpret, throwing an error
* only if it can't. * only if it can't.
*/ */

View File

@ -28,7 +28,6 @@ import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender; import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.player.PlayerQuitEvent;
@ -57,7 +56,7 @@ public class PerformanceAnalysisManager implements Listener {
} }
private static final int NB_TICK_HISTORY = 20 * 60 * 60; // 60 secondes; private static final int NB_TICK_HISTORY = 20 * 60 * 60; // 60 secondes ;
private final Plugin plugin = PandaLibPaper.getPlugin(); private final Plugin plugin = PandaLibPaper.getPlugin();
private long firstRecord = 0; private long firstRecord = 0;
@ -292,7 +291,7 @@ public class PerformanceAnalysisManager implements Listener {
} }
else { else {
String tps1sDisp = Double.isNaN(tps1s) ? "N/A" : (Math.round(tps1s)) + ""; String tps1sDisplay = Double.isNaN(tps1s) ? "N/A" : (Math.round(tps1s)) + "";
int[] tpsHistory = getTPSHistory(); int[] tpsHistory = getTPSHistory();
@ -319,7 +318,7 @@ public class PerformanceAnalysisManager implements Listener {
// we have a lag spike, so we need to display the time since lagging // we have a lag spike, so we need to display the time since lagging
long lagDurationSec = System.nanoTime() - tickEndNanoTime; long lagDurationSec = System.nanoTime() - tickEndNanoTime;
timings = text("(") timings = text("(")
.thenFailure("lag:" + dispRound10(lagDurationSec / (double) 1_000_000_000) + "s") .thenFailure("lag:" + displayRound10(lagDurationSec / (double) 1_000_000_000) + "s")
.thenText(")"); .thenText(")");
} }
else { else {
@ -359,7 +358,7 @@ public class PerformanceAnalysisManager implements Listener {
title = infoText("TPS [") title = infoText("TPS [")
.thenLegacyText(s.toString()) .thenLegacyText(s.toString())
.thenText("] ") .thenText("] ")
.then(text(tps1sDisp+"/20 ").color(tps1sGradient.pickColorAt(tps1s))) .then(text(tps1sDisplay+"/20 ").color(tps1sGradient.pickColorAt(tps1s)))
.then(timings); .then(timings);
} }
@ -469,7 +468,7 @@ public class PerformanceAnalysisManager implements Listener {
Log.info(finalMessage.getLegacyText()); Log.info(finalMessage.getLegacyText());
} }
public static String dispRound10(double val) { public static String displayRound10(double val) {
long v = (long) Math.ceil(val * 10); long v = (long) Math.ceil(val * 10);
return "" + (v / 10f); return "" + (v / 10f);
} }

View File

@ -1,6 +1,5 @@
package fr.pandacube.lib.paper.players; package fr.pandacube.lib.paper.players;
import com.google.common.io.Files;
import fr.pandacube.lib.paper.reflect.util.PrimaryWorlds; import fr.pandacube.lib.paper.reflect.util.PrimaryWorlds;
import fr.pandacube.lib.paper.reflect.wrapper.craftbukkit.CraftServer; import fr.pandacube.lib.paper.reflect.wrapper.craftbukkit.CraftServer;
import fr.pandacube.lib.paper.reflect.wrapper.dataconverter.MCDataConverter; import fr.pandacube.lib.paper.reflect.wrapper.dataconverter.MCDataConverter;
@ -21,6 +20,7 @@ import org.bukkit.scoreboard.Team;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files;
import java.util.function.UnaryOperator; import java.util.function.UnaryOperator;
/** /**
@ -76,7 +76,7 @@ public interface PaperOffPlayer extends AbstractOffPlayer {
* @return the display name of the player. * @return the display name of the player.
* *
* @implNote This default implementation gets the display name from bukkit (if the player is online). * @implNote This default implementation gets the display name from bukkit (if the player is online).
* If its different to the player name, it returns it. Otherwise, it tries to generate the team displayname with {@link #getTeamDisplayName()}. * If it's different to the player name, it returns it. Otherwise, it tries to generate the team display name with {@link #getTeamDisplayName()}.
* If the player is not in a team, then the player name is used. * If the player is not in a team, then the player name is used.
*/ */
@Override @Override
@ -84,16 +84,16 @@ public interface PaperOffPlayer extends AbstractOffPlayer {
String name = getName(); String name = getName();
Player p = getBukkitPlayer(); Player p = getBukkitPlayer();
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
String bukkitDispName = p != null ? p.getDisplayName() : name; String bukkitDisplayName = p != null ? p.getDisplayName() : name;
if (!name.equals(bukkitDispName)) if (!name.equals(bukkitDisplayName))
return bukkitDispName; return bukkitDisplayName;
String teamDispName = getTeamDisplayName(); String teamDisplayName = getTeamDisplayName();
return teamDispName == null ? name : teamDispName; return teamDisplayName == null ? name : teamDisplayName;
} }
/** /**
* Computes and returns the the name of the player with the prefix, suffix and color of the team the player is in. * Computes and returns the name of the player with the prefix, suffix and color of the team the player is in.
* @return The legacy formated player display name, if he is in a {@link Team}, or null otherwise. * @return The legacy formatted player display name, if he is in a {@link Team}, or null otherwise.
*/ */
default String getTeamDisplayName() { default String getTeamDisplayName() {
String name = getName(); String name = getName();
@ -151,10 +151,10 @@ public interface PaperOffPlayer extends AbstractOffPlayer {
*/ */
/** /**
* Gets the NBT data from the playerdata file. * Gets the NBT data from the player-data file.
* It will not work if the player is online, because the data on the file are not synchronized with real-time values. * It will not work if the player is online, because the data on the file are not synchronized with real-time values.
* @param convertTag true to convert the data to the current MC version, false to keep the saved version * @param convertTag true to convert the data to the current MC version, false to keep the saved version
* @return the NBT data from the playerdata file. * @return the NBT data from the player-data file.
* @throws IllegalStateException if the player is online. * @throws IllegalStateException if the player is online.
*/ */
default CompoundTag getPlayerData(boolean convertTag) { default CompoundTag getPlayerData(boolean convertTag) {
@ -173,9 +173,9 @@ public interface PaperOffPlayer extends AbstractOffPlayer {
} }
/** /**
* Gets a wrapper for the NBT data from the playerdata file. * Gets a wrapper for the NBT data from the player-data file.
* It will not work if the player is online, because the data on the file are not synchronized with real-time values. * It will not work if the player is online, because the data on the file are not synchronized with real-time values.
* @return the NBT data from the playerdata file. * @return the NBT data from the player-data file.
* @throws IllegalStateException if the player is online. * @throws IllegalStateException if the player is online.
*/ */
default PlayerDataWrapper getPlayerDataWrapper() { default PlayerDataWrapper getPlayerDataWrapper() {
@ -183,7 +183,7 @@ public interface PaperOffPlayer extends AbstractOffPlayer {
} }
/** /**
* Saves the provided NBT data to the playerdata file. * Saves the provided NBT data to the player-data file.
* It will not work if the player is online, because the provided data will be lost when the player disconnects. * It will not work if the player is online, because the provided data will be lost when the player disconnects.
* @param data the data to save. * @param data the data to save.
* @throws IllegalStateException if the player is online. * @throws IllegalStateException if the player is online.
@ -195,14 +195,14 @@ public interface PaperOffPlayer extends AbstractOffPlayer {
File file = getPlayerDataFile(false); File file = getPlayerDataFile(false);
File old = getPlayerDataFile(true); File old = getPlayerDataFile(true);
old.delete(); old.delete();
Files.move(file, old); Files.move(file.toPath(), old.toPath());
NbtIo.writeCompressed(data.data, file); NbtIo.writeCompressed(data.data, file);
} }
/** /**
* Gets the file where the playerdata is stored. * Gets the file where the player-data is stored.
* @param old true to return the path of old data, false to return the actual file. * @param old true to return the path of old data, false to return the actual file.
* @return the file where the playerdata is stored. * @return the file where the player-data is stored.
*/ */
default File getPlayerDataFile(boolean old) { default File getPlayerDataFile(boolean old) {
File playerDataDir = new File(WorldUtil.worldDir(PrimaryWorlds.PRIMARY_WORLDS.get(0)), "playerdata"); File playerDataDir = new File(WorldUtil.worldDir(PrimaryWorlds.PRIMARY_WORLDS.get(0)), "playerdata");

View File

@ -97,7 +97,7 @@ public interface PaperOnlinePlayer extends PaperOffPlayer, AbstractOnlinePlayer
* Play a sound on this players client, sourced at this players location. * Play a sound on this players client, sourced at this players location.
* @param sound the sound to play * @param sound the sound to play
* @param volume the volume of the sound. * @param volume the volume of the sound.
* @param pitch the pich in which the sound is played. * @param pitch the pitch in which the sound is played.
*/ */
default void playSound(Sound sound, float volume, float pitch) { default void playSound(Sound sound, float volume, float pitch) {
playSound(sound, getBukkitPlayer().getLocation(), volume, pitch); playSound(sound, getBukkitPlayer().getLocation(), volume, pitch);
@ -108,7 +108,7 @@ public interface PaperOnlinePlayer extends PaperOffPlayer, AbstractOnlinePlayer
* @param sound the sound to play * @param sound the sound to play
* @param location the source location of the sound. * @param location the source location of the sound.
* @param volume the volume of the sound. * @param volume the volume of the sound.
* @param pitch the pich in which the sound is played. * @param pitch the pitch in which the sound is played.
*/ */
default void playSound(Sound sound, Location location, float volume, float pitch) { default void playSound(Sound sound, Location location, float volume, float pitch) {
getBukkitPlayer().playSound(location, sound, volume, pitch); getBukkitPlayer().playSound(location, sound, volume, pitch);

View File

@ -18,12 +18,12 @@ import java.util.stream.Collectors;
public class PaperPlayerConfigStorage { public class PaperPlayerConfigStorage {
static File storageFile = new File(PandaLibPaper.getPlugin().getDataFolder(), "playerdata.yml"); static final File storageFile = new File(PandaLibPaper.getPlugin().getDataFolder(), "playerdata.yml");
static boolean initialized = false; static boolean initialized = false;
static LinkedHashMap<ConfigKey, ConfigEntry> data = new LinkedHashMap<>(); static final LinkedHashMap<ConfigKey, ConfigEntry> data = new LinkedHashMap<>();
static LinkedHashMap<UUID, LinkedHashSet<ConfigEntry>> playerSortedData = new LinkedHashMap<>(); static final LinkedHashMap<UUID, LinkedHashSet<ConfigEntry>> playerSortedData = new LinkedHashMap<>();
static LinkedHashMap<String, LinkedHashSet<ConfigEntry>> keySortedData = new LinkedHashMap<>(); static final LinkedHashMap<String, LinkedHashSet<ConfigEntry>> keySortedData = new LinkedHashMap<>();
static boolean changed = false; static boolean changed = false;
@ -196,10 +196,6 @@ public class PaperPlayerConfigStorage {
return value; return value;
} }
private void setValue(String value) {
this.value = value;
}
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(playerId, key); return Objects.hash(playerId, key);

View File

@ -79,7 +79,7 @@ public class PlayerNonPersistentConfig {
} }
public static class ExpiresTick extends Expiration { public static class ExpiresTick extends Expiration {
long expirationTick; final long expirationTick;
public ExpiresTick(long expirationDelayTick) { public ExpiresTick(long expirationDelayTick) {
expirationTick = tick + expirationDelayTick; expirationTick = tick + expirationDelayTick;

View File

@ -68,7 +68,7 @@ public class NMSReflect {
OBF_NAMESPACE = (String) obfHelperClass.field("SPIGOT_NAMESPACE").getStaticValue(); OBF_NAMESPACE = (String) obfHelperClass.field("SPIGOT_NAMESPACE").getStaticValue();
MOJ_NAMESPACE = (String) obfHelperClass.field("MOJANG_PLUS_YARN_NAMESPACE").getStaticValue(); MOJ_NAMESPACE = (String) obfHelperClass.field("MOJANG_PLUS_YARN_NAMESPACE").getStaticValue();
} catch (ReflectiveOperationException e) { } catch (ReflectiveOperationException e) {
throw new ReflectiveOperationException("Unable to find the Paper ofbuscation mapping class or class members.", e); throw new ReflectiveOperationException("Unable to find the Paper obfuscation mapping class or class members.", e);
} }
List<ClassMapping> mappings = loadMappings(obfHelperClass); List<ClassMapping> mappings = loadMappings(obfHelperClass);
@ -165,7 +165,7 @@ public class NMSReflect {
private static List<ClassMapping> loadMappings(ReflectClass<?> obfHelperClass) throws IOException { private static List<ClassMapping> loadMappings(ReflectClass<?> obfHelperClass) throws IOException {
try (final InputStream mappingsInputStream = obfHelperClass.get().getClassLoader().getResourceAsStream("META-INF/mappings/reobf.tiny")) { try (final InputStream mappingsInputStream = obfHelperClass.get().getClassLoader().getResourceAsStream("META-INF/mappings/reobf.tiny")) {
if (mappingsInputStream == null) { if (mappingsInputStream == null) {
throw new RuntimeException("Unable to find the ofbuscation mapping file in the Paper jar."); throw new RuntimeException("Unable to find the obfuscation mapping file in the Paper jar.");
} }
MemoryMappingTree tree = new MemoryMappingTree(); MemoryMappingTree tree = new MemoryMappingTree();
@ -290,7 +290,7 @@ public class NMSReflect {
/** /**
* Represents the mapping between the obfuscated and mojang names of a class and all its members. * Represents the mapping between the obfuscated and Mojang names of a class and all its members.
*/ */
public static class ClassMapping { public static class ClassMapping {
private static int nextID = 0; private static int nextID = 0;
@ -463,9 +463,9 @@ public class NMSReflect {
private List<NMSTypeWrapper> superInterfaces(boolean obf) { private List<NMSTypeWrapper> superInterfaces(boolean obf) {
Class<?>[] interfaces = runtimeClass().getInterfaces(); Class<?>[] interfaces = runtimeClass().getInterfaces();
List<NMSTypeWrapper> types = new ArrayList<>(interfaces.length); List<NMSTypeWrapper> types = new ArrayList<>(interfaces.length);
for (Class<?> interfce : interfaces) { for (Class<?> i : interfaces) {
ClassMapping cm = (IS_SERVER_OBFUSCATED ? CLASSES_BY_OBF : CLASSES_BY_MOJ).get(interfce.getName()); ClassMapping cm = (IS_SERVER_OBFUSCATED ? CLASSES_BY_OBF : CLASSES_BY_MOJ).get(i.getName());
types.add((cm != null) ? cm.toType(obf) : NMSTypeWrapper.of(interfce)); types.add((cm != null) ? cm.toType(obf) : NMSTypeWrapper.of(i));
} }
return types; return types;
} }

View File

@ -25,7 +25,7 @@ public class OBCReflect {
/** /**
* Returns the OBC class that has the provided name, wrapped into a {@link ReflectClass}. * Returns the OBC class that has the provided name, wrapped into a {@link ReflectClass}.
* @param obcClass the name of the class, including the subpackage in whitch the requested class is. This parameter * @param obcClass the name of the class, including the subpackage in which the requested class is. This parameter
* will be prefixed with the {@code OBC} package and the current package version. * will be prefixed with the {@code OBC} package and the current package version.
* @return the OBC class that has the provided name, wrapped into a {@link ReflectClass}. * @return the OBC class that has the provided name, wrapped into a {@link ReflectClass}.
* @throws ClassNotFoundException if the provided class was not found in {@code OBC} package. * @throws ClassNotFoundException if the provided class was not found in {@code OBC} package.

View File

@ -79,14 +79,14 @@ import fr.pandacube.lib.util.ThrowableAccumulator;
import static fr.pandacube.lib.reflect.wrapper.WrapperRegistry.initWrapper; import static fr.pandacube.lib.reflect.wrapper.WrapperRegistry.initWrapper;
/** /**
* Initializer for all the reflect tools in {@code pandalib-paper-reflect} module. * Initializer for all the reflection tools in {@code pandalib-paper-reflect} module.
*/ */
public class PandalibPaperReflect { public class PandalibPaperReflect {
private static boolean isInit = false; private static boolean isInit = false;
/** /**
* Initializes the reflect tools in {@code pandalib-paper-reflect} module. * Initializes the reflection tools in {@code pandalib-paper-reflect} module.
* @throws Exception if a problem occurs when initializing wrapper classes. * @throws Exception if a problem occurs when initializing wrapper classes.
*/ */
public static void init() throws Exception { public static void init() throws Exception {
@ -117,7 +117,7 @@ public class PandalibPaperReflect {
thAcc.catchThrowable(() -> initWrapper(RenderData.class, RenderData.REFLECT.get())); thAcc.catchThrowable(() -> initWrapper(RenderData.class, RenderData.REFLECT.get()));
thAcc.catchThrowable(() -> initWrapper(VanillaCommandWrapper.class, VanillaCommandWrapper.REFLECT.get())); thAcc.catchThrowable(() -> initWrapper(VanillaCommandWrapper.class, VanillaCommandWrapper.REFLECT.get()));
// dataconverter // data-converter
thAcc.catchThrowable(() -> initWrapper(MCDataConverter.class, MCDataConverter.REFLECT.get())); thAcc.catchThrowable(() -> initWrapper(MCDataConverter.class, MCDataConverter.REFLECT.get()));
thAcc.catchThrowable(() -> initWrapper(MCDataType.class, MCDataType.REFLECT.get())); thAcc.catchThrowable(() -> initWrapper(MCDataType.class, MCDataType.REFLECT.get()));
thAcc.catchThrowable(() -> initWrapper(MCTypeRegistry.class, MCTypeRegistry.REFLECT.get())); thAcc.catchThrowable(() -> initWrapper(MCTypeRegistry.class, MCTypeRegistry.REFLECT.get()));
@ -204,7 +204,7 @@ public class PandalibPaperReflect {
thAcc.catchThrowable(() -> initWrapper(QueuedChangesMapLong2Object.class, QueuedChangesMapLong2Object.REFLECT.get())); thAcc.catchThrowable(() -> initWrapper(QueuedChangesMapLong2Object.class, QueuedChangesMapLong2Object.REFLECT.get()));
thAcc.throwCatched(); thAcc.throwCaught();
} }
} }

View File

@ -22,7 +22,7 @@ public final class BedrockBambooCollisionFixer implements Listener {
// Make the bamboo block have zero collision. // Make the bamboo block have zero collision.
try { try {
BambooStalkBlock.COLLISION_SHAPE(new AABBVoxelShape(new AABB(0.5, 0, 0.5, 0.5, 0, 0.5))); BambooStalkBlock.COLLISION_SHAPE(new AABBVoxelShape(new AABB(0.5, 0, 0.5, 0.5, 0, 0.5)));
Log.info("Bamboo block collision box removed succesfully."); Log.info("Bamboo block collision box removed successfully.");
} catch (Exception e) { } catch (Exception e) {
Log.severe("Unable to remove the collision box of the Bamboo block.", e); Log.severe("Unable to remove the collision box of the Bamboo block.", e);
return; return;

View File

@ -2,14 +2,10 @@ package fr.pandacube.lib.paper.reflect.wrapper.craftbukkit;
import fr.pandacube.lib.paper.reflect.OBCReflect; import fr.pandacube.lib.paper.reflect.OBCReflect;
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.nbt.CompoundTag; import fr.pandacube.lib.paper.reflect.wrapper.minecraft.nbt.CompoundTag;
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.world.MapItemSavedData;
import fr.pandacube.lib.reflect.ReflectClass; import fr.pandacube.lib.reflect.ReflectClass;
import fr.pandacube.lib.reflect.ReflectField;
import fr.pandacube.lib.reflect.ReflectMethod; import fr.pandacube.lib.reflect.ReflectMethod;
import fr.pandacube.lib.reflect.wrapper.ReflectWrapperTyped; import fr.pandacube.lib.reflect.wrapper.ReflectWrapperTyped;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.map.MapView;
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,12 +19,12 @@ import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
public class VanillaCommandWrapper extends ReflectWrapperTyped<BukkitCommand> { public class VanillaCommandWrapper extends ReflectWrapperTyped<BukkitCommand> {
public static final ReflectClass<?> REFLECT = wrapEx(() -> OBCReflect.ofClass("command.VanillaCommandWrapper")); public static final ReflectClass<?> REFLECT = wrapEx(() -> OBCReflect.ofClass("command.VanillaCommandWrapper"));
public static final ReflectConstructor<?> CONSTRUTOR = wrapEx(() -> REFLECT.constructor(Commands.MAPPING.runtimeClass(), CommandNode.class)); public static final ReflectConstructor<?> CONSTRUCTOR = wrapEx(() -> REFLECT.constructor(Commands.MAPPING.runtimeClass(), CommandNode.class));
public static final ReflectField<?> vanillaCommand = wrapEx(() -> REFLECT.field("vanillaCommand")); public static final ReflectField<?> vanillaCommand = wrapEx(() -> REFLECT.field("vanillaCommand"));
public static final ReflectMethod<?> getListener = wrapEx(() -> REFLECT.method("getListener", CommandSender.class)); public static final ReflectMethod<?> getListener = wrapEx(() -> REFLECT.method("getListener", CommandSender.class));
public VanillaCommandWrapper(Commands dispatcher, CommandNode<BukkitBrigadierCommandSource> vanillaCommand) { public VanillaCommandWrapper(Commands dispatcher, CommandNode<BukkitBrigadierCommandSource> vanillaCommand) {
this(wrapReflectEx(() -> CONSTRUTOR.instanciate(unwrap(dispatcher), vanillaCommand))); this(wrapReflectEx(() -> CONSTRUCTOR.instantiate(unwrap(dispatcher), vanillaCommand)));
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")

View File

@ -1,7 +1,6 @@
package fr.pandacube.lib.paper.reflect.wrapper.dataconverter; package fr.pandacube.lib.paper.reflect.wrapper.dataconverter;
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.nbt.CompoundTag; import fr.pandacube.lib.paper.reflect.wrapper.minecraft.nbt.CompoundTag;
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.network.chat.Component;
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;

View File

@ -57,7 +57,7 @@ public class CompoundTag extends ReflectWrapper implements Tag {
private static final ReflectMethod<?> containsStringInt = wrapEx(() -> MAPPING.mojMethod("contains", String.class, int.class)); private static final ReflectMethod<?> containsStringInt = wrapEx(() -> MAPPING.mojMethod("contains", String.class, int.class));
public CompoundTag() { public CompoundTag() {
this(wrapReflectEx(() -> CONSTRUCTOR.instanciate())); this(wrapReflectEx(() -> CONSTRUCTOR.instantiate()));
} }
protected CompoundTag(Object nms) { protected CompoundTag(Object nms) {
@ -167,7 +167,7 @@ public class CompoundTag extends ReflectWrapper implements Tag {
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public Map<String, ?> entries() { public Map<String, ?> entries() {
// we cannot easily wrap every value of the map without being able to synch the returned map with the wrapped map // we cannot easily wrap every value of the map without being able to synchronize the returned map with the wrapped map
return (Map<String, ?>) wrapReflectEx(() -> entries.invoke(__getRuntimeInstance())); return (Map<String, ?>) wrapReflectEx(() -> entries.invoke(__getRuntimeInstance()));
} }
public int size() { public int size() {

View File

@ -4,7 +4,6 @@ import fr.pandacube.lib.paper.reflect.NMSReflect;
import fr.pandacube.lib.paper.reflect.NMSReflect.ClassMapping; import fr.pandacube.lib.paper.reflect.NMSReflect.ClassMapping;
import fr.pandacube.lib.reflect.ReflectConstructor; import fr.pandacube.lib.reflect.ReflectConstructor;
import fr.pandacube.lib.reflect.ReflectMethod; import fr.pandacube.lib.reflect.ReflectMethod;
import fr.pandacube.lib.reflect.wrapper.ReflectWrapper;
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;
@ -19,7 +18,7 @@ public class ListTag extends CollectionTag {
} }
public ListTag() { public ListTag() {
this(wrapReflectEx(() -> CONSTRUCTOR.instanciate())); this(wrapReflectEx(() -> CONSTRUCTOR.instantiate()));
} }
protected ListTag(Object nms) { protected ListTag(Object nms) {

View File

@ -14,7 +14,7 @@ public class FriendlyByteBuf extends ByteBuf {
private static final ReflectMethod<?> writeUtf = wrapEx(() -> MAPPING.mojMethod("writeUtf", String.class)); private static final ReflectMethod<?> writeUtf = wrapEx(() -> MAPPING.mojMethod("writeUtf", String.class));
public FriendlyByteBuf(ByteBuf parent) { public FriendlyByteBuf(ByteBuf parent) {
this(wrapReflectEx(() -> CONSTRUCTOR.instanciate(unwrap(parent)))); this(wrapReflectEx(() -> CONSTRUCTOR.instantiate(unwrap(parent))));
} }
public FriendlyByteBuf writeUtf(String string) { public FriendlyByteBuf writeUtf(String string) {

View File

@ -24,6 +24,6 @@ public class ClientboundCustomPayloadPacket extends ReflectWrapper implements Pa
} }
public ClientboundCustomPayloadPacket(ResourceLocation res, FriendlyByteBuf buff) { public ClientboundCustomPayloadPacket(ResourceLocation res, FriendlyByteBuf buff) {
this(wrapReflectEx(() -> CONSTRUCTOR.instanciate(unwrap(res), unwrap(buff)))); this(wrapReflectEx(() -> CONSTRUCTOR.instantiate(unwrap(res), unwrap(buff))));
} }
} }

View File

@ -22,7 +22,7 @@ public class ClientboundGameEventPacket extends ReflectWrapper implements Packet
} }
public ClientboundGameEventPacket(Type type, float value) { public ClientboundGameEventPacket(Type type, float value) {
this(wrapReflectEx(() -> CONSTRUCTOR.instanciate(unwrap(type), value))); this(wrapReflectEx(() -> CONSTRUCTOR.instantiate(unwrap(type), value)));
} }
protected ClientboundGameEventPacket(Object obj) { protected ClientboundGameEventPacket(Object obj) {

View File

@ -1,7 +1,6 @@
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.server; package fr.pandacube.lib.paper.reflect.wrapper.minecraft.server;
import fr.pandacube.lib.paper.reflect.NMSReflect; import fr.pandacube.lib.paper.reflect.NMSReflect;
import fr.pandacube.lib.reflect.wrapper.ReflectWrapper;
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx; import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;

View File

@ -12,7 +12,7 @@ public class AABB extends ReflectWrapper {
private static final ReflectConstructor<?> CONSTRUCTOR = wrapEx(() -> MAPPING.runtimeReflect().constructor(double.class, double.class, double.class, double.class, double.class, double.class)); private static final ReflectConstructor<?> CONSTRUCTOR = wrapEx(() -> MAPPING.runtimeReflect().constructor(double.class, double.class, double.class, double.class, double.class, double.class));
public AABB(double x1, double y1, double z1, double x2, double y2, double z2) { public AABB(double x1, double y1, double z1, double x2, double y2, double z2) {
this(wrapReflectEx(() -> CONSTRUCTOR.instanciate(x1, y1, z1, x2, y2, z2))); this(wrapReflectEx(() -> CONSTRUCTOR.instantiate(x1, y1, z1, x2, y2, z2)));
} }
protected AABB(Object obj) { protected AABB(Object obj) {

View File

@ -12,7 +12,7 @@ public class ChunkPos extends ReflectWrapper {
public static final ReflectConstructor<?> CONSTRUCTOR = wrapEx(() -> MAPPING.runtimeReflect().constructor(int.class, int.class)); public static final ReflectConstructor<?> CONSTRUCTOR = wrapEx(() -> MAPPING.runtimeReflect().constructor(int.class, int.class));
public ChunkPos(int x, int z) { public ChunkPos(int x, int z) {
this(wrapReflectEx(() -> CONSTRUCTOR.instanciate(x, z))); this(wrapReflectEx(() -> CONSTRUCTOR.instantiate(x, z)));
} }
protected ChunkPos(Object obj) { protected ChunkPos(Object obj) {

View File

@ -2,10 +2,8 @@ package fr.pandacube.lib.paper.reflect.wrapper.minecraft.world;
import fr.pandacube.lib.paper.reflect.NMSReflect; import fr.pandacube.lib.paper.reflect.NMSReflect;
import fr.pandacube.lib.reflect.wrapper.ReflectWrapper; import fr.pandacube.lib.reflect.wrapper.ReflectWrapper;
import fr.pandacube.lib.reflect.ReflectField;
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx; import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
public class DamageSource extends ReflectWrapper { public class DamageSource extends ReflectWrapper {
public static final NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.world.damagesource.DamageSource")); public static final NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.world.damagesource.DamageSource"));

View File

@ -1,11 +1,9 @@
package fr.pandacube.lib.paper.reflect.wrapper.minecraft.world; package fr.pandacube.lib.paper.reflect.wrapper.minecraft.world;
import fr.pandacube.lib.paper.reflect.NMSReflect; import fr.pandacube.lib.paper.reflect.NMSReflect;
import fr.pandacube.lib.reflect.ReflectField;
import fr.pandacube.lib.reflect.wrapper.ReflectWrapper; import fr.pandacube.lib.reflect.wrapper.ReflectWrapper;
import static fr.pandacube.lib.util.ThrowableUtil.wrapEx; import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx;
public class DamageSources extends ReflectWrapper { public class DamageSources extends ReflectWrapper {
public static final NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.world.damagesource.DamageSources")); public static final NMSReflect.ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.world.damagesource.DamageSources"));

View File

@ -2,8 +2,6 @@ package fr.pandacube.lib.paper.reflect.wrapper.minecraft.world;
import fr.pandacube.lib.paper.reflect.NMSReflect; import fr.pandacube.lib.paper.reflect.NMSReflect;
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.nbt.CompoundTag; import fr.pandacube.lib.paper.reflect.wrapper.minecraft.nbt.CompoundTag;
import fr.pandacube.lib.paper.reflect.wrapper.paper.configuration.WorldConfiguration;
import fr.pandacube.lib.reflect.ReflectField;
import fr.pandacube.lib.reflect.ReflectMethod; import fr.pandacube.lib.reflect.ReflectMethod;
import fr.pandacube.lib.reflect.wrapper.ReflectWrapper; import fr.pandacube.lib.reflect.wrapper.ReflectWrapper;

View File

@ -14,7 +14,7 @@ public class AABBVoxelShape extends VoxelShape {
private static final ReflectConstructor<?> CONSTRUCTOR = wrapEx(() -> REFLECT.constructor(AABB.MAPPING.runtimeClass())); private static final ReflectConstructor<?> CONSTRUCTOR = wrapEx(() -> REFLECT.constructor(AABB.MAPPING.runtimeClass()));
public AABBVoxelShape(AABB aabb) { public AABBVoxelShape(AABB aabb) {
this(wrapReflectEx(() -> CONSTRUCTOR.instanciate(unwrap(aabb)))); this(wrapReflectEx(() -> CONSTRUCTOR.instantiate(unwrap(aabb))));
} }
protected AABBVoxelShape(Object obj) { protected AABBVoxelShape(Object obj) {

View File

@ -1,15 +1,11 @@
package fr.pandacube.lib.paper.scheduler; package fr.pandacube.lib.paper.scheduler;
import java.util.ArrayList; import fr.pandacube.lib.paper.PandaLibPaper;
import java.util.List;
import java.util.Objects;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scheduler.BukkitTask; import org.bukkit.scheduler.BukkitTask;
import fr.pandacube.lib.paper.PandaLibPaper; import java.util.Objects;
/** /**
* An extension of {@link BukkitRunnable} that already integrates a reference to the Bukkit plugin. * An extension of {@link BukkitRunnable} that already integrates a reference to the Bukkit plugin.
@ -21,13 +17,13 @@ public class PandalibRunnable extends BukkitRunnable {
/** /**
* Instanciate a {@link PandalibRunnable}, whose {@link #run()} method will be called by the server scheduler. * Instantiate a {@link PandalibRunnable}, whose {@link #run()} method will be called by the server scheduler.
* When using this default constructor, the {@link #run()} method must be override to provides code to run. * When using this default constructor, the {@link #run()} method must be overridden to provide code to run.
*/ */
protected PandalibRunnable() { } protected PandalibRunnable() { }
/** /**
* Instanciate a {@link PandalibRunnable}, with an {@code updater} that will be called by the server scheduler. * Instantiate a {@link PandalibRunnable}, with an {@code updater} that will be called by the server scheduler.
* @param updater the updater to run when this task is executed. * @param updater the updater to run when this task is executed.
*/ */
public PandalibRunnable(Runnable updater) { public PandalibRunnable(Runnable updater) {

Some files were not shown because too many files have changed in this diff Show More