Compare commits

..

2 Commits

Author SHA1 Message Date
e7b528718c Update paper plugin to MC 1.20.6
- Convert Brigadier command to use the new Brigadier/Paper API
- EquipmentSlot now has BODY value for horses and wolves armor
- ItemMeta’ canPlaceOn and canDestroy does not work anymore. Removed the related methods from ItemStackBuilder
- Enchantment DURABILITY now has the proper vanilla name UNBREAKING
- Pandalib-chat now uses Adventure’s TranslationArgument
2024-06-07 00:05:07 +02:00
d411618e63 Fix Javadoc warnings due to Java 21 update (+ some other warnings)
The default implicit constructor must also have a doc comment, so I have to make it explicit and either properly restrict the visibility of the constructor, or actually document it.
2024-06-06 23:59:32 +02:00
62 changed files with 306 additions and 432 deletions

View File

@ -25,7 +25,6 @@ import java.util.function.Function;
*/ */
public class PandalibBungeePermissions implements Listener { public class PandalibBungeePermissions implements Listener {
/** /**
* Registers event listener to redirect permission checks to {@code pandalib-permissions}. * Registers event listener to redirect permission checks to {@code pandalib-permissions}.
* @param bungeePlugin a BungeeCord plugin. * @param bungeePlugin a BungeeCord plugin.
@ -35,6 +34,8 @@ public class PandalibBungeePermissions implements Listener {
} }
private PandalibBungeePermissions() {}
/** /**
* Event handler called when a plugin asks if a player has a permission. * Event handler called when a plugin asks if a player has a permission.
* @param event the permission check event. * @param event the permission check event.

View File

@ -43,4 +43,7 @@ public class PandaLibBungee {
public static Plugin getPlugin() { public static Plugin getPlugin() {
return plugin; return plugin;
} }
private PandaLibBungee() {}
} }

View File

@ -35,4 +35,11 @@ public class BungeeBackupConfig {
* A list of ignored files or directory in the workdir to exclude from the backup. * A list of ignored files or directory in the workdir to exclude from the backup.
*/ */
public List<String> workdirIgnoreList = new ArrayList<>(); public List<String> workdirIgnoreList = new ArrayList<>();
/**
* Creates a new {@link BungeeBackupConfig}.
*/
public BungeeBackupConfig() {
}
} }

View File

@ -5,6 +5,8 @@ import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.ComponentBuilder; import net.kyori.adventure.text.ComponentBuilder;
import net.kyori.adventure.text.ComponentLike; import net.kyori.adventure.text.ComponentLike;
import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.TranslationArgument;
import net.kyori.adventure.text.TranslationArgumentLike;
import net.kyori.adventure.text.event.ClickEvent; import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.event.HoverEvent; import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.event.HoverEventSource; import net.kyori.adventure.text.event.HoverEventSource;
@ -972,21 +974,38 @@ public abstract sealed class Chat extends ChatStatic implements HoverEventSource
/* package */ static ComponentLike filterObjToComponentLike(Object v) {
return switch (v) {
case BaseComponent[] baseComponents -> toAdventure(baseComponents);
case BaseComponent baseComponent -> toAdventure(baseComponent);
case ComponentLike componentLike -> componentLike;
case null, default -> Component.text(Objects.toString(v));
};
}
/* package */ static ComponentLike[] filterObjToComponentLike(Object[] values) { /* package */ static ComponentLike[] filterObjToComponentLike(Object[] values) {
if (values == null) if (values == null)
return null; return null;
ComponentLike[] ret = new ComponentLike[values.length]; ComponentLike[] ret = new ComponentLike[values.length];
for (int i = 0; i < values.length; i++) {
ret[i] = filterObjToComponentLike(values[i]);
}
return ret;
}
/* package */ static TranslationArgumentLike[] filterObjToTranslationArgumentLike(Object[] values) {
if (values == null)
return null;
TranslationArgumentLike[] ret = new TranslationArgumentLike[values.length];
for (int i = 0; i < values.length; i++) { for (int i = 0; i < values.length; i++) {
Object v = values[i]; Object v = values[i];
if (v instanceof BaseComponent[]) if (v instanceof Number n)
ret[i] = toAdventure((BaseComponent[]) v); ret[i] = TranslationArgument.numeric(n);
else if (v instanceof BaseComponent) else if (v instanceof Boolean b)
ret[i] = toAdventure((BaseComponent) v); ret[i] = TranslationArgument.bool(b);
else if (v instanceof ComponentLike)
ret[i] = (ComponentLike) v;
else else
ret[i] = Component.text(Objects.toString(v)); ret[i] = TranslationArgument.component(filterObjToComponentLike(values[i]));
} }
return ret; return ret;
} }

View File

