Compare commits
2 Commits
69b72ef90d
...
5edd8cdfec
Author | SHA1 | Date | |
---|---|---|---|
5edd8cdfec | |||
c984b63cee |
@ -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 didn’t 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
|
||||||
|
|
||||||
|
@ -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<>();
|
||||||
|
@ -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
|
if (new File(getSourceDir(), "logs").equals(file))
|
||||||
public boolean test(File file, String path) {
|
return false;
|
||||||
if (new File(getSourceDir(), "logs").equals(file))
|
if (file.isFile() && file.getName().endsWith(".lck"))
|
||||||
return false;
|
return false;
|
||||||
if (file.isFile() && file.getName().endsWith(".lck"))
|
return BungeeWorkdirProcess.super.getFilenameFilter().test(file, path);
|
||||||
return false;
|
|
||||||
return BungeeWorkdirProcess.super.getFilenameFilter().test(file, path);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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 player’s client.
|
|
||||||
* @return the minecraft version of this player’s client.
|
|
||||||
* @deprecated use {@link #getProtocolVersion()} instead.
|
|
||||||
*/
|
|
||||||
@Deprecated(forRemoval = true)
|
|
||||||
default MinecraftVersion getMinecraftVersion() {
|
|
||||||
return MinecraftVersion.getVersion(getBungeeProxiedPlayer().getPendingConnection().getVersion());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the protocol version of this player’s client.
|
* Gets the protocol version of this player’s client.
|
||||||
* @return the protocol version of this player’s client.
|
* @return the protocol version of this player’s client.
|
||||||
|
@ -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")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
|
@ -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) { }
|
||||||
|
@ -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) {
|
||||||
|
@ -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. */
|
||||||
|
@ -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)
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
@ -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 doesn’t 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 it’s in game chat.
|
* @param console true if the progress bar is intended to be displayed on the console, false if it’s in game chat.
|
||||||
|
@ -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 Jline’s {@link ConsoleReader} for the
|
* Class to handle general standard IO operation for a CLI application. It uses Jline’s {@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);
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
@ -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();
|
||||||
|
@ -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) {
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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) {
|
||||||
|
@ -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];
|
||||||
|
@ -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) {
|
||||||
|
@ -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 don’t like.
|
* Utility methods to replace some functionalities of Brigadier, especially suggestion sorting that we don’t like.
|
||||||
*/
|
*/
|
||||||
public class BrigadierSuggestionsUtil {
|
public class BrigadierSuggestionsUtil {
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
@ -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 + "...");
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
@ -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 + " doesn’t exist");
|
Log.warning("[Backup] Unable to compress " + ChatColor.GRAY + getDisplayName() + ChatColor.RESET + ": source directory " + sourceDir + " doesn't exist");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
@ -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");
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
@ -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());
|
||||||
|
@ -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}.
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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, <0 if v1<v2 and vice-versa.
|
* @return 0 if they are equal, <0 if v1<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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
MinecraftVersionList data = Json.gson.fromJson(isr, MinecraftVersionList.class);
|
try (InputStreamReader isr = new InputStreamReader(is)) {
|
||||||
versionList.set(data);
|
MinecraftVersionList data = Json.gson.fromJson(isr, MinecraftVersionList.class);
|
||||||
|
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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
|
||||||
|
@ -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 it’s an unique auto-incremented
|
* This is not good practice to set the {@code id} field of any entry, because it’s 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 doesn’t 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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 field’s Java type.
|
* @param <T> the field’s 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 table’s entries.
|
* @return a map of the foreign key values, mapped to the foreign table’s entries.
|
||||||
* @param <T> the field’s Java type.
|
* @param <T> the field’s 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 table’s entries which the provided foreign key is targeting the entries of this list, and
|
* Gets all the original table’s 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 table’s entries which the provided foreign key is targeting the entries of this list.
|
* @return the original table’s 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 table’s entries which the provided foreign key is targeting the entries of this list,
|
* Gets all the original table’s 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 table’s entries.
|
* @return a map of the foreign key values, mapped to the orignal table’s entries.
|
||||||
* @throws DBException if an error occurs when interacting with the database.
|
* @throws DBException if an error occurs when interacting with the database.
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
@ -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.
|
|
||||||
|
|
||||||
It’s still in development (actually not touched since years), and it’s 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
|
|
@ -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>
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -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();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -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]);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
|
|
||||||
}
|
|
@ -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 + "}";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -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 + "}";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -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);
|
|
||||||
|
|
||||||
}
|
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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>
|
||||||
|
@ -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) {
|
||||||
|
@ -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 don’t want that.
|
* and we don’t want that.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -143,7 +134,7 @@ import fr.pandacube.lib.util.Log;
|
|||||||
public boolean hasPermission(String permission)
|
public boolean hasPermission(String permission)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* WARNING: don’t call PermissibleOnlinePlayer#hasPermission(String) here or it will result on a stack overflow
|
* WARNING: don’t 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); // doesn’t 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,36 +205,34 @@ 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 {
|
||||||
|
return effectivePermissionsListCache.get(world, () -> {
|
||||||
|
// first get the superperms effective permissions (that take isOp into account)
|
||||||
|
Map<String, PermissionAttachmentInfo> perms = oldPermissible.getEffectivePermissions().stream()
|
||||||
|
.collect(Collectors.toMap(PermissionAttachmentInfo::getPermission, Function.identity()));
|
||||||
|
|
||||||
|
// then override them with the permissions from our permission system (that has priority, and take current world into account)
|
||||||
|
for (Map.Entry<String, Boolean> permE : getEffectivePermissionsOnServerInWorld().entrySet()) {
|
||||||
|
perms.put(permE.getKey(), new PermissionAttachmentInfo(this, permE.getKey(), null, permE.getValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new LinkedHashSet<>(perms.values());
|
||||||
|
});
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
Log.severe(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
|
||||||
return effectivePermissionsListCache.get(world, () -> {
|
|
||||||
// first get the superperms effective permissions (taht take isOp into accound)
|
|
||||||
Map<String, PermissionAttachmentInfo> perms = oldPermissible.getEffectivePermissions().stream()
|
|
||||||
.collect(Collectors.toMap(PermissionAttachmentInfo::getPermission, Function.identity()));
|
|
||||||
|
|
||||||
// then override them with the permissions from our permission system (that has priority, and take current world into account)
|
return oldPermissible.getEffectivePermissions();
|
||||||
for (Map.Entry<String, Boolean> permE : getEffectivePermissionsOnServerInWorld().entrySet()) {
|
|
||||||
perms.put(permE.getKey(), new PermissionAttachmentInfo(this, permE.getKey(), null, permE.getValue()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return new LinkedHashSet<>(perms.values());
|
|
||||||
});
|
|
||||||
} catch (ExecutionException e) {
|
|
||||||
Log.severe(e);
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
@ -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));
|
||||||
|
@ -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,17 +11,14 @@ public class PaperWorkdirProcess extends PaperBackupProcess {
|
|||||||
|
|
||||||
|
|
||||||
public BiPredicate<File, String> getFilenameFilter() {
|
public BiPredicate<File, String> getFilenameFilter() {
|
||||||
return new BiPredicate<File, String>() {
|
return (file, path) -> {
|
||||||
@Override
|
if (file.isDirectory() && new File(file, "level.dat").exists())
|
||||||
public boolean test(File file, String path) {
|
return false;
|
||||||
if (file.isDirectory() && new File(file, "level.dat").exists())
|
if (new File(getSourceDir(), "logs").equals(file))
|
||||||
return false;
|
return false;
|
||||||
if (new File(getSourceDir(), "logs").equals(file))
|
if (file.isFile() && file.getName().endsWith(".lck"))
|
||||||
return false;
|
return false;
|
||||||
if (file.isFile() && file.getName().endsWith(".lck"))
|
return PaperWorkdirProcess.super.getFilenameFilter().test(file, path);
|
||||||
return false;
|
|
||||||
return PaperWorkdirProcess.super.getFilenameFilter().test(file, path);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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. Don’t need to register again
|
// this command is already registered in NMS. Don’t 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,
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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");
|
||||||
|
@ -97,7 +97,7 @@ public interface PaperOnlinePlayer extends PaperOffPlayer, AbstractOnlinePlayer
|
|||||||
* Play a sound on this player’s client, sourced at this player’s location.
|
* Play a sound on this player’s client, sourced at this player’s 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);
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
|
@ -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();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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")
|
||||||
|
@ -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;
|
||||||
|
@ -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() {
|
||||||
|
@ -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) {
|
||||||
|
@ -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) {
|
||||||
|
@ -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))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
@ -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) {
|
||||||
|
@ -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"));
|
||||||
|
@ -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"));
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
@ -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
Loading…
Reference in New Issue
Block a user