@ -10,6 +10,7 @@ import org.jetbrains.annotations.NotNull;
* A custom gradient with at least 2 colors in it. * A custom gradient with at least 2 colors in it.
*/ */
public class ChatColorGradient { public class ChatColorGradient {
private record GradientColor( private record GradientColor(
float location, float location,
TextColor color TextColor color
@ -22,6 +23,11 @@ public class ChatColorGradient {
private final List<GradientColor> colors = new ArrayList<>(); private final List<GradientColor> colors = new ArrayList<>();
/**
* Create the custom gradient.
*/
public ChatColorGradient() {}
/** /**
* Put a specific color at a specific location in the gradient. * Put a specific color at a specific location in the gradient.
* @param gradientLocation the location in the gradient. * @param gradientLocation the location in the gradient.
@ -43,7 +49,7 @@ public class ChatColorGradient {
if (colors.isEmpty()) if (colors.isEmpty())
throw new IllegalStateException("Must define at least one color in this ChatColorGradient instance."); throw new IllegalStateException("Must define at least one color in this ChatColorGradient instance.");
if (colors.size() == 1) if (colors.size() == 1)
return colors.get(0).color(); return colors.getFirst().color();
int i = 0; int i = 0;
for (; i < colors.size(); i++) { for (; i < colors.size(); i++) {
@ -54,7 +60,7 @@ public class ChatColorGradient {
if (i == 0) if (i == 0)
return colors.get(i).color(); return colors.get(i).color();
if (i == colors.size()) if (i == colors.size())
return colors.get(colors.size() - 1).color(); return colors.getLast().color();
int p = i - 1; int p = i - 1;
float pLoc = colors.get(p).location(); float pLoc = colors.get(p).location();

View File

@ -293,4 +293,7 @@ public class ChatColorUtil {
} }
private ChatColorUtil() {}
} }

View File

@ -157,5 +157,9 @@ public class ChatConfig {
.thenText("] "); .thenText("] ");
} }
private PandaTheme() {}
} }
private ChatConfig() {}
} }

View File

@ -264,7 +264,7 @@ public abstract class ChatStatic {
* @return a new {@link FormatableChat} with the provided translation key and parameters. * @return a new {@link FormatableChat} with the provided translation key and parameters.
*/ */
public static FormatableChat translation(String key, Object... with) { public static FormatableChat translation(String key, Object... with) {
return new FormatableChat(Component.translatable().key(key).args(Chat.filterObjToComponentLike(with))); return new FormatableChat(Component.translatable().key(key).arguments(Chat.filterObjToTranslationArgumentLike(with)));
} }
/** /**
@ -632,52 +632,39 @@ public abstract class ChatStatic {
private static ComponentBuilder<?, ?> componentToBuilder(Component c) { private static ComponentBuilder<?, ?> componentToBuilder(Component c) {
ComponentBuilder<?, ?> builder; ComponentBuilder<?, ?> builder = switch (c) {
if (c instanceof TextComponent) { case TextComponent textComponent -> Component.text()
builder = Component.text() .content(textComponent.content());
.content(((TextComponent) c).content()); case TranslatableComponent translatableComponent -> Component.translatable()
} .key(translatableComponent.key()).arguments(translatableComponent.arguments());
else if (c instanceof TranslatableComponent) { case SelectorComponent selectorComponent -> Component.selector()
builder = Component.translatable() .pattern(selectorComponent.pattern());
.key(((TranslatableComponent) c).key()) case ScoreComponent scoreComponent -> Component.score()
.args(((TranslatableComponent) c).args()); .name(scoreComponent.name())
} .objective(scoreComponent.objective());
else if (c instanceof SelectorComponent) { case KeybindComponent keybindComponent -> Component.keybind()
builder = Component.selector() .keybind(keybindComponent.keybind());
.pattern(((SelectorComponent) c).pattern()); case BlockNBTComponent blockNBTComponent -> Component.blockNBT()
} .interpret(blockNBTComponent.interpret())
else if (c instanceof ScoreComponent) { .nbtPath(blockNBTComponent.nbtPath())
builder = Component.score() .pos(blockNBTComponent.pos());
.name(((ScoreComponent) c).name()) case EntityNBTComponent entityNBTComponent -> Component.entityNBT()
.objective(((ScoreComponent) c).objective()); .interpret(entityNBTComponent.interpret())
} .nbtPath(entityNBTComponent.nbtPath())
else if (c instanceof KeybindComponent) { .selector(entityNBTComponent.selector());
builder = Component.keybind() case StorageNBTComponent storageNBTComponent -> Component.storageNBT()
.keybind(((KeybindComponent) c).keybind()); .interpret(storageNBTComponent.interpret())
} .nbtPath(storageNBTComponent.nbtPath())
else if (c instanceof BlockNBTComponent) { .storage(storageNBTComponent.storage());
builder = Component.blockNBT() case null, default -> throw new IllegalArgumentException("Unknown component type " + (c == null ? "null" : c.getClass()));
.interpret(((BlockNBTComponent) c).interpret()) };
.nbtPath(((BlockNBTComponent) c).nbtPath())
.pos(((BlockNBTComponent) c).pos());
}
else if (c instanceof EntityNBTComponent) {
builder = Component.entityNBT()
.interpret(((EntityNBTComponent) c).interpret())
.nbtPath(((EntityNBTComponent) c).nbtPath())
.selector(((EntityNBTComponent) c).selector());
}
else if (c instanceof StorageNBTComponent) {
builder = Component.storageNBT()
.interpret(((StorageNBTComponent) c).interpret())
.nbtPath(((StorageNBTComponent) c).nbtPath())
.storage(((StorageNBTComponent) c).storage());
}
else {
throw new IllegalArgumentException("Unknown component type " + c.getClass());
}
return builder.style(c.style()).append(c.children()); return builder.style(c.style()).append(c.children());
} }
/**
* Creates a new {@link ChatStatic} instance.
*/
protected ChatStatic() {}
} }

View File

@ -14,6 +14,7 @@ import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.ComponentLike; import net.kyori.adventure.text.ComponentLike;
import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.TranslatableComponent; import net.kyori.adventure.text.TranslatableComponent;
import net.kyori.adventure.text.TranslationArgument;
import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextColor; import net.kyori.adventure.text.format.TextColor;
import net.kyori.adventure.text.format.TextDecoration; import net.kyori.adventure.text.format.TextDecoration;
@ -265,8 +266,8 @@ public class ChatUtil {
count += strWidth(((TextComponent)component).content(), console, actuallyBold); count += strWidth(((TextComponent)component).content(), console, actuallyBold);
} }
else if (component instanceof TranslatableComponent) { else if (component instanceof TranslatableComponent) {
for (Component c : ((TranslatableComponent)component).args()) for (TranslationArgument c : ((TranslatableComponent)component).arguments())
count += componentWidth(c, console, actuallyBold); count += componentWidth(c.asComponent(), console, actuallyBold);
} }
for (Component c : component.children()) for (Component c : component.children())
@ -480,7 +481,7 @@ public class ChatUtil {
spacedRow.thenText(space); spacedRow.thenText(space);
} }
if (!row.isEmpty()) if (!row.isEmpty())
spacedRow.then(row.get(row.size() - 1)); spacedRow.then(row.getLast());
spacedRows.add(spacedRow.getAdv()); spacedRows.add(spacedRow.getAdv());
} }
@ -657,5 +658,6 @@ public class ChatUtil {
return str; return str;
} }
private ChatUtil() {}
} }

View File

@ -25,6 +25,9 @@ public class CLIBrigadierDispatcher extends BrigadierDispatcher<CLICommandSender
public static final CLICommandSender CLI_CONSOLE_COMMAND_SENDER = new CLIConsoleCommandSender(); public static final CLICommandSender CLI_CONSOLE_COMMAND_SENDER = new CLIConsoleCommandSender();
private CLIBrigadierDispatcher() {}
/** /**
* Executes the provided command as the console. * Executes the provided command as the console.
* @param commandWithoutSlash the command, without the eventual slash at the beginning. * @param commandWithoutSlash the command, without the eventual slash at the beginning.

View File

@ -11,6 +11,12 @@ import org.jetbrains.annotations.NotNull;
* The console command sender. * The console command sender.
*/ */
public class CLIConsoleCommandSender implements CLICommandSender { public class CLIConsoleCommandSender implements CLICommandSender {
/**
* Creates a new console command sender.
*/
protected CLIConsoleCommandSender() {}
public String getName() { public String getName() {
return "Console"; return "Console";
} }

View File

@ -36,6 +36,11 @@ import static fr.pandacube.lib.chat.ChatStatic.text;
*/ */
public class CommandAdmin extends CLIBrigadierCommand { public class CommandAdmin extends CLIBrigadierCommand {
/**
* Initializes the admin command.
*/
public CommandAdmin() {}
@Override @Override
protected LiteralArgumentBuilder<CLICommandSender> buildCommand() { protected LiteralArgumentBuilder<CLICommandSender> buildCommand() {
return literal("admin") return literal("admin")

View File

@ -9,6 +9,11 @@ import fr.pandacube.lib.cli.CLIApplication;
*/ */
public class CommandStop extends CLIBrigadierCommand { public class CommandStop extends CLIBrigadierCommand {
/**
* Initializes the admin command.
*/
public CommandStop() {}
@Override @Override
protected LiteralArgumentBuilder<CLICommandSender> buildCommand() { protected LiteralArgumentBuilder<CLICommandSender> buildCommand() {
return literal("stop") return literal("stop")

View File

@ -97,5 +97,7 @@ public class CLILogger {
t.start(); t.start();
return ps; return ps;
} }
private CLILogger() {}
} }

View File

@ -25,6 +25,11 @@ import java.util.function.Predicate;
*/ */
public abstract class BrigadierCommand<S> { public abstract class BrigadierCommand<S> {
/**
* Creates a Brigadier command.
*/
public BrigadierCommand() {}
/** /**
* Returns a builder for this command. * Returns a builder for this command.

View File

@ -21,6 +21,11 @@ public abstract class BrigadierDispatcher<S> {
private final CommandDispatcher<S> dispatcher = new CommandDispatcher<>(); private final CommandDispatcher<S> dispatcher = new CommandDispatcher<>();
/**
* Creates a new Dispatcher instance.
*/
public BrigadierDispatcher() {}
/** /**
* Registers the provided command node into this dispatcher. * Registers the provided command node into this dispatcher.

View File

@ -140,4 +140,8 @@ public class BrigadierSuggestionsUtil {
} }
private BrigadierSuggestionsUtil() {}
} }

View File

@ -70,6 +70,11 @@ public abstract class BackupCleaner implements UnaryOperator<TreeSet<LocalDateTi
}; };
} }
/**
* Create a backup cleaner.
*/
public BackupCleaner() {}
/** /**
* Creates a new {@link BackupCleaner} that keeps the archives kept by this {@link BackupCleaner} or by the provided * Creates a new {@link BackupCleaner} that keeps the archives kept by this {@link BackupCleaner} or by the provided

View File

@ -54,7 +54,7 @@ public class CronScheduler {
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
if (!tasks.isEmpty()) { if (!tasks.isEmpty()) {
CronTask next = tasks.get(0); CronTask next = tasks.getFirst();
if (next.nextRun <= now) { if (next.nextRun <= now) {
next.runAsync(); next.runAsync();
setLastRun(next.taskId, now); setLastRun(next.taskId, now);
@ -224,5 +224,6 @@ public class CronScheduler {
.toEpochMilli(); .toEpochMilli();
} }
private CronScheduler() {}
} }

View File

@ -163,4 +163,6 @@ public class Json {
} }
}*/ }*/
private Json() {}
} }

View File

@ -30,6 +30,8 @@ public class ThrowableAdapter implements JsonSerializer<Throwable>, JsonDeserial
/* package */ static final TypeAdapterFactory FACTORY = TreeTypeAdapter.newTypeHierarchyFactory(Throwable.class, new ThrowableAdapter()); /* package */ static final TypeAdapterFactory FACTORY = TreeTypeAdapter.newTypeHierarchyFactory(Throwable.class, new ThrowableAdapter());
private ThrowableAdapter() {}
@Override @Override
public Throwable deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { public Throwable deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {

View File

@ -237,5 +237,8 @@ public class TypeConverter {
} }
} }
private TypeConverter() {}
} }

View File

@ -58,6 +58,9 @@ public record MinecraftVersionList(
private static final TypeToken<Map<String, Integer>> MAP_STR_INT_TYPE = new TypeToken<>() { }; private static final TypeToken<Map<String, Integer>> MAP_STR_INT_TYPE = new TypeToken<>() { };
private static final TypeToken<Map<Integer, List<String>>> MAP_INT_LIST_STRING_TYPE = new TypeToken<>() { }; private static final TypeToken<Map<Integer, List<String>>> MAP_INT_LIST_STRING_TYPE = new TypeToken<>() { };
private MinecraftVersionListAdapter() {}
@Override @Override
public MinecraftVersionList deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { public MinecraftVersionList deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
if (!(json instanceof JsonObject jsonObj)) if (!(json instanceof JsonObject jsonObj))

View File

@ -135,4 +135,7 @@ public class MinecraftVersionUtil {
return set; return set;
} }
private MinecraftVersionUtil() {}
} }

View File

@ -56,18 +56,21 @@
<artifact>org.apache.commons:commons-dbcp2</artifact> <artifact>org.apache.commons:commons-dbcp2</artifact>
<excludes> <excludes>
<exclude>META-INF/MANIFEST.MF</exclude> <exclude>META-INF/MANIFEST.MF</exclude>
<exclude>META-INF/versions/9/**</exclude>
</excludes> </excludes>
</filter> </filter>
<filter> <filter>
<artifact>org.apache.commons:commons-pool2</artifact> <artifact>org.apache.commons:commons-pool2</artifact>
<excludes> <excludes>
<exclude>META-INF/MANIFEST.MF</exclude> <exclude>META-INF/MANIFEST.MF</exclude>
<exclude>META-INF/versions/9/**</exclude>
</excludes> </excludes>
</filter> </filter>
<filter> <filter>
<artifact>commons-logging:commons-logging</artifact> <artifact>commons-logging:commons-logging</artifact>
<excludes> <excludes>
<exclude>META-INF/MANIFEST.MF</exclude> <exclude>META-INF/MANIFEST.MF</exclude>
<exclude>META-INF/versions/9/**</exclude>
</excludes> </excludes>
</filter> </filter>
</filters> </filters>

View File

@ -16,6 +16,11 @@ import java.util.stream.Collectors;
*/ */
public class SQLElementList<E extends SQLElement<E>> extends ArrayList<E> { public class SQLElementList<E extends SQLElement<E>> extends ArrayList<E> {
/**
* Creates an empty list of sql elements.
*/
public SQLElementList() {}
/** /**
* Stores all the values modified by {@link #setCommon(SQLField, Object)}. * Stores all the values modified by {@link #setCommon(SQLField, Object)}.
*/ */

View File

@ -232,12 +232,8 @@ public class SQLField<E extends SQLElement<E>, T> {
} }
@SuppressWarnings({"rawtypes", "unchecked"}) @SuppressWarnings({"rawtypes", "unchecked"})
public Object fromJavaTypeToJDBCType(Object value) throws DBException { /* package */ Object fromJavaTypeToJDBCType(Object value) throws DBException {
Object ret = value; Object ret = value;
if (value != null && type instanceof SQLCustomType customType) { if (value != null && type instanceof SQLCustomType customType) {
try { try {
@ -250,7 +246,7 @@ public class SQLField<E extends SQLElement<E>, T> {
return ret; return ret;
} }
public Collection<Object> fromListJavaTypeToJDBCType(Collection<?> values) throws DBException { /* package */ Collection<Object> fromListJavaTypeToJDBCType(Collection<?> values) throws DBException {
if (values == null) if (values == null)
return null; return null;
List<Object> ret = new ArrayList<>(values.size()); List<Object> ret = new ArrayList<>(values.size());

View File

@ -13,6 +13,11 @@ import fr.pandacube.lib.util.log.Log;
*/ */
public abstract class SQLWhere<E extends SQLElement<E>> { public abstract class SQLWhere<E extends SQLElement<E>> {
/**
* Creates a SQL WHERE expression.
*/
protected SQLWhere() {}
/* package */ abstract ParameterizedSQLString toSQL() throws DBException; /* package */ abstract ParameterizedSQLString toSQL() throws DBException;
@Override @Override
@ -69,6 +74,7 @@ public abstract class SQLWhere<E extends SQLElement<E>> {
* Create a custom SQL {@code WHERE} expression. * Create a custom SQL {@code WHERE} expression.
* @param whereExpr the raw SQL {@code WHERE} expression. * @param whereExpr the raw SQL {@code WHERE} expression.
* @return a new SQL {@code WHERE} expression. * @return a new SQL {@code WHERE} expression.
* @param <E> the table type.
*/ */
public static <E extends SQLElement<E>> SQLWhere<E> expression(String whereExpr) { public static <E extends SQLElement<E>> SQLWhere<E> expression(String whereExpr) {
return expression(whereExpr, List.of()); return expression(whereExpr, List.of());
@ -79,6 +85,7 @@ public abstract class SQLWhere<E extends SQLElement<E>> {
* @param whereExpr the raw SQL {@code WHERE} expression. * @param whereExpr the raw SQL {@code WHERE} expression.
* @param params the parameters of the provided expression. * @param params the parameters of the provided expression.
* @return a new SQL {@code WHERE} expression. * @return a new SQL {@code WHERE} expression.
* @param <E> the table type.
*/ */
public static <E extends SQLElement<E>> SQLWhere<E> expression(String whereExpr, List<Object> params) { public static <E extends SQLElement<E>> SQLWhere<E> expression(String whereExpr, List<Object> params) {
return new SQLWhereCustomExpression<>(whereExpr, params); return new SQLWhereCustomExpression<>(whereExpr, params);
@ -89,6 +96,7 @@ public abstract class SQLWhere<E extends SQLElement<E>> {
* @param leftExpr the raw SQL left operand. * @param leftExpr the raw SQL left operand.
* @param valuesIn the values on the right of the {@code IN} operator. * @param valuesIn the values on the right of the {@code IN} operator.
* @return a new SQL {@code WHERE} expression. * @return a new SQL {@code WHERE} expression.
* @param <E> the table type.
*/ */
public static <E extends SQLElement<E>> SQLWhere<E> expressionIn(String leftExpr, Collection<?> valuesIn) { public static <E extends SQLElement<E>> SQLWhere<E> expressionIn(String leftExpr, Collection<?> valuesIn) {
return expressionIn(leftExpr, List.of(), valuesIn); return expressionIn(leftExpr, List.of(), valuesIn);
@ -100,6 +108,7 @@ public abstract class SQLWhere<E extends SQLElement<E>> {
* @param leftParams the parameters of the left operand. * @param leftParams the parameters of the left operand.
* @param valuesIn the values on the right of the {@code IN} operator. * @param valuesIn the values on the right of the {@code IN} operator.
* @return a new SQL {@code WHERE} expression. * @return a new SQL {@code WHERE} expression.
* @param <E> the table type.
*/ */
public static <E extends SQLElement<E>> SQLWhere<E> expressionIn(String leftExpr, List<Object> leftParams, Collection<?> valuesIn) { public static <E extends SQLElement<E>> SQLWhere<E> expressionIn(String leftExpr, List<Object> leftParams, Collection<?> valuesIn) {
return new SQLWhereInCustom<>(leftExpr, leftParams, valuesIn); return new SQLWhereInCustom<>(leftExpr, leftParams, valuesIn);

View File

@ -21,4 +21,8 @@
</dependency> </dependency>
</dependencies> </dependencies>
<properties>
<maven.javadoc.skip>true</maven.javadoc.skip>
</properties>
</project> </project>

View File

@ -82,6 +82,12 @@ public class PandalibPaperPermissions implements Listener {
} }
} }
/**
* Creates a {@link PandalibPaperPermissions} instance.
*/
private PandalibPaperPermissions() {}
/** /**
* Player login event handler. * Player login event handler.
* @param event the event. * @param event the event.

View File

@ -2,38 +2,26 @@ package fr.pandacube.lib.paper.commands;
import com.destroystokyo.paper.brigadier.BukkitBrigadierCommandSource; import com.destroystokyo.paper.brigadier.BukkitBrigadierCommandSource;
import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.ArgumentType;
import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.suggestion.SuggestionProvider; import com.mojang.brigadier.suggestion.SuggestionProvider;
import com.mojang.brigadier.tree.CommandNode;
import com.mojang.brigadier.tree.LiteralCommandNode; import com.mojang.brigadier.tree.LiteralCommandNode;
import com.mojang.brigadier.tree.RootCommandNode; import com.mojang.brigadier.tree.RootCommandNode;
import fr.pandacube.lib.chat.Chat; import fr.pandacube.lib.chat.Chat;
import fr.pandacube.lib.commands.BadCommandUsage; import fr.pandacube.lib.commands.BadCommandUsage;
import fr.pandacube.lib.commands.BrigadierCommand; import fr.pandacube.lib.commands.BrigadierCommand;
import fr.pandacube.lib.commands.SuggestionsSupplier; import fr.pandacube.lib.commands.SuggestionsSupplier;
import fr.pandacube.lib.paper.permissions.PandalibPaperPermissions;
import fr.pandacube.lib.paper.reflect.PandalibPaperReflect; import fr.pandacube.lib.paper.reflect.PandalibPaperReflect;
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.craftbukkit.CraftVector;
import fr.pandacube.lib.paper.reflect.wrapper.craftbukkit.VanillaCommandWrapper; import fr.pandacube.lib.paper.reflect.wrapper.craftbukkit.VanillaCommandWrapper;
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands.BlockPosArgument;
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands.Commands; import fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands.Commands;
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands.ComponentArgument;
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands.Coordinates;
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands.EntityArgument;
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands.EntitySelector;
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands.Vec3Argument;
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.core.BlockPos;
import fr.pandacube.lib.paper.reflect.wrapper.minecraft.server.ServerPlayer;
import fr.pandacube.lib.paper.reflect.wrapper.paper.PaperAdventure;
import fr.pandacube.lib.players.standalone.AbstractOffPlayer; import fr.pandacube.lib.players.standalone.AbstractOffPlayer;
import fr.pandacube.lib.players.standalone.AbstractOnlinePlayer; import fr.pandacube.lib.players.standalone.AbstractOnlinePlayer;
import fr.pandacube.lib.players.standalone.AbstractPlayerManager; import fr.pandacube.lib.players.standalone.AbstractPlayerManager;
import fr.pandacube.lib.reflect.wrapper.ReflectWrapper; import fr.pandacube.lib.reflect.wrapper.ReflectWrapper;
import fr.pandacube.lib.util.log.Log; import fr.pandacube.lib.util.log.Log;
import net.kyori.adventure.text.Component; import io.papermc.paper.command.brigadier.CommandSourceStack;
import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.command.Command; import org.bukkit.command.Command;
@ -41,18 +29,10 @@ import org.bukkit.command.CommandMap;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender; import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.command.PluginCommand; import org.bukkit.command.PluginCommand;
import org.bukkit.command.defaults.BukkitCommand;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerCommandSendEvent;
import org.bukkit.event.server.ServerLoadEvent;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import org.bukkit.util.BlockVector;
import org.bukkit.util.Vector;
import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@ -64,7 +44,9 @@ import static fr.pandacube.lib.util.ThrowableUtil.wrapEx;
/** /**
* Abstract class to hold a command to be integrated into a Paper server vanilla command dispatcher. * Abstract class to hold a command to be integrated into a Paper server vanilla command dispatcher.
*/ */
public abstract class PaperBrigadierCommand extends BrigadierCommand<BukkitBrigadierCommandSource> implements Listener { @SuppressWarnings("UnstableApiUsage")
public abstract class PaperBrigadierCommand extends BrigadierCommand<CommandSourceStack> implements Listener {
private static final Commands vanillaCommandDispatcher; private static final Commands vanillaCommandDispatcher;
private static final CommandDispatcher<BukkitBrigadierCommandSource> nmsDispatcher; private static final CommandDispatcher<BukkitBrigadierCommandSource> nmsDispatcher;
@ -91,6 +73,7 @@ public abstract class PaperBrigadierCommand extends BrigadierCommand<BukkitBriga
return; return;
} }
Log.info("Removing Bukkit command /" + name + " (" + getCommandIdentity(bukkitCommand) + ")"); Log.info("Removing Bukkit command /" + name + " (" + getCommandIdentity(bukkitCommand) + ")");
Log.warning("[1.20.6 update] Please test that the bukkit command removal is actually working.");
bukkitCmdMap.getKnownCommands().remove(name.toLowerCase(java.util.Locale.ENGLISH)); bukkitCmdMap.getKnownCommands().remove(name.toLowerCase(java.util.Locale.ENGLISH));
bukkitCommand.unregister(bukkitCmdMap); bukkitCommand.unregister(bukkitCmdMap);
@ -131,7 +114,13 @@ public abstract class PaperBrigadierCommand extends BrigadierCommand<BukkitBriga
/** /**
* The command node of this command. * The command node of this command.
*/ */
protected final LiteralCommandNode<BukkitBrigadierCommandSource> commandNode; protected final LiteralCommandNode<CommandSourceStack> commandNode;
/**
* The command requested aliases.
*/
protected final String[] aliases;
protected final String description;
private final RegistrationPolicy registrationPolicy; private final RegistrationPolicy registrationPolicy;
@ -147,12 +136,14 @@ public abstract class PaperBrigadierCommand extends BrigadierCommand<BukkitBriga
plugin = pl; plugin = pl;
registrationPolicy = regPolicy; registrationPolicy = regPolicy;
commandNode = buildCommand().build(); commandNode = buildCommand().build();
String[] aliasesTmp = getAliases();
aliases = aliasesTmp == null ? new String[0] : aliasesTmp;
description = getDescription();
postBuildCommand(commandNode); postBuildCommand(commandNode);
register(); register();
Bukkit.getPluginManager().registerEvents(this, plugin); //try {
try { // PandalibPaperPermissions.addPermissionMapping("minecraft.command." + commandNode.getLiteral().toLowerCase(), getTargetPermission().toLowerCase());
PandalibPaperPermissions.addPermissionMapping("minecraft.command." + commandNode.getLiteral().toLowerCase(), getTargetPermission().toLowerCase()); //} catch (NoClassDefFoundError ignored) { }
} catch (NoClassDefFoundError ignored) { }
} }
/** /**
@ -167,130 +158,28 @@ public abstract class PaperBrigadierCommand extends BrigadierCommand<BukkitBriga
private void register() { private void register() {
plugin.getLifecycleManager().registerEventHandler(LifecycleEvents.COMMANDS, event -> {
String[] aliases = getAliases(); registeredAliases = new HashSet<>(event.registrar().register(commandNode, description, List.of(aliases)));
if (aliases == null)
aliases = new String[0];
String pluginName = plugin.getName().toLowerCase(); if (registrationPolicy == RegistrationPolicy.ALL) {
// enforce registration of aliases
for (String alias : aliases) {
if (!registeredAliases.contains(alias))
registeredAliases.addAll(event.registrar().register(getAliasNode(alias), description));
}
}
registeredAliases = new HashSet<>(); });
registerNode(commandNode, false);
registerAlias(pluginName + ":" + commandNode.getLiteral(), true);
for (String alias : aliases) {
registerAlias(alias, false);
registerAlias(pluginName + ":" + alias, true);
}
} }
private void registerAlias(String alias, boolean prefixed) { private LiteralCommandNode<CommandSourceStack> getAliasNode(String alias) {
LiteralCommandNode<BukkitBrigadierCommandSource> node = literal(alias) return literal(alias)
.requires(commandNode.getRequirement()) .requires(commandNode.getRequirement())
.executes(commandNode.getCommand()) .executes(commandNode.getCommand())
.redirect(commandNode) .redirect(commandNode)
.build(); .build();
registerNode(node, prefixed);
}
private void registerNode(LiteralCommandNode<BukkitBrigadierCommandSource> node, boolean prefixed) {
RootCommandNode<BukkitBrigadierCommandSource> root = getRootNode();
String name = node.getLiteral();
boolean isAlias = node.getRedirect() == commandNode;
boolean forceRegistration = switch (registrationPolicy) {
case NONE -> false;
case ONLY_BASE_COMMAND -> prefixed || !isAlias;
case ALL -> true;
};
// nmsDispatcher integration and conflit resolution
boolean nmsRegister = false, nmsRegistered = false;
CommandNode<BukkitBrigadierCommandSource> nmsConflicted = root.getChild(name);
if (nmsConflicted != null) {
if (isFromThisCommand(nmsConflicted)) {
// this command is already registered in NMS. Dont need to register again
nmsRegistered = true;
}
else if (forceRegistration) {
nmsRegister = true;
Log.info("Overwriting Brigadier command /" + name);
}
else if (prefixed || !isAlias) {
Log.severe("/" + name + " already in NMS Brigadier instance."
+ " Wont replace it because registration is not forced for prefixed or initial name of a command.");
}
else { // conflict, won't replace, not forced but only an alias anyway
Log.info("/" + name + " already in NMS Brigadier instance."
+ " Wont replace it because registration is not forced for a non-prefixed alias.");
}
}
else {
nmsRegister = true;
}
if (nmsRegister) {
@SuppressWarnings("unchecked")
var rCommandNode = ReflectWrapper.wrapTyped(root, fr.pandacube.lib.paper.reflect.wrapper.brigadier.CommandNode.class);
rCommandNode.removeCommand(name);
root.addChild(node);
nmsRegistered = true;
}
if (!nmsRegistered) {
return;
}
registeredAliases.add(name);
// bukkit dispatcher conflict resolution
boolean bukkitRegister = false;
CommandMap bukkitCmdMap = Bukkit.getCommandMap();
Command bukkitConflicted = bukkitCmdMap.getCommand(name);
if (bukkitConflicted != null) {
if (!isFromThisCommand(bukkitConflicted)) {
if (forceRegistration) {
bukkitRegister = true;
Log.info("Overwriting Bukkit command /" + name
+ " (" + getCommandIdentity(bukkitConflicted) + ")");
}
else if (prefixed || !isAlias) {
Log.severe("/" + name + " already in Bukkit dispatcher (" + getCommandIdentity(bukkitConflicted) + ")." +
" Wont replace it because registration is not forced for prefixed or initial name of a command.");
}
else {
Log.info("/" + name + " already in Bukkit dispatcher (" + getCommandIdentity(bukkitConflicted) + ")." +
" Wont replace it because registration is not forced for a non-prefixed alias.");
}
}
}
else {
bukkitRegister = true;
}
if (bukkitRegister) {
bukkitCmdMap.getKnownCommands().remove(name.toLowerCase());
if (bukkitConflicted != null)
bukkitConflicted.unregister(bukkitCmdMap);
Command newCommand = new VanillaCommandWrapper(vanillaCommandDispatcher, node).__getRuntimeInstance();
bukkitCmdMap.getKnownCommands().put(name.toLowerCase(), newCommand);
newCommand.register(bukkitCmdMap);
}
}
private boolean isFromThisCommand(CommandNode<BukkitBrigadierCommandSource> node) {
return node == commandNode || node.getRedirect() == commandNode;
}
private boolean isFromThisCommand(Command bukkitCmd) {
if (VanillaCommandWrapper.REFLECT.get().isInstance(bukkitCmd)) {
return isFromThisCommand(ReflectWrapper.wrapTyped((BukkitCommand) bukkitCmd, VanillaCommandWrapper.class).vanillaCommand());
}
return false;
} }
private static String getCommandIdentity(Command bukkitCmd) { private static String getCommandIdentity(Command bukkitCmd) {
@ -305,25 +194,6 @@ public abstract class PaperBrigadierCommand extends BrigadierCommand<BukkitBriga
} }
/**
* Player command sender event handler.
* @param event the event.
*/
@EventHandler
public void onPlayerCommandSend(PlayerCommandSendEvent event) {
event.getCommands().removeAll(registeredAliases.stream().map(s -> "minecraft:" + s).toList());
}
/**
* Server load event handler.
* @param event the event.
*/
@EventHandler
public void onServerLoad(ServerLoadEvent event) {
register();
}
@ -342,6 +212,15 @@ public abstract class PaperBrigadierCommand extends BrigadierCommand<BukkitBriga
*/ */
protected abstract String getTargetPermission(); protected abstract String getTargetPermission();
/**
* Returns the permission that should be tested instead of "minecraft.command.cmdName". The conversion from the
* minecraft prefixed permission node to the returned node is done by the {@code pandalib-paper-permissions} if it
* is present in the classpath during runtime.
* @return the permission that should be tested instead of "minecraft.command.cmdName".
*/
protected String getDescription() {
return "A command from " + plugin.getName();
}
@ -355,13 +234,14 @@ public abstract class PaperBrigadierCommand extends BrigadierCommand<BukkitBriga
public boolean isConsole(BukkitBrigadierCommandSource wrapper) {
public boolean isConsole(CommandSourceStack wrapper) {
return isConsole(getCommandSender(wrapper)); return isConsole(getCommandSender(wrapper));
} }
public boolean isPlayer(BukkitBrigadierCommandSource wrapper) { public boolean isPlayer(CommandSourceStack wrapper) {
return isPlayer(getCommandSender(wrapper)); return isPlayer(getCommandSender(wrapper));
} }
public Predicate<BukkitBrigadierCommandSource> hasPermission(String permission) { public Predicate<CommandSourceStack> hasPermission(String permission) {
return wrapper -> getCommandSender(wrapper).hasPermission(permission); return wrapper -> getCommandSender(wrapper).hasPermission(permission);
} }
@ -395,7 +275,7 @@ public abstract class PaperBrigadierCommand extends BrigadierCommand<BukkitBriga
* @param context the command context from which to get the Bukkit command sender. * @param context the command context from which to get the Bukkit command sender.
* @return the Bukkit command sender. * @return the Bukkit command sender.
*/ */
public static CommandSender getCommandSender(CommandContext<BukkitBrigadierCommandSource> context) { public static CommandSender getCommandSender(CommandContext<CommandSourceStack> context) {
return getCommandSender(context.getSource()); return getCommandSender(context.getSource());
} }
@ -404,8 +284,8 @@ public abstract class PaperBrigadierCommand extends BrigadierCommand<BukkitBriga
* @param wrapper the wrapper from which to get the Bukkit command sender. * @param wrapper the wrapper from which to get the Bukkit command sender.
* @return the Bukkit command sender. * @return the Bukkit command sender.
*/ */
public static CommandSender getCommandSender(BukkitBrigadierCommandSource wrapper) { public static CommandSender getCommandSender(CommandSourceStack wrapper) {
return wrapper.getBukkitSender(); return wrapper.getSender();
} }
/** /**
@ -413,8 +293,8 @@ public abstract class PaperBrigadierCommand extends BrigadierCommand<BukkitBriga
* @param sender the command sender. * @param sender the command sender.
* @return a new instance of a command sender wrapper for the provided command sender. * @return a new instance of a command sender wrapper for the provided command sender.
*/ */
public static BukkitBrigadierCommandSource getBrigadierCommandSource(CommandSender sender) { public static CommandSourceStack getBrigadierCommandSource(CommandSender sender) {
return VanillaCommandWrapper.getListener(sender); throw new UnsupportedOperationException("The 1.20.6 Paper API update uses a different wrapper for Brigadier command sender.");
} }
@ -443,7 +323,7 @@ public abstract class PaperBrigadierCommand extends BrigadierCommand<BukkitBriga
* @param suggestions the suggestions to wrap. * @param suggestions the suggestions to wrap.
* @return a {@link SuggestionProvider} generating the suggestions from the provided {@link SuggestionsSupplier}. * @return a {@link SuggestionProvider} generating the suggestions from the provided {@link SuggestionsSupplier}.
*/ */
public SuggestionProvider<BukkitBrigadierCommandSource> wrapSuggestions(SuggestionsSupplier<CommandSender> suggestions) { public SuggestionProvider<CommandSourceStack> wrapSuggestions(SuggestionsSupplier<CommandSender> suggestions) {
return wrapSuggestions(suggestions, PaperBrigadierCommand::getCommandSender); return wrapSuggestions(suggestions, PaperBrigadierCommand::getCommandSender);
} }
@ -456,7 +336,7 @@ public abstract class PaperBrigadierCommand extends BrigadierCommand<BukkitBriga
* @param cmd the command executor to wrap. * @param cmd the command executor to wrap.
* @return a wrapper command executor. * @return a wrapper command executor.
*/ */
protected static com.mojang.brigadier.Command<BukkitBrigadierCommandSource> wrapCommand(com.mojang.brigadier.Command<BukkitBrigadierCommandSource> cmd) { protected static com.mojang.brigadier.Command<CommandSourceStack> wrapCommand(com.mojang.brigadier.Command<CommandSourceStack> cmd) {
return context -> { return context -> {
try { try {
return cmd.run(context); return cmd.run(context);
@ -485,181 +365,13 @@ public abstract class PaperBrigadierCommand extends BrigadierCommand<BukkitBriga
*/ */
/**
* Creates a new instance of the Brigadier argument type {@code minecraft:entity}.
* @param singleTarget if this argument takes only a single target.
* @param playersOnly if this argument takes players only.
* @return the {@code minecraft:entity} argument type with the specified parameters.
*/
public static ArgumentType<Object> argumentMinecraftEntity(boolean singleTarget, boolean playersOnly) {
if (playersOnly) {
return singleTarget ? EntityArgument.player() : EntityArgument.players();
}
else {
return singleTarget ? EntityArgument.entity() : EntityArgument.entities();
}
}
/**
* Gets the value of the provided argument of type {@code minecraft:entity} (list of entities), from the provided context.
* @param context the command execution context.
* @param argument the argument name.
* @return the value of the argument, or null if not found.
*/
public List<Entity> tryGetMinecraftEntityArgument(CommandContext<BukkitBrigadierCommandSource> context, String argument) {
EntitySelector es = ReflectWrapper.wrap(tryGetArgument(context, argument, EntitySelector.MAPPING.runtimeClass()), EntitySelector.class);
if (es == null)
return null;
List<fr.pandacube.lib.paper.reflect.wrapper.minecraft.world.Entity> nmsEntityList = es.findEntities(context.getSource());
List<Entity> entityList = new ArrayList<>(nmsEntityList.size());
for (fr.pandacube.lib.paper.reflect.wrapper.minecraft.world.Entity nmsEntity : nmsEntityList) {
entityList.add(nmsEntity.getBukkitEntity());
}
return entityList;
}
/**
* Gets the value of the provided argument of type {@code minecraft:entity} (list of players), from the provided context.
* @param context the command execution context.
* @param argument the argument name.
* @return the value of the argument, or null if not found.
*/
public List<Player> tryGetMinecraftEntityArgumentPlayers(CommandContext<BukkitBrigadierCommandSource> context, String argument) {
EntitySelector es = ReflectWrapper.wrap(tryGetArgument(context, argument, EntitySelector.MAPPING.runtimeClass()), EntitySelector.class);
if (es == null)
return null;
List<ServerPlayer> nmsPlayerList = es.findPlayers(context.getSource());
List<Player> playerList = new ArrayList<>(nmsPlayerList.size());
for (ServerPlayer nmsPlayer : nmsPlayerList) {
playerList.add(nmsPlayer.getBukkitEntity());
}
return playerList;
}
/**
* Gets the value of the provided argument of type {@code minecraft:entity} (one entity), from the provided context.
* @param context the command execution context.
* @param argument the argument name.
* @return the value of the argument, or null if not found.
*/
public Entity tryGetMinecraftEntityArgumentOneEntity(CommandContext<BukkitBrigadierCommandSource> context, String argument) {
EntitySelector es = ReflectWrapper.wrap(tryGetArgument(context, argument, EntitySelector.MAPPING.runtimeClass()), EntitySelector.class);
if (es == null)
return null;
fr.pandacube.lib.paper.reflect.wrapper.minecraft.world.Entity nmsEntity = es.findSingleEntity(context.getSource());
return nmsEntity == null ? null : nmsEntity.getBukkitEntity();
}
/**
* Gets the value of the provided argument of type {@code minecraft:entity} (one player), from the provided context.
* @param context the command execution context.
* @param argument the argument name.
* @return the value of the argument, or null if not found.
*/
public Player tryGetMinecraftEntityArgumentOnePlayer(CommandContext<BukkitBrigadierCommandSource> context, String argument) {
EntitySelector es = ReflectWrapper.wrap(tryGetArgument(context, argument, EntitySelector.MAPPING.runtimeClass()), EntitySelector.class);
if (es == null)
return null;
ServerPlayer nmsPlayer = es.findSinglePlayer(context.getSource());
return nmsPlayer == null ? null : nmsPlayer.getBukkitEntity();
}
/**
* Creates a new instance of the Brigadier argument type {@code minecraft:block_pos}.
* @return the {@code minecraft:block_pos} argument type.
*/
public static ArgumentType<Object> argumentMinecraftBlockPosition() {
return BlockPosArgument.blockPos();
}
/**
* Gets the value of the provided argument of type {@code minecraft:block_pos}, from the provided context.
* @param context the command execution context.
* @param argument the argument name.
* @param deflt a default value if the argument is not found.
* @return the value of the argument.
*/
public BlockVector tryGetMinecraftBlockPositionArgument(CommandContext<BukkitBrigadierCommandSource> context,
String argument, BlockVector deflt) {
return tryGetArgument(context, argument, Coordinates.MAPPING.runtimeClass(), nmsCoordinate -> {
BlockPos bp = ReflectWrapper.wrap(nmsCoordinate, Coordinates.class).getBlockPos(context.getSource());
return new BlockVector(bp.getX(), bp.getY(), bp.getZ());
}, deflt);
}
/**
* Creates a new instance of the Brigadier argument type {@code minecraft:vec3}.
* @return the {@code minecraft:vec3} argument type.
*/
public static ArgumentType<Object> argumentMinecraftVec3() {
return Vec3Argument.vec3(true);
}
/**
* Gets the value of the provided argument of type {@code minecraft:vec3}, from the provided context.
* @param context the command execution context.
* @param argument the argument name.
* @param deflt a default value if the argument is not found.
* @return the value of the argument.
*/
public Vector tryGetMinecraftVec3Argument(CommandContext<BukkitBrigadierCommandSource> context, String argument,
Vector deflt) {
return tryGetArgument(context, argument, Coordinates.MAPPING.runtimeClass(),
nmsCoordinate -> CraftVector.toBukkit(
ReflectWrapper.wrap(nmsCoordinate, Coordinates.class).getPosition(context.getSource())
),
deflt);
}
/**
* Creates a new instance of the Brigadier argument type {@code minecraft:component}.
* @return the {@code minecraft:component} argument type.
*/
public static ArgumentType<Object> argumentMinecraftChatComponent() {
return ComponentArgument.textComponent();
}
/**
* Gets the value of the provided argument of type {@code minecraft:component}, from the provided context.
* @param context the command execution context.
* @param argument the argument name.
* @param deflt a default value if the argument is not found.
* @return the value of the argument.
*/
public Component tryGetMinecraftChatComponentArgument(CommandContext<BukkitBrigadierCommandSource> context,
String argument, Component deflt) {
return tryGetArgument(context, argument,
fr.pandacube.lib.paper.reflect.wrapper.minecraft.network.chat.Component.MAPPING.runtimeClass(),
nmsComp -> PaperAdventure.asAdventure(
ReflectWrapper.wrap(nmsComp,
fr.pandacube.lib.paper.reflect.wrapper.minecraft.network.chat.Component.class)
),
deflt);
}
/** /**
* All possible choices on how to force the registration of a command, based on certain conditions. * All possible choices on how to force the registration of a command, based on certain conditions.
*/ */
public enum RegistrationPolicy { public enum RegistrationPolicy {
/**
* Do not force to register a command node or an alias if there is already a command with that name in the
* vanilla Brigadier dispatcher.
* Note that all plugin-name-prefixed aliases will be registered anyway.
*/
NONE,
/** /**
* Force only the base command (but not the aliases) to be registered, even if a command with that name already * Force only the base command (but not the aliases) to be registered, even if a command with that name already
* exists in the vanilla Brigadier dispatcher. * exists in the vanilla Brigadier dispatcher.

View File

@ -1,6 +1,5 @@
package fr.pandacube.lib.paper.util; package fr.pandacube.lib.paper.util;
import com.destroystokyo.paper.Namespaced;
import com.google.common.collect.Streams; import com.google.common.collect.Streams;
import fr.pandacube.lib.chat.Chat; import fr.pandacube.lib.chat.Chat;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
@ -13,10 +12,8 @@ import org.bukkit.inventory.meta.Damageable;
import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.ItemMeta;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Set;
import java.util.function.Consumer; import java.util.function.Consumer;
import static fr.pandacube.lib.chat.ChatStatic.chatComponent; import static fr.pandacube.lib.chat.ChatStatic.chatComponent;
@ -183,7 +180,7 @@ public class ItemStackBuilder {
public ItemStackBuilder fakeEnchant(boolean apply) { public ItemStackBuilder fakeEnchant(boolean apply) {
if (apply) { if (apply) {
enchant(Enchantment.DURABILITY, 1); enchant(Enchantment.UNBREAKING, 1);
return hideEnchants(); return hideEnchants();
} }
return this; return this;
@ -196,22 +193,6 @@ public class ItemStackBuilder {
public ItemStackBuilder unbreakable(boolean unbreakable) { public ItemStackBuilder unbreakable(boolean unbreakable) {
return meta(m -> m.setUnbreakable(unbreakable)); return meta(m -> m.setUnbreakable(unbreakable));
} }
public ItemStackBuilder canDestroy(Set<Material> destroyable) {
return canDestroy(destroyable.stream().map(m -> (Namespaced) m.getKey()).toList());
}
public ItemStackBuilder canPlaceOn(Set<Material> placeOn) {
return canPlaceOn(placeOn.stream().map(m -> (Namespaced) m.getKey()).toList());
}
public ItemStackBuilder canDestroy(Collection<Namespaced> destroyable) {
return meta(m -> m.setDestroyableKeys(destroyable));
}
public ItemStackBuilder canPlaceOn(Collection<Namespaced> placeOn) {
return meta(m -> m.setPlaceableKeys(placeOn));
}
public ItemStackBuilder damage(int d) { public ItemStackBuilder damage(int d) {
return meta(m -> m.setDamage(d), Damageable.class); return meta(m -> m.setDamage(d), Damageable.class);

View File

@ -18,6 +18,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.Arrays; import java.util.Arrays;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects; import java.util.Objects;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.function.IntUnaryOperator; import java.util.function.IntUnaryOperator;
@ -98,7 +99,7 @@ public record PlayerDataWrapper(CompoundTag data) {
Inventory inv = Bukkit.createInventory(null, bukkitType); Inventory inv = Bukkit.createInventory(null, bukkitType);
if (stacks.isEmpty()) if (stacks.isEmpty())
return inv; return inv;
for (Map.Entry<Integer, ItemStack> is : stacks.entrySet()) { for (Entry<Integer, ItemStack> is : stacks.entrySet()) {
inv.setItem(nbtToBukkitSlotConverter.applyAsInt(is.getKey()), is.getValue()); inv.setItem(nbtToBukkitSlotConverter.applyAsInt(is.getKey()), is.getValue());
} }
return inv; return inv;
@ -142,7 +143,7 @@ public record PlayerDataWrapper(CompoundTag data) {
private void setRawInventoryContent(String key, Map<Integer, ItemStack> stacks) { private void setRawInventoryContent(String key, Map<Integer, ItemStack> stacks) {
ListTag list = new ListTag(); ListTag list = new ListTag();
for (Map.Entry<Integer, ItemStack> is : stacks.entrySet()) { for (Entry<Integer, ItemStack> is : stacks.entrySet()) {
ItemStack stack = filterStack(is.getValue()); ItemStack stack = filterStack(is.getValue());
if (stack == null) if (stack == null)
continue; continue;
@ -312,6 +313,7 @@ public record PlayerDataWrapper(CompoundTag data) {
case LEGS -> Objects.requireNonNullElseGet(this.getLeggings(), () -> new ItemStack(Material.AIR)); case LEGS -> Objects.requireNonNullElseGet(this.getLeggings(), () -> new ItemStack(Material.AIR));
case CHEST -> Objects.requireNonNullElseGet(this.getChestplate(), () -> new ItemStack(Material.AIR)); case CHEST -> Objects.requireNonNullElseGet(this.getChestplate(), () -> new ItemStack(Material.AIR));
case HEAD -> Objects.requireNonNullElseGet(this.getHelmet(), () -> new ItemStack(Material.AIR)); case HEAD -> Objects.requireNonNullElseGet(this.getHelmet(), () -> new ItemStack(Material.AIR));
case BODY -> new ItemStack(Material.AIR); // for horses/wolves armor
}; };
} }

View File

@ -119,5 +119,7 @@ public class PermissionExpressionParser {
return super.evaluate(constant, evaluationContext); return super.evaluate(constant, evaluationContext);
} }
} }
private PermissionExpressionParser() {}
} }

View File

@ -199,5 +199,7 @@ public class Permissions {
checkInitialized(); checkInitialized();
return backendReader.getFullPermissionsList(); return backendReader.getFullPermissionsList();
} }
private Permissions() {}
} }

View File

@ -48,4 +48,5 @@ public class Reflect {
} }
private Reflect() {}
} }

View File

@ -78,4 +78,7 @@ public class WrapperRegistry {
ReflectConstructor<? extends ReflectWrapperI> objectWrapperConstructor) { ReflectConstructor<? extends ReflectWrapperI> objectWrapperConstructor) {
} }
private WrapperRegistry() {}
} }

View File

@ -104,4 +104,7 @@ public class DistanceUtil {
} }
} }
private DistanceUtil() {}
} }

View File

@ -84,4 +84,6 @@ public class EnumUtil {
return RandomUtil.arrayElement(enumType.getEnumConstants()); return RandomUtil.arrayElement(enumType.getEnumConstants());
} }
private EnumUtil() {}
} }

View File

@ -52,4 +52,7 @@ public class FileUtils {
Files.copy(source.toPath(), target.toPath()); Files.copy(source.toPath(), target.toPath());
} }
} }
private FileUtils() {}
} }

View File

@ -21,4 +21,8 @@ public class ListUtil {
list.add(i); list.add(i);
} }
} }
private ListUtil() {}
} }

View File

@ -158,5 +158,7 @@ public class MemoryUtil {
unitMultiplier = uMultiplier; unitMultiplier = uMultiplier;
} }
} }
private MemoryUtil() {}
} }

View File

@ -97,6 +97,8 @@ public class MinecraftWebUtil {
return builder.toString(); return builder.toString();
} }
private MinecraftWebUtil() {}

View File

@ -10,7 +10,7 @@ import java.util.UUID;
* <p> * <p>
* You can generate the UUID programmatically using {@link #getFromNickName(String)} and * You can generate the UUID programmatically using {@link #getFromNickName(String)} and
* {@link #getFromNickNames(String[])}. * {@link #getFromNickNames(String[])}.
* * <p>
* To use this class as a program, type * To use this class as a program, type
* <pre> * <pre>
* java -cp&lt;anyClassPathContainingThisClass&gt; fr.pandacube.lib.util.OfflineUUID [playernames...] * java -cp&lt;anyClassPathContainingThisClass&gt; fr.pandacube.lib.util.OfflineUUID [playernames...]
@ -67,4 +67,6 @@ public class OfflineUUID {
System.out.println(arg + "\t" + getFromNickName(arg)); System.out.println(arg + "\t" + getFromNickName(arg));
} }
} }
private OfflineUUID() {}
} }

View File

@ -172,7 +172,7 @@ public class RandomUtil {
return String.valueOf(pw); return String.valueOf(pw);
} }
private RandomUtil() {}
} }

View File

@ -146,6 +146,6 @@ public class StringUtil {
private StringUtil() {}
} }

View File

@ -147,5 +147,6 @@ public class ThrowableUtil {
return new RuntimeException(t); return new RuntimeException(t);
} }
private ThrowableUtil() {}
} }

View File

@ -56,4 +56,6 @@ public class Tick {
return Duration.ofMillis(toMs(tick)); return Duration.ofMillis(toMs(tick));
} }
private Tick() {}
} }

View File

@ -481,4 +481,7 @@ public class TimeUtil {
} }
private TimeUtil() {}
} }

View File

@ -2,6 +2,9 @@ package fr.pandacube.lib.util.function;
/** /**
* A consumer that can possibly throw a checked exception. * A consumer that can possibly throw a checked exception.
* @param <T> the first parameter for this bi-consumer.
* @param <U> the second parameter for this bi-consumer.
* @param <E> the exception type that this interface method can throw.
*/ */
@FunctionalInterface @FunctionalInterface
public interface BiConsumerException<T, U, E extends Exception> { public interface BiConsumerException<T, U, E extends Exception> {

View File

@ -2,6 +2,8 @@ package fr.pandacube.lib.util.function;
/** /**
* A predicate that can possibly throw a checked exception. * A predicate that can possibly throw a checked exception.
* @param <T> the parameter for this predicate.
* @param <E> the exception type that this predicate can throw.
*/ */
@FunctionalInterface @FunctionalInterface
public interface PredicateException<T, E extends Exception> { public interface PredicateException<T, E extends Exception> {

View File

@ -2,6 +2,7 @@ package fr.pandacube.lib.util.function;
/** /**
* A runnable that can possibly throw a checked exception. * A runnable that can possibly throw a checked exception.
* @param <E> the exception type that this interface method can throw.
*/ */
@FunctionalInterface @FunctionalInterface
public interface RunnableException<E extends Exception> { public interface RunnableException<E extends Exception> {

View File

@ -2,6 +2,8 @@ package fr.pandacube.lib.util.function;
/** /**
* A supplier that can possibly throw a checked exception. * A supplier that can possibly throw a checked exception.
* @param <T> the return type of this supplier.
* @param <E> the exception type that this interface method can throw.
*/ */
@FunctionalInterface @FunctionalInterface
public interface SupplierException<T, E extends Exception> { public interface SupplierException<T, E extends Exception> {

View File

@ -2,6 +2,9 @@ package fr.pandacube.lib.util.function;
/** /**
* A function that can possibly throw a checked exception. * A function that can possibly throw a checked exception.
* @param <T> the first parameter for this bi-function.
* @param <U> the second parameter for this bi-function.
* @param <E> the exception type that this interface method can throw.
*/ */
@FunctionalInterface @FunctionalInterface
public interface ToIntBiFunctionException<T, U, E extends Exception> { public interface ToIntBiFunctionException<T, U, E extends Exception> {

View File

@ -2,6 +2,10 @@ package fr.pandacube.lib.util.function;
/** /**
* A consumer that can possibly throw a checked exception. * A consumer that can possibly throw a checked exception.
* @param <T> the first parameter for this tri-consumer.
* @param <U> the second parameter for this tri-consumer.
* @param <V> the third parameter for this tri-consumer.
* @param <E> the exception type that this interface method can throw.
*/ */
@FunctionalInterface @FunctionalInterface
public interface TriConsumerException<T, U, V, E extends Exception> { public interface TriConsumerException<T, U, V, E extends Exception> {

View File

@ -30,6 +30,11 @@ public class DailyLogRotateFileHandler extends Handler {
private String currentFileDate = getCurrentDay(); private String currentFileDate = getCurrentDay();
private boolean closed = false; private boolean closed = false;
/**
* Creates a new {@link DailyLogRotateFileHandler}.
*/
public DailyLogRotateFileHandler() {}
@Override @Override
public synchronized void close() throws SecurityException { public synchronized void close() throws SecurityException {

View File

@ -159,4 +159,6 @@ public final class Log {
logger.info(message); logger.info(message);
} }
private Log() {}
} }

View File

@ -14,6 +14,11 @@ import java.time.Duration;
public abstract class AbstractServerWS extends WebSocketAdapter implements AbstractWS { public abstract class AbstractServerWS extends WebSocketAdapter implements AbstractWS {
private boolean isClosed = false; private boolean isClosed = false;
/**
* Creates a Websocket server endpoint.
*/
public AbstractServerWS() {}
@Override @Override
public final void onWebSocketConnect(Session session) public final void onWebSocketConnect(Session session)

View File

@ -100,4 +100,6 @@ public class PayloadRegistry {
registerPayloadType("login-succeed", LoginSucceedPayload.class); registerPayloadType("login-succeed", LoginSucceedPayload.class);
} }
private PayloadRegistry() {}
} }

View File

@ -4,4 +4,9 @@ package fr.pandacube.lib.ws.payloads;
* Payload used by the server in inform the client the login was successful. * Payload used by the server in inform the client the login was successful.
*/ */
public class LoginSucceedPayload extends Payload { public class LoginSucceedPayload extends Payload {
/**
* Creates a new {@link LoginSucceedPayload}.
*/
public LoginSucceedPayload() {}
} }

View File

@ -5,4 +5,8 @@ package fr.pandacube.lib.ws.payloads;
*/ */
public abstract class Payload { public abstract class Payload {
/**
* Creates a new {@link Payload}.
*/
public Payload() {}
} }

View File

@ -25,7 +25,7 @@
</developer> </developer>
</developers> </developers>
<inceptionYear>2015</inceptionYear> <inceptionYear>2011</inceptionYear>
<ciManagement> <ciManagement>
<system>jenkins</system> <system>jenkins</system>
@ -56,8 +56,8 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<bungeecord.version>1.20-R0.3-SNAPSHOT</bungeecord.version> <bungeecord.version>1.20-R0.3-SNAPSHOT</bungeecord.version>
<paper.version>1.20.4-R0.1</paper.version> <paper.version>1.20.6-R0.1</paper.version>
<mc.version>1.20.4</mc.version> <mc.version>1.20.6</mc.version>
</properties> </properties>
<modules> <modules>