) msg);
+ if (out == null) promise.setSuccess();
+ else ctx.write(out, promise);
+ }
+ }
+
+ private @Nullable > P filterOutgoing(P packet) {
+ return discardRules.contains(packet.getClass()) ? null : packet;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
+ if (!(msg instanceof Packet> packet)) {
+ super.channelRead(ctx, msg);
+ return;
+ }
+
+ @SuppressWarnings("unchecked")
+ var p = (Packet super ServerGamePacketListener>) packet;
+
+ var listener = listeners.get(packet.getClass());
+ if (listener != null) listener.offer(p);
+
+ var redirect = redirections.get(packet.getClass());
+ if (redirect != null) redirect.offer(p);
+ else super.channelRead(ctx, packet);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Common/src/main/java/fr/maxlego08/menu/common/network/PacketQueue.java b/Common/src/main/java/fr/maxlego08/menu/common/network/PacketQueue.java
new file mode 100644
index 00000000..35ff8127
--- /dev/null
+++ b/Common/src/main/java/fr/maxlego08/menu/common/network/PacketQueue.java
@@ -0,0 +1,238 @@
+package fr.maxlego08.menu.common.network;
+
+import com.tcoded.folialib.wrapper.task.WrappedTask;
+import fr.maxlego08.menu.api.MenuPlugin;
+import net.minecraft.network.protocol.Packet;
+import org.bukkit.entity.Player;
+
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+public class PacketQueue> {
+
+ private final Queue queue;
+ private final Map, Consumer super T>> handlers;
+ private final Consumer super T> fallback;
+ private final boolean discard;
+ private final boolean directDispatch;
+ private WrappedTask task;
+
+ private PacketQueue(Builder builder) {
+ this.queue = builder.concurrent ? new ConcurrentLinkedQueue<>() : new LinkedList<>();
+ this.handlers = Map.copyOf(builder.handlers);
+ this.fallback = builder.fallback;
+ this.discard = builder.discard;
+ this.directDispatch = builder.directDispatch;
+ }
+
+ // โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+ // Queue access
+ // โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+
+ /** Raw queue โ hand this to MenuPacketListener if needed. */
+ public Queue queue() {
+ return queue;
+ }
+
+ // โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+ // Offer
+ // โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+
+ /**
+ * Called by MenuPacketListener on the Netty I/O thread.
+ *
+ * If {@code discard} is enabled the packet is silently dropped.
+ * If {@code directDispatch} is enabled the handler fires immediately
+ * on the Netty thread โ only safe for thread-safe, Bukkit-API-free handlers.
+ * Otherwise the packet is queued for later {@link #dispatch()} on the main thread.
+ */
+ public void offer(T packet) {
+ if (discard) return;
+ if (directDispatch) {
+ dispatchSingle(packet);
+ return;
+ }
+ queue.offer(packet);
+ }
+
+ // โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+ // Dispatch
+ // โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+
+ /**
+ * Drain every queued packet and fire the matching consumer.
+ * Must be called on the correct thread (main / entity thread).
+ * No-op when {@code directDispatch} is enabled since packets never queue.
+ */
+ public void dispatch() {
+ T packet;
+ while ((packet = queue.poll()) != null) dispatchSingle(packet);
+ }
+
+ /**
+ * Drain exactly one queued packet.
+ * Returns {@code true} if a packet was dispatched.
+ */
+ public boolean dispatchOne() {
+ T packet = queue.poll();
+ if (packet == null) return false;
+ dispatchSingle(packet);
+ return true;
+ }
+
+ @SuppressWarnings("unchecked")
+ private void dispatchSingle(T packet) {
+ Consumer super T> handler = handlers.get(packet.getClass());
+ if (handler != null) handler.accept(packet);
+ else if (fallback != null) fallback.accept(packet);
+ }
+
+ // โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+ // Scheduling
+ // โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+
+ /**
+ * Schedules a repeating task that calls {@link #dispatch()} every tick.
+ * The queue owns the task lifecycle โ call {@link #cancel()} to stop it.
+ *
+ * Accepts a scheduler function to keep PacketQueue decoupled from FoliaLib:
+ *
{@code
+ * queue.schedule(r -> plugin.getScheduler().runAtEntityTimer(player, r, 1L, 1L));
+ * }
+ */
+ public PacketQueue schedule(Function scheduler) {
+ this.task = scheduler.apply(this::dispatch);
+ return this;
+ }
+
+ /**
+ * Convenience overload when you don't need a custom interval.
+ * Schedules at 1-tick period on the player's entity thread.
+ */
+ public PacketQueue schedule(MenuPlugin plugin, Player player) {
+ return schedule(r -> plugin.getScheduler().runAtEntityTimer(player, r, 1L, 1L));
+ }
+
+ /** Cancels the scheduled dispatch task if one was started via {@link #schedule}. */
+ public void cancel() {
+ if (task != null) {
+ task.cancel();
+ task = null;
+ }
+ }
+
+ // โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+ // Utility
+ // โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+
+ public boolean isEmpty() { return queue.isEmpty(); }
+ public int size() { return queue.size(); }
+ public void clear() { queue.clear(); }
+
+ // โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+ // Static factories
+ // โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+
+ /**
+ * Silently discards every packet โ useful to block a packet type
+ * without processing it.
+ */
+ public static > PacketQueue empty() {
+ return new PacketQueue<>(new Builder().discard(true).concurrent(false));
+ }
+
+ /**
+ * Packets are queued but never dispatched automatically.
+ * Drain manually via {@link #dispatch()} or {@link #dispatchOne()}.
+ */
+ public static > PacketQueue unhandled() {
+ return PacketQueue.builder().build();
+ }
+
+ /**
+ * Queue with a single catch-all handler for every packet type.
+ */
+ public static > PacketQueue of(Consumer super T> handler) {
+ return PacketQueue.builder().orElse(handler).build();
+ }
+
+ /**
+ * Queue with a single typed handler.
+ */
+ public static > PacketQueue
of(Class
type, Consumer super P> handler) {
+ return PacketQueue.
builder().on(type, handler).build();
+ }
+
+ public static > Builder builder() {
+ return new Builder<>();
+ }
+
+ // โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+ // Builder
+ // โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+
+ public static final class Builder> {
+
+ private boolean concurrent = true;
+ private boolean discard = false;
+ private boolean directDispatch = false;
+ private final Map, Consumer super T>> handlers = new LinkedHashMap<>();
+ private Consumer super T> fallback;
+
+ public Builder concurrent(boolean concurrent) {
+ this.concurrent = concurrent;
+ return this;
+ }
+
+ /**
+ * When {@code true}, every incoming packet is silently dropped.
+ * No handlers are called and nothing is queued.
+ */
+ public Builder discard(boolean discard) {
+ this.discard = discard;
+ return this;
+ }
+
+ /**
+ * When {@code true}, handlers fire immediately on the Netty I/O thread
+ * instead of being queued for the main thread.
+ *
+ * Only enable this if your handlers are thread-safe and do not touch
+ * the Bukkit API. Using this with {@link org.bukkit.entity.Player}
+ * methods or any scheduler will cause corruption or crashes.
+ */
+ public Builder directDispatch(boolean directDispatch) {
+ this.directDispatch = directDispatch;
+ return this;
+ }
+
+ /**
+ * Register a typed handler for a specific packet subclass.
+ * {@code
+ * .on(ServerboundRenameItemPacket.class, p -> handleRename(p.getName()))
+ * }
+ */
+ @SuppressWarnings("unchecked")
+ public Builder on(Class type, Consumer super P> handler) {
+ handlers.put(type, (Consumer super T>) handler);
+ return this;
+ }
+
+ /**
+ * Catch-all โ fires for any packet whose class has no specific handler.
+ */
+ public Builder orElse(Consumer super T> fallback) {
+ this.fallback = fallback;
+ return this;
+ }
+
+ public PacketQueue build() {
+ return new PacketQueue<>(this);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Common/src/main/java/fr/maxlego08/menu/common/utils/MessageUtils.java b/Common/src/main/java/fr/maxlego08/menu/common/utils/MessageUtils.java
index ce9596bf..7081e740 100644
--- a/Common/src/main/java/fr/maxlego08/menu/common/utils/MessageUtils.java
+++ b/Common/src/main/java/fr/maxlego08/menu/common/utils/MessageUtils.java
@@ -3,7 +3,7 @@
import fr.maxlego08.menu.api.MenuPlugin;
import fr.maxlego08.menu.api.utils.IMessage;
import fr.maxlego08.menu.api.utils.Message;
-import fr.maxlego08.menu.common.utils.nms.NmsVersion;
+import fr.maxlego08.menu.common.MinecraftVersion;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
@@ -130,7 +130,7 @@ protected final Class> getNMSClass(String name) {
protected void title(Player player, String title, String subtitle, int fadeInTime, int showTime, int fadeOutTime) {
- if (NmsVersion.nmsVersion.isNewMaterial()) {
+ if (MinecraftVersion.getCurrentVersion().isAtLeast(MinecraftVersion.parse("1.13"))) {
player.sendTitle(title, subtitle, fadeInTime, showTime, fadeOutTime);
return;
}
diff --git a/Common/src/main/java/fr/maxlego08/menu/common/utils/ZUtils.java b/Common/src/main/java/fr/maxlego08/menu/common/utils/ZUtils.java
index 6ac42804..329581ac 100644
--- a/Common/src/main/java/fr/maxlego08/menu/common/utils/ZUtils.java
+++ b/Common/src/main/java/fr/maxlego08/menu/common/utils/ZUtils.java
@@ -3,9 +3,9 @@
import fr.maxlego08.menu.api.MenuPlugin;
import fr.maxlego08.menu.api.utils.EnumInventory;
import fr.maxlego08.menu.api.utils.Message;
+import fr.maxlego08.menu.common.MinecraftVersion;
import fr.maxlego08.menu.common.enums.Permission;
import fr.maxlego08.menu.common.utils.nms.NMSUtils;
-import fr.maxlego08.menu.common.utils.nms.NmsVersion;
import fr.maxlego08.menu.zcore.logger.Logger;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.ClickEvent;
@@ -45,7 +45,7 @@ public abstract class ZUtils extends MessageUtils {
private static Material[] byId;
static {
- if (!NmsVersion.nmsVersion.isNewMaterial()) {
+ if (!MinecraftVersion.getCurrentVersion().isAtLeast(MinecraftVersion.parse("1.13"))) {
byId = new Material[0];
for (Material material : Material.values()) {
if (byId.length <= material.getId()) {
@@ -57,7 +57,7 @@ public abstract class ZUtils extends MessageUtils {
}
protected String findPlayerLocale(Player player) {
- if (NmsVersion.getCurrentVersion().getVersion() >= NmsVersion.V_1_13.getVersion()) {
+ if (MinecraftVersion.getCurrentVersion().isAtLeast(MinecraftVersion.parse("1.13"))) {
try {
return player != null ? player.getLocale() : null;
} catch (Exception exception) {
@@ -452,7 +452,7 @@ private void applyTextureUrl(ItemStack itemStack, String url) {
protected Object getPrivateField(Object object, String field) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
Class> clazz = object.getClass();
- Field objectField = field.equals("commandMap") ? clazz.getDeclaredField(field) : field.equals("knownCommands") ? NmsVersion.nmsVersion.isNewMaterial() ? clazz.getSuperclass().getDeclaredField(field) : clazz.getDeclaredField(field) : null;
+ Field objectField = field.equals("commandMap") ? clazz.getDeclaredField(field) : field.equals("knownCommands") ? MinecraftVersion.getCurrentVersion().isAtLeast(MinecraftVersion.parse("1.13")) ? clazz.getSuperclass().getDeclaredField(field) : clazz.getDeclaredField(field) : null;
objectField.setAccessible(true);
Object result = objectField.get(object);
objectField.setAccessible(false);
diff --git a/Common/src/main/java/fr/maxlego08/menu/common/utils/itemstack/MenuItemStackFromItemStack.java b/Common/src/main/java/fr/maxlego08/menu/common/utils/itemstack/MenuItemStackFromItemStack.java
index 5edc1a38..d2739d16 100644
--- a/Common/src/main/java/fr/maxlego08/menu/common/utils/itemstack/MenuItemStackFromItemStack.java
+++ b/Common/src/main/java/fr/maxlego08/menu/common/utils/itemstack/MenuItemStackFromItemStack.java
@@ -4,8 +4,8 @@
import fr.maxlego08.menu.api.InventoryManager;
import fr.maxlego08.menu.api.itemstack.Firework;
import fr.maxlego08.menu.api.itemstack.Potion;
+import fr.maxlego08.menu.common.MinecraftVersion;
import fr.maxlego08.menu.common.utils.nms.ItemStackUtils;
-import fr.maxlego08.menu.common.utils.nms.NmsVersion;
import org.bukkit.FireworkEffect;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.*;
@@ -24,7 +24,7 @@ public static ZMenuItemStack fromItemStack(InventoryManager manager, ItemStack i
menuItemStack.setMaterial(itemStack.getType().name());
int amount = itemStack.getAmount();
if (amount > 1) menuItemStack.setAmount(String.valueOf(itemStack.getAmount()));
- if (NmsVersion.getCurrentVersion().isItemLegacy()) {
+ if (MinecraftVersion.getCurrentVersion().isBefore(MinecraftVersion.parse("1.13"))) {
int durability = itemStack.getDurability();
if (durability > 0) menuItemStack.setDurability(durability);
int data = itemStack.getData().getData();
@@ -45,7 +45,7 @@ public static ZMenuItemStack fromItemStack(InventoryManager manager, ItemStack i
menuItemStack.setFlags(new ArrayList<>(itemMeta.getItemFlags()));
menuItemStack.setEnchantments(itemMeta.getEnchants());
- if (NmsVersion.getCurrentVersion().isCustomModelData() && itemMeta.hasCustomModelData()) {
+ if (MinecraftVersion.getCurrentVersion().isAtLeast(MinecraftVersion.parse("1.14")) && itemMeta.hasCustomModelData()) {
menuItemStack.setModelID(itemMeta.getCustomModelData());
}
diff --git a/Common/src/main/java/fr/maxlego08/menu/common/utils/nms/ItemStackCompound.java b/Common/src/main/java/fr/maxlego08/menu/common/utils/nms/ItemStackCompound.java
index c6e796eb..3cf202e5 100644
--- a/Common/src/main/java/fr/maxlego08/menu/common/utils/nms/ItemStackCompound.java
+++ b/Common/src/main/java/fr/maxlego08/menu/common/utils/nms/ItemStackCompound.java
@@ -1,6 +1,8 @@
package fr.maxlego08.menu.common.utils.nms;
+import fr.maxlego08.menu.common.MinecraftVersion;
import fr.maxlego08.menu.common.utils.nms.ItemStackUtils.EnumReflectionItemStack;
+import fr.maxlego08.menu.nms.NMSHandler;
import org.bukkit.inventory.ItemStack;
public class ItemStackCompound {
@@ -12,14 +14,14 @@ public class ItemStackCompound {
// Static block to initialize the itemStackCompound based on the NmsVersion
static {
- fr.maxlego08.menu.common.utils.nms.NmsVersion nmsVersion = fr.maxlego08.menu.common.utils.nms.NmsVersion.nmsVersion;
- if (nmsVersion == fr.maxlego08.menu.common.utils.nms.NmsVersion.V_1_18_2) {
+ MinecraftVersion currentVersion = MinecraftVersion.getCurrentVersion();
+ if (currentVersion.equals(MinecraftVersion.parse("1.18.2"))) {
itemStackCompound = new ItemStackCompound(EnumReflectionCompound.V1_18_2);
- } else if (nmsVersion.getVersion() >= 1200) {
+ } else if (currentVersion.isAtLeast(MinecraftVersion.parse("1.12"))) {
itemStackCompound = new ItemStackCompound(EnumReflectionCompound.V1_12);
- } else if (nmsVersion.getVersion() >= 1190) {
+ } else if (currentVersion.isAtLeast(MinecraftVersion.parse("1.19"))) {
itemStackCompound = new ItemStackCompound(EnumReflectionCompound.V1_19);
- } else if (nmsVersion.getVersion() >= 1170) {
+ } else if (currentVersion.isAtLeast(MinecraftVersion.parse("1.17"))) {
itemStackCompound = new ItemStackCompound(EnumReflectionCompound.V1_17);
} else itemStackCompound = new ItemStackCompound(EnumReflectionCompound.V1_8_8);
}
@@ -29,7 +31,7 @@ public class ItemStackCompound {
/**
* Constructs an ItemStackCompound instance based on the given EnumReflectionCompound.
*
- * @param reflection The EnumReflectionCompound representing the NBT tag reflection version.
+ * @param reflection The EnumReflectionCompound representing the NBT tag reflection value.
*/
public ItemStackCompound(EnumReflectionCompound reflection) {
super();
@@ -77,6 +79,8 @@ public ItemStack applyCompound(ItemStack itemStack, Object compoundObject) throw
* @return The modified ItemStack.
*/
public ItemStack setString(ItemStack itemStack, String key, String value) {
+ NMSHandler handler = NMSProvider.getHandler();
+ if (handler != null) return handler.setString(itemStack, key, value);
try {
Object compoundObject = this.getCompound(itemStack);
if (compoundObject == null) return null;
@@ -97,6 +101,8 @@ public ItemStack setString(ItemStack itemStack, String key, String value) {
* @return The string value.
*/
public String getString(ItemStack itemStack, String key) {
+ NMSHandler handler = NMSProvider.getHandler();
+ if (handler != null) return handler.getString(itemStack, key);
try {
Object compoundObject = this.getCompound(itemStack);
if (compoundObject == null) return null;
@@ -117,6 +123,8 @@ public String getString(ItemStack itemStack, String key) {
* @return The double value.
*/
public double getDouble(ItemStack itemStack, String key) {
+ NMSHandler handler = NMSProvider.getHandler();
+ if (handler != null) return handler.getDouble(itemStack, key);
try {
Object compoundObject = this.getCompound(itemStack);
if (compoundObject == null) return 0;
@@ -136,6 +144,8 @@ public double getDouble(ItemStack itemStack, String key) {
* @return The long value.
*/
public long getLong(ItemStack itemStack, String key) {
+ NMSHandler handler = NMSProvider.getHandler();
+ if (handler != null) return handler.getLong(itemStack, key);
try {
Object compoundObject = this.getCompound(itemStack);
if (compoundObject == null) return 0;
@@ -154,6 +164,8 @@ public long getLong(ItemStack itemStack, String key) {
* @return The integer value.
*/
public int getInt(ItemStack itemStack, String key) {
+ NMSHandler handler = NMSProvider.getHandler();
+ if (handler != null) return handler.getInt(itemStack, key);
try {
Object compoundObject = this.getCompound(itemStack);
if (compoundObject == null) return 0;
@@ -173,6 +185,8 @@ public int getInt(ItemStack itemStack, String key) {
* @return The float value.
*/
public float getFloat(ItemStack itemStack, String key) {
+ NMSHandler handler = NMSProvider.getHandler();
+ if (handler != null) return handler.getFloat(itemStack, key);
try {
Object compoundObject = this.getCompound(itemStack);
return (float) compoundObject.getClass().getMethod(this.reflection.getMethodGetFloat(), String.class).invoke(compoundObject, new Object[]{key});
@@ -191,6 +205,8 @@ public float getFloat(ItemStack itemStack, String key) {
* @return The boolean value.
*/
public boolean getBoolean(ItemStack itemStack, String key) {
+ NMSHandler handler = NMSProvider.getHandler();
+ if (handler != null) return handler.getBoolean(itemStack, key);
try {
Object compoundObject = this.getCompound(itemStack);
return (boolean) compoundObject.getClass().getMethod(this.reflection.getMethodGetBoolean(), String.class).invoke(compoundObject, new Object[]{key});
@@ -210,6 +226,8 @@ public boolean getBoolean(ItemStack itemStack, String key) {
* @return The modified ItemStack.
*/
public ItemStack setInt(ItemStack itemStack, String key, int value) {
+ NMSHandler handler = NMSProvider.getHandler();
+ if (handler != null) return handler.setInt(itemStack, key, value);
try {
Object compoundObject = this.getCompound(itemStack);
compoundObject.getClass().getMethod(this.reflection.getMethodSetInt(), String.class, int.class).invoke(compoundObject, key, value);
@@ -230,6 +248,8 @@ public ItemStack setInt(ItemStack itemStack, String key, int value) {
* @return The modified ItemStack.
*/
public ItemStack setLong(ItemStack itemStack, String key, long value) {
+ NMSHandler handler = NMSProvider.getHandler();
+ if (handler != null) return handler.setLong(itemStack, key, value);
try {
Object compoundObject = this.getCompound(itemStack);
compoundObject.getClass().getMethod(this.reflection.getMethodSetLong(), String.class, long.class).invoke(compoundObject, key, value);
@@ -250,6 +270,8 @@ public ItemStack setLong(ItemStack itemStack, String key, long value) {
* @return The modified ItemStack.
*/
public ItemStack setFloat(ItemStack itemStack, String key, float value) {
+ NMSHandler handler = NMSProvider.getHandler();
+ if (handler != null) return handler.setFloat(itemStack, key, value);
try {
Object compoundObject = this.getCompound(itemStack);
compoundObject.getClass().getMethod(this.reflection.getMethodSetFloat(), String.class, float.class).invoke(compoundObject, key, value);
@@ -270,6 +292,8 @@ public ItemStack setFloat(ItemStack itemStack, String key, float value) {
* @return The modified ItemStack.
*/
public ItemStack setBoolean(ItemStack itemStack, String key, boolean value) {
+ NMSHandler handler = NMSProvider.getHandler();
+ if (handler != null) return handler.setBoolean(itemStack, key, value);
try {
Object compoundObject = this.getCompound(itemStack);
@@ -291,6 +315,8 @@ public ItemStack setBoolean(ItemStack itemStack, String key, boolean value) {
* @return The modified ItemStack.
*/
public ItemStack setDouble(ItemStack itemStack, String key, double value) {
+ NMSHandler handler = NMSProvider.getHandler();
+ if (handler != null) return handler.setDouble(itemStack, key, value);
try {
Object compoundObject = this.getCompound(itemStack);
compoundObject.getClass().getMethod(this.reflection.getMethodSetDouble(), String.class, double.class).invoke(compoundObject, key, value);
@@ -310,6 +336,8 @@ public ItemStack setDouble(ItemStack itemStack, String key, double value) {
* @return True if the key is present, false otherwise.
*/
public boolean isKey(ItemStack itemStack, String key) {
+ NMSHandler handler = NMSProvider.getHandler();
+ if (handler != null) return handler.hasKey(itemStack, key);
try {
Object nbttagCompound = this.getCompound(itemStack);
if (nbttagCompound == null) return false;
diff --git a/Common/src/main/java/fr/maxlego08/menu/common/utils/nms/ItemStackUtils.java b/Common/src/main/java/fr/maxlego08/menu/common/utils/nms/ItemStackUtils.java
index cdd70f66..be1e9cfc 100644
--- a/Common/src/main/java/fr/maxlego08/menu/common/utils/nms/ItemStackUtils.java
+++ b/Common/src/main/java/fr/maxlego08/menu/common/utils/nms/ItemStackUtils.java
@@ -1,6 +1,7 @@
package fr.maxlego08.menu.common.utils.nms;
import fr.maxlego08.menu.api.configuration.Configuration;
+import fr.maxlego08.menu.common.MinecraftVersion;
import fr.maxlego08.menu.common.utils.Base64;
import org.bukkit.Bukkit;
import org.bukkit.inventory.ItemStack;
@@ -15,6 +16,7 @@ public class ItemStackUtils {
private static final fr.maxlego08.menu.common.utils.nms.NmsVersion NMS_VERSION = fr.maxlego08.menu.common.utils.nms.NmsVersion.nmsVersion;
private static final Map itemStackSerialized = new HashMap<>();
+ private static final MinecraftVersion MINECRAFT_VERSION = MinecraftVersion.getCurrentVersion();
public static String serializeItemStack(ItemStack paramItemStack) {
@@ -26,7 +28,7 @@ public static String serializeItemStack(ItemStack paramItemStack) {
return itemStackSerialized.get(paramItemStack);
}
- if (fr.maxlego08.menu.common.utils.nms.NmsVersion.getCurrentVersion().isAttributItemStack()) {
+ if (MinecraftVersion.getCurrentVersion().isAtLeast(MinecraftVersion.parse("1.20.5"))) {
return Base64ItemStack.encode(paramItemStack);
}
@@ -67,7 +69,7 @@ public static ItemStack deserializeItemStack(String paramString) {
return null;
}
- if (fr.maxlego08.menu.common.utils.nms.NmsVersion.getCurrentVersion().isAttributItemStack()) {
+ if (MinecraftVersion.getCurrentVersion().isAtLeast(MinecraftVersion.parse("1.20.5"))) {
return Base64ItemStack.decode(paramString);
}
@@ -99,7 +101,7 @@ public static ItemStack deserializeItemStack(String paramString) {
if (NMS_VERSION == fr.maxlego08.menu.common.utils.nms.NmsVersion.V_1_11 || NMS_VERSION == fr.maxlego08.menu.common.utils.nms.NmsVersion.V_1_12) {
Constructor> localConstructor = localClass2.getConstructor(localClass1);
localObject2 = localConstructor.newInstance(localObject1);
- } else if (!NMS_VERSION.isItemLegacy()) {
+ } else if (MINECRAFT_VERSION.isAtMost(MinecraftVersion.parse("1.13"))) {
localObject2 = localClass2.getMethod("a", new Class[]{localClass1}).invoke(null,
localObject1);
} else {
diff --git a/Common/src/main/java/fr/maxlego08/menu/common/utils/nms/NMSProvider.java b/Common/src/main/java/fr/maxlego08/menu/common/utils/nms/NMSProvider.java
new file mode 100644
index 00000000..fd43d903
--- /dev/null
+++ b/Common/src/main/java/fr/maxlego08/menu/common/utils/nms/NMSProvider.java
@@ -0,0 +1,61 @@
+package fr.maxlego08.menu.common.utils.nms;
+
+import fr.maxlego08.menu.api.utils.ReflectionsCache;
+import fr.maxlego08.menu.common.MinecraftVersion;
+import fr.maxlego08.menu.nms.NMSHandler;
+import fr.maxlego08.menu.nms.NMSVersion;
+import fr.maxlego08.menu.zcore.logger.Logger;
+import org.bukkit.Bukkit;
+import org.bukkit.plugin.java.JavaPlugin;
+import org.reflections.Reflections;
+
+import java.util.Set;
+
+public class NMSProvider {
+
+ private static NMSHandler handler;
+
+ public static NMSHandler getHandler() {
+ if (handler == null) {
+ handler = loadHandler();
+ }
+ return handler;
+ }
+
+ private static NMSHandler loadHandler() {
+ MinecraftVersion current = MinecraftVersion.getCurrentVersion();
+ JavaPlugin plugin = (JavaPlugin) Bukkit.getPluginManager().getPlugin("zMenu");
+ if (plugin == null) return null;
+
+ Reflections reflections = ReflectionsCache.getInstance().getOrCreate(plugin, "fr.maxlego08.menu.nms");
+ Set> candidates = reflections.getTypesAnnotatedWith(NMSVersion.class);
+
+ Class extends NMSHandler> bestMatch = null;
+ MinecraftVersion bestVersion = null;
+
+ for (Class> clazz : candidates) {
+ if (!NMSHandler.class.isAssignableFrom(clazz)) continue;
+
+ NMSVersion annotation = clazz.getAnnotation(NMSVersion.class);
+ MinecraftVersion required = MinecraftVersion.parse(annotation.value());
+
+ if (current.isAtLeast(required)) {
+ if (bestVersion == null || required.isAfter(bestVersion)) {
+ bestVersion = required;
+ bestMatch = (Class extends NMSHandler>) clazz;
+ }
+ }
+ }
+
+ if (bestMatch != null) {
+ try {
+ return bestMatch.getDeclaredConstructor().newInstance();
+ } catch (Exception e) {
+ Logger.info("Could not instantiate NMS handler " + bestMatch.getName() + ": " + e.getMessage());
+ }
+ }
+
+ return null;
+ }
+}
+
diff --git a/Common/src/main/java/fr/maxlego08/menu/common/utils/nms/NMSUtils.java b/Common/src/main/java/fr/maxlego08/menu/common/utils/nms/NMSUtils.java
index df76458f..90642df9 100644
--- a/Common/src/main/java/fr/maxlego08/menu/common/utils/nms/NMSUtils.java
+++ b/Common/src/main/java/fr/maxlego08/menu/common/utils/nms/NMSUtils.java
@@ -5,9 +5,9 @@
public class NMSUtils {
/**
- * Get minecraft serveur version
+ * Get minecraft serveur value
*
- * @return version
+ * @return value
*/
public static double getNMSVersion() {
if (version != 0)
@@ -24,7 +24,7 @@ public static double getNMSVersion() {
}
/**
- * Check if minecraft version has shulker
+ * Check if minecraft value has shulker
*
* @return boolean
*/
@@ -33,7 +33,7 @@ public static boolean hasShulker() {
}
/**
- * Check if minecraft version has barrel
+ * Check if minecraft value has barrel
*
* @return booleab
*/
@@ -44,7 +44,7 @@ public static boolean hasBarrel() {
}
/**
- * check if version is granther than 1.13
+ * check if value is granther than 1.13
*
* @return boolean
*/
@@ -53,7 +53,7 @@ public static boolean isNewVersion() {
}
/**
- * Check if version has one hand
+ * Check if value has one hand
*
* @return boolean
*/
@@ -62,7 +62,7 @@ public static boolean isOneHand() {
}
/**
- * Check is version is minecraft 1.7
+ * Check is value is minecraft 1.7
*
* @return boolean
*/
@@ -71,7 +71,7 @@ public static boolean isVeryOldVersion() {
} public static double version = getNMSVersion();
/**
- * Check if version has itemmeta unbreakable
+ * Check if value has itemmeta unbreakable
*
* @return boolean
*/
@@ -80,7 +80,7 @@ public static boolean isUnbreakable() {
}
/**
- * Check if version is old version of minecraft with old material system
+ * Check if value is old value of minecraft with old material system
*
* @return boolean
*/
@@ -90,7 +90,7 @@ public static boolean isOldVersion() {
}
/**
- * Check if server vesion is new version
+ * Check if server vesion is new value
*
* @return boolean
*/
@@ -101,7 +101,7 @@ public static boolean isNewNMSVersion() {
}
/**
- * Allows to check if the version has the colors in hex
+ * Allows to check if the value has the colors in hex
*
* @return boolean
*/
@@ -111,7 +111,7 @@ public static boolean isHexColor() {
}
/**
- * Allows to check if the version has the colors in hex
+ * Allows to check if the value has the colors in hex
*
* @return boolean
*/
@@ -121,7 +121,7 @@ public static boolean isComponentColor() {
}
/**
- * Check if server version is new version
+ * Check if server value is new value
*
* @return boolean
*/
@@ -133,7 +133,7 @@ public static boolean isNewNBTVersion() {
}
/**
- * Check if server version is new version
+ * Check if server value is new value
*
* @return boolean
*/
diff --git a/Common/src/main/java/fr/maxlego08/menu/common/utils/nms/NmsVersion.java b/Common/src/main/java/fr/maxlego08/menu/common/utils/nms/NmsVersion.java
index 9d27dc7e..aadb88d6 100644
--- a/Common/src/main/java/fr/maxlego08/menu/common/utils/nms/NmsVersion.java
+++ b/Common/src/main/java/fr/maxlego08/menu/common/utils/nms/NmsVersion.java
@@ -1,5 +1,6 @@
package fr.maxlego08.menu.common.utils.nms;
+import fr.maxlego08.menu.common.MinecraftVersion;
import fr.maxlego08.menu.zcore.logger.Logger;
import org.bukkit.Bukkit;
@@ -60,9 +61,7 @@ public enum NmsVersion {
V_1_21_10(12110),
V_1_21_11(12111),
- UNKNOWN(Integer.MAX_VALUE)
-
- ;
+ UNKNOWN(Integer.MAX_VALUE);
public static final NmsVersion nmsVersion = getNmsVersion();
private final int version;
@@ -75,12 +74,14 @@ public enum NmsVersion {
* Gets the current version of the Bukkit server.
*
* @return The NmsVersion instance corresponding to the current version.
+ * @deprecated Use {@link MinecraftVersion#getCurrentVersion()} instead.
*/
+ @Deprecated(since = "1.1.1.4", forRemoval = true)
public static NmsVersion getCurrentVersion() {
return nmsVersion;
}
- private static NmsVersion getNmsVersion(){
+ private static NmsVersion getNmsVersion() {
Matcher matcher = Pattern.compile("(?\\d+\\.\\d+)(?\\.\\d+)?").matcher(Bukkit.getBukkitVersion());
int currentVersion = matcher.find() ? Integer.parseInt(matcher.group("version").replace(".", "") + (matcher.group("patch") != null ? matcher.group("patch").replace(".", "") : "0")) : 0;
@@ -93,11 +94,11 @@ private static NmsVersion getNmsVersion(){
if (currentVersion > highestSupportedVersionEnum.version) {
Logger.info(String.format(
- "Running Minecraft %s (newer than highest supported version %s). " +
- "Please report this version to help us add support. " +
- "Check for plugin updates if you experience issues.",
- currentVersion,
- highestSupportedVersionEnum.name()
+ "Running Minecraft %s (newer than highest supported version %s). " +
+ "Please report this version to help us add support. " +
+ "Check for plugin updates if you experience issues.",
+ currentVersion,
+ highestSupportedVersionEnum.name()
), Logger.LogType.WARNING);
return UNKNOWN;
}
@@ -116,161 +117,218 @@ private static NmsVersion getNmsVersion(){
}
/**
- * Checks if the current version supports PlayerProfiles.
- *
- * @return True if PlayerProfiles are supported, else False.
+ * @deprecated Use {@code MinecraftVersion.getCurrentVersion().isAtLeast(MinecraftVersion.parse("1.18.1"))} instead.
*/
+ @Deprecated(since = "1.1.1.4", forRemoval = true)
public boolean hasPlayerProfiles() {
return this.version >= NmsVersion.V_1_18_1.version;
}
/**
- * Checks if the current version uses obfuscated names.
- *
- * @return True if names are obfuscated, else False.
+ * @deprecated Use {@code MinecraftVersion.getCurrentVersion().isAtLeast(MinecraftVersion.parse("1.17"))} instead.
*/
+ @Deprecated(since = "1.1.1.4", forRemoval = true)
public boolean hasObfuscatedNames() {
return this.version >= NmsVersion.V_1_17.version;
}
/**
- * Checks if the current version supports components.
- *
- * @param isPaper True if the server uses Paper, else False.
- * @return True if components are supported, else False.
+ * @deprecated Use {@code MinecraftVersion.getCurrentVersion().isAtLeast(MinecraftVersion.parse("1.16.5"))} instead (combined with your Paper check).
*/
+ @Deprecated(since = "1.1.1.4", forRemoval = true)
public boolean isComponent(boolean isPaper) {
return isPaper && this.version >= NmsVersion.V_1_16_5.version;
}
/**
- * Checks if the current version is a legacy item version.
- *
- * @return True if the version is legacy, else False.
+ * @deprecated Use {@code MinecraftVersion.getCurrentVersion().isBefore(MinecraftVersion.parse("1.13"))} instead.
*/
+ @Deprecated(since = "1.1.1.4", forRemoval = true)
public boolean isItemLegacy() {
return this.version < NmsVersion.V_1_13.version;
}
/**
- * Checks if the current version supports PersistentDataContainer.
- *
- * @return True if PersistentDataContainer is supported, else False.
+ * @deprecated Use {@code MinecraftVersion.getCurrentVersion().isAtLeast(MinecraftVersion.parse("1.14"))} instead.
*/
+ @Deprecated(since = "1.1.1.4", forRemoval = true)
public boolean isPdcVersion() {
return this.version >= NmsVersion.V_1_14.version;
}
/**
- * Checks if the current version is a legacy version for Skull owners.
- *
- * @return True if the version is legacy, else False.
+ * @deprecated Use {@code MinecraftVersion.getCurrentVersion().isAtMost(MinecraftVersion.parse("1.12"))} instead.
*/
+ @Deprecated(since = "1.1.1.4", forRemoval = true)
public boolean isSkullOwnerLegacy() {
return this.version <= NmsVersion.V_1_12.version;
}
/**
- * Checks if the current version supports CustomModelData.
- *
- * @return True if CustomModelData is supported, else False.
+ * @deprecated Use {@code MinecraftVersion.getCurrentVersion().isAtLeast(MinecraftVersion.parse("1.14"))} instead.
*/
+ @Deprecated(since = "1.1.1.4", forRemoval = true)
public boolean isCustomModelData() {
return this.version >= NmsVersion.V_1_14.version;
}
/**
- * Checks if the current version is a hexadecimal version.
- *
- * @return True if the version is hexadecimal, else False.
+ * @deprecated Use {@code MinecraftVersion.getCurrentVersion().isAtLeast(MinecraftVersion.parse("1.16"))} instead.
*/
+ @Deprecated(since = "1.1.1.4", forRemoval = true)
public boolean isHexVersion() {
return this.version >= NmsVersion.V_1_16.version;
}
/**
- * Checks if the current version is an Attribute version.
- *
- * @return True if the version is Attribute, else False.
+ * @deprecated Use {@code MinecraftVersion.getCurrentVersion().isAfter(MinecraftVersion.parse("1.8.8"))} instead.
*/
+ @Deprecated(since = "1.1.1.4", forRemoval = true)
public boolean isAttributeVersion() {
return this.version != NmsVersion.V_1_8_8.version;
}
/**
- * Gets the version number associated with the enumeration.
- *
- * @return The version number.
+ * @deprecated Use {@link MinecraftVersion#getMinor()} or comparisons via {@link MinecraftVersion} instead.
*/
+ @Deprecated(since = "1.1.1.4", forRemoval = true)
public int getVersion() {
return this.version;
}
+ /**
+ * @deprecated Use {@code MinecraftVersion.getCurrentVersion().isAtLeast(MinecraftVersion.parse("1.20.5"))} instead.
+ */
+ @Deprecated(since = "1.1.1.4", forRemoval = true)
public boolean isAttributItemStack() {
return this.version >= NmsVersion.V_1_20_5.version;
}
+ /**
+ * @deprecated Use {@code MinecraftVersion.getCurrentVersion().equals(MinecraftVersion.parse("1.8.8"))} instead.
+ */
+ @Deprecated(since = "1.1.1.4", forRemoval = true)
public boolean isOneHand() {
return this.version == NmsVersion.V_1_8_8.version;
}
+ /**
+ * @deprecated Use {@code MinecraftVersion.getCurrentVersion().isAtLeast(MinecraftVersion.parse("1.14"))} instead.
+ */
+ @Deprecated(since = "1.1.1.4", forRemoval = true)
public boolean isBarrel() {
return this.version >= V_1_14.version;
}
+ /**
+ * @deprecated Use {@code MinecraftVersion.getCurrentVersion().isAtLeast(MinecraftVersion.parse("1.9"))} instead.
+ */
+ @Deprecated(since = "1.1.1.4", forRemoval = true)
public boolean isShulker() {
return this.version >= V_1_9.version;
}
+ /**
+ * @deprecated Use {@code MinecraftVersion.getCurrentVersion().isAtLeast(MinecraftVersion.parse("1.13"))} instead.
+ */
+ @Deprecated(since = "1.1.1.4", forRemoval = true)
public boolean isNewMaterial() {
return this.version >= V_1_13.version;
}
+ /**
+ * @deprecated Use {@code MinecraftVersion.getCurrentVersion().isAtLeast(MinecraftVersion.parse("1.18"))} instead.
+ */
+ @Deprecated(since = "1.1.1.4", forRemoval = true)
public boolean isNewNBTVersion() {
return this.version >= V_1_18.version;
}
+ /**
+ * @deprecated Use {@code MinecraftVersion.getCurrentVersion().isAtLeast(MinecraftVersion.parse("1.20"))} instead.
+ */
+ @Deprecated(since = "1.1.1.4", forRemoval = true)
public boolean isNewHeadApi() {
return this.version >= V_1_20.version;
}
+ /**
+ * @deprecated Use {@code MinecraftVersion.getCurrentVersion().isAtLeast(MinecraftVersion.parse("1.17"))} instead.
+ */
+ @Deprecated(since = "1.1.1.4", forRemoval = true)
public boolean isNewNMSVersion() {
return this.version >= V_1_17.version;
}
+ /**
+ * @deprecated Use {@code MinecraftVersion.getCurrentVersion().isAtLeast(MinecraftVersion.parse("1.11"))} instead.
+ */
+ @Deprecated(since = "1.1.1.4", forRemoval = true)
public boolean is1_11OrNewer() {
return this.version >= V_1_11.version;
}
+ /**
+ * @deprecated Use {@code MinecraftVersion.getCurrentVersion().isAtLeast(MinecraftVersion.parse("1.12"))} instead.
+ */
+ @Deprecated(since = "1.1.1.4", forRemoval = true)
public boolean is1_12OrNewer() {
return this.version >= V_1_12.version;
}
+ /**
+ * @deprecated Use {@code MinecraftVersion.getCurrentVersion().isAtLeast(MinecraftVersion.parse("1.21"))} instead.
+ */
+ @Deprecated(since = "1.1.1.4", forRemoval = true)
public boolean isNewItemStackAPI() {
return this.version >= V_1_21.version;
}
+ /**
+ * @deprecated Use {@code MinecraftVersion.getCurrentVersion().isAtLeast(MinecraftVersion.parse("1.21.4"))} instead.
+ */
+ @Deprecated(since = "1.1.1.4", forRemoval = true)
public boolean isNewItemModelAPI() {
return this.version >= V_1_21_4.version;
}
+ /**
+ * @deprecated Use {@code MinecraftVersion.getCurrentVersion().isAtLeast(MinecraftVersion.parse("1.21.7"))} instead.
+ */
+ @Deprecated(since = "1.1.1.4", forRemoval = true)
public boolean isDialogsVersion() {
return this.version >= V_1_21_7.version;
}
+ /**
+ * @deprecated Use {@code MinecraftVersion.getCurrentVersion().isAtLeast(MinecraftVersion.parse("1.21.2"))} instead.
+ */
+ @Deprecated(since = "1.1.1.4", forRemoval = true)
public boolean is1_21_2OrNewer() {
return this.version >= V_1_21_2.version;
}
+ /**
+ * @deprecated Use {@code MinecraftVersion.getCurrentVersion().isAtLeast(MinecraftVersion.parse("1.21.5"))} instead.
+ */
+ @Deprecated(since = "1.1.1.4", forRemoval = true)
public boolean is1_21_5OrNewer() {
return this.version >= V_1_21_5.version;
}
+ /**
+ * @deprecated Use {@code MinecraftVersion.getCurrentVersion().isAtLeast(MinecraftVersion.parse("1.21.9"))} instead.
+ */
+ @Deprecated(since = "1.1.1.4", forRemoval = true)
public boolean is1_21_9OrNewer() {
return this.version >= V_1_21_9.version;
}
+ /**
+ * @deprecated Use {@code MinecraftVersion.getCurrentVersion().isAtLeast(MinecraftVersion.parse("1.21.11"))} instead.
+ */
+ @Deprecated(since = "1.1.1.4", forRemoval = true)
public boolean is1_21_11OrNewer() {
return this.version >= V_1_21_11.version;
}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/fr/maxlego08/menu/inventory/VInventory.java b/Common/src/main/java/fr/maxlego08/menu/inventory/VInventory.java
similarity index 84%
rename from src/main/java/fr/maxlego08/menu/inventory/VInventory.java
rename to Common/src/main/java/fr/maxlego08/menu/inventory/VInventory.java
index d83dc1ff..174902cb 100644
--- a/src/main/java/fr/maxlego08/menu/inventory/VInventory.java
+++ b/Common/src/main/java/fr/maxlego08/menu/inventory/VInventory.java
@@ -1,7 +1,7 @@
package fr.maxlego08.menu.inventory;
-import fr.maxlego08.menu.ZMenuPlugin;
import fr.maxlego08.menu.api.InventoryListener;
+import fr.maxlego08.menu.api.MenuPlugin;
import fr.maxlego08.menu.api.animation.PlayerTitleAnimation;
import fr.maxlego08.menu.api.animation.TitleAnimation;
import fr.maxlego08.menu.api.configuration.Configuration;
@@ -11,6 +11,7 @@
import fr.maxlego08.menu.api.exceptions.InventoryOpenException;
import fr.maxlego08.menu.api.utils.ClearInvType;
import fr.maxlego08.menu.common.utils.ZUtils;
+import fr.maxlego08.menu.zcore.logger.Logger;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryClickEvent;
@@ -20,6 +21,7 @@
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import org.jspecify.annotations.NonNull;
import java.util.HashMap;
@@ -28,7 +30,7 @@
public abstract class VInventory extends ZUtils implements Cloneable, BaseInventory {
protected int id;
- protected ZMenuPlugin plugin;
+ protected MenuPlugin plugin;
protected final Map items = new HashMap<>();
protected final Map playerInventoryItems = new HashMap<>();
protected Player player;
@@ -110,7 +112,8 @@ public ItemButton addItem(boolean inPlayerInventory, int slot, ItemStack itemSta
this.createDefaultInventory();
if (itemStack == null) {
- this.plugin.getLogger().severe("Attention, a null ItemStack was found in slot " + slot + " ! > " + this);
+ if (Configuration.enableDebug)
+ Logger.info("Attention, a null ItemStack was found in slot " + slot + " ! > " + this, Logger.LogType.ERROR);
return null;
}
@@ -162,6 +165,11 @@ public void clearItem() {
return this.items;
}
+ @Nullable
+ public ItemButton getItem(int slot) {
+ return this.items.get(slot);
+ }
+
@Override
public @NonNull Map getPlayerInventoryItems() {
return this.playerInventoryItems;
@@ -201,7 +209,7 @@ public String getGuiName() {
return this.guiName;
}
- protected InventoryResult preOpenInventory(@NotNull ZMenuPlugin main, Player player, int page, Object... args) throws InventoryOpenException {
+ protected InventoryResult preOpenInventory(@NotNull MenuPlugin main, Player player, int page, Object... args) throws InventoryOpenException {
this.page = page;
this.args = args;
@@ -211,9 +219,9 @@ protected InventoryResult preOpenInventory(@NotNull ZMenuPlugin main, Player pla
return this.openInventory(main, player, page, args);
}
- public abstract InventoryResult openInventory(ZMenuPlugin main, Player player, int page, Object... args) throws InventoryOpenException;
+ public abstract InventoryResult openInventory(MenuPlugin main, Player player, int page, Object... args) throws InventoryOpenException;
- protected void onPreClose(InventoryCloseEvent event, ZMenuPlugin plugin, Player player) {
+ protected void onPreClose(InventoryCloseEvent event, MenuPlugin plugin, Player player) {
this.isClose = true;
if (this.playerTitleAnimation != null){
this.playerTitleAnimation.stop();
@@ -221,17 +229,21 @@ protected void onPreClose(InventoryCloseEvent event, ZMenuPlugin plugin, Player
this.onClose(event, plugin, player);
}
- protected void onClose(InventoryCloseEvent event, ZMenuPlugin plugin, Player player) {
+ protected void onClose(InventoryCloseEvent event, MenuPlugin plugin, Player player) {
}
- protected void onDrag(InventoryDragEvent event, ZMenuPlugin plugin, Player player) {
+ protected void onInventorySwitch(InventoryCloseEvent event, Player player, VInventory newInventoryEngine) {
+ this.onPreClose(event, this.plugin, player);
}
- public @NonNull ZMenuPlugin getPlugin() {
+ protected void onDrag(InventoryDragEvent event, MenuPlugin plugin, Player player) {
+ }
+
+ public @NonNull MenuPlugin getPlugin() {
return this.plugin;
}
- public void setPlugin(ZMenuPlugin plugin) {
+ public void setPlugin(MenuPlugin plugin) {
this.plugin = plugin;
}
@@ -245,9 +257,11 @@ protected VInventory clone() {
return null;
}
- public void postOpen(ZMenuPlugin plugin, Player player, int page, Object[] objects) {
+ public void postOpen(MenuPlugin plugin, Player player, int page, Object[] objects) {
}
+ protected void onPostOpen(Player player, MenuPlugin plugin, int page, Object[] objects) {}
+
@Override
public @NotNull Inventory getInventory() {
return this.inventory;
@@ -302,7 +316,7 @@ public boolean isClickLimiterEnabled() {
return this.isClickLimiterEnabled;
}
- public void onInventoryClick(InventoryClickEvent event, ZMenuPlugin plugin, Player player) {
+ public void onInventoryClick(InventoryClickEvent event, MenuPlugin plugin, Player player) {
}
}
diff --git a/Common/src/main/java/fr/maxlego08/menu/inventory/inventories/AnvilInventoryDefault.java b/Common/src/main/java/fr/maxlego08/menu/inventory/inventories/AnvilInventoryDefault.java
new file mode 100644
index 00000000..45466b88
--- /dev/null
+++ b/Common/src/main/java/fr/maxlego08/menu/inventory/inventories/AnvilInventoryDefault.java
@@ -0,0 +1,132 @@
+package fr.maxlego08.menu.inventory.inventories;
+
+import fr.maxlego08.menu.api.MenuPlugin;
+import fr.maxlego08.menu.api.button.Button;
+import fr.maxlego08.menu.api.engine.AnvilInventoryEngine;
+import fr.maxlego08.menu.api.engine.ItemButton;
+import fr.maxlego08.menu.api.inventory.AnvilInventory;
+import fr.maxlego08.menu.api.requirement.Requirement;
+import fr.maxlego08.menu.api.utils.Placeholders;
+import fr.maxlego08.menu.api.utils.TextChange;
+import fr.maxlego08.menu.api.utils.TextChangeType;
+import fr.maxlego08.menu.common.network.NMSMenuPacketListener;
+import fr.maxlego08.menu.common.network.PacketQueue;
+import fr.maxlego08.menu.inventory.VInventory;
+import net.minecraft.network.protocol.Packet;
+import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket;
+import net.minecraft.network.protocol.game.ServerGamePacketListener;
+import net.minecraft.network.protocol.game.ServerboundRenameItemPacket;
+import net.minecraft.world.item.ItemStack;
+import org.bukkit.craftbukkit.entity.CraftPlayer;
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.InventoryCloseEvent;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+public class AnvilInventoryDefault extends InventoryDefault implements AnvilInventoryEngine {
+ private PacketQueue> incomingPackets;
+ private String currentText = "";
+ private volatile int containerId;
+
+
+ private boolean firstPacketReceived = false;
+
+ private TextChange updateText(String newText) {
+ if (newText == null) newText = "";
+ TextChange change = TextChange.compute(currentText, newText);
+ currentText = newText;
+ return change;
+ }
+
+ @Override
+ protected void onPostOpen(Player player, MenuPlugin plugin, int page, Object[] objects) {
+
+ this.containerId = ((CraftPlayer) player).getHandle().containerMenu.containerId;
+
+ super.onPostOpen(player, plugin, page, objects);
+ }
+
+ @Override
+ public @NotNull String getCurrentText() {
+ return this.currentText;
+ }
+
+ @Override
+ public void postOpen(MenuPlugin plugin, Player player, int page, Object[] objects) {
+ incomingPackets = PacketQueue.>builder()
+ .on(ServerboundRenameItemPacket.class, packet -> {
+ if (!(this.getMenuInventory() instanceof AnvilInventory anvilInventory)) return;
+
+ TextChange textChange = updateText(packet.getName());
+
+ if (!firstPacketReceived && textChange.type() == TextChangeType.EQUAL) {
+ // The client sends an initial packet with the default text when the menu is opened, ignore it
+ firstPacketReceived = true;
+ return;
+ }
+
+ Placeholders placeholders = new Placeholders();
+
+ ItemButton item = this.getItem(2);
+
+ if (item != null) {
+ ItemStack nmsCopy = CraftItemStack.asNMSCopy(item.getDisplayItem());
+ ClientboundContainerSetSlotPacket clientboundContainerSetSlotPacket = new ClientboundContainerSetSlotPacket(
+ containerId,
+ 8,
+ 2,
+ nmsCopy
+ );
+
+ NMSMenuPacketListener.get().sendPacket(player, clientboundContainerSetSlotPacket);
+ }
+
+ placeholders.register("type", textChange.type().name());
+ placeholders.register("old_text", textChange.oldText());
+ switch (textChange.type()) {
+ case ADDED, REMOVED -> {
+ placeholders.register("char", String.valueOf(textChange.changedChar()));
+ placeholders.register("new_text", textChange.newText());
+ }
+ case CLEARED -> placeholders.register("new_text", "");
+ case REPLACED, EQUAL -> placeholders.register("new_text", textChange.newText());
+ }
+
+ for (Requirement requirement : anvilInventory.getRenameRequirements()) {
+ requirement.execute(player, null, this, placeholders);
+ }
+
+ List buttons = getButtons();
+ for (Button button : buttons) {
+ button.onAnvilTextChange(player, this, textChange, placeholders);
+ }
+
+ })
+ .build()
+ .schedule(plugin, player);
+
+ NMSMenuPacketListener.get().redirectIncoming(player, ServerboundRenameItemPacket.class, incomingPackets);
+
+ super.postOpen(plugin, player, page, objects);
+ }
+
+ @Override
+ protected void onClose(InventoryCloseEvent event, MenuPlugin plugin, Player player) {
+ NMSMenuPacketListener.get().stopRedirecting(player, ServerboundRenameItemPacket.class);
+ incomingPackets.cancel();
+ super.onClose(event, plugin, player);
+ }
+
+ @Override
+ protected void onInventorySwitch(InventoryCloseEvent event, Player player, VInventory newInventoryEngine) {
+ // Don't
+ if (!(newInventoryEngine instanceof AnvilInventoryEngine)) {
+ this.onClose(event, this.plugin, player);
+ } else {
+ incomingPackets.cancel();
+ super.onClose(event, this.plugin, player);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/fr/maxlego08/menu/inventory/inventories/InventoryDefault.java b/Common/src/main/java/fr/maxlego08/menu/inventory/inventories/InventoryDefault.java
similarity index 83%
rename from src/main/java/fr/maxlego08/menu/inventory/inventories/InventoryDefault.java
rename to Common/src/main/java/fr/maxlego08/menu/inventory/inventories/InventoryDefault.java
index 6e60d212..0d05108d 100644
--- a/src/main/java/fr/maxlego08/menu/inventory/inventories/InventoryDefault.java
+++ b/Common/src/main/java/fr/maxlego08/menu/inventory/inventories/InventoryDefault.java
@@ -1,14 +1,17 @@
package fr.maxlego08.menu.inventory.inventories;
import com.tcoded.folialib.wrapper.task.WrappedTask;
-import fr.maxlego08.menu.ZMenuPlugin;
import fr.maxlego08.menu.api.Inventory;
import fr.maxlego08.menu.api.InventoryManager;
+import fr.maxlego08.menu.api.MenuItemStack;
+import fr.maxlego08.menu.api.MenuPlugin;
import fr.maxlego08.menu.api.button.Button;
import fr.maxlego08.menu.api.engine.InventoryEngine;
import fr.maxlego08.menu.api.engine.InventoryResult;
import fr.maxlego08.menu.api.engine.ItemButton;
import fr.maxlego08.menu.api.exceptions.InventoryOpenException;
+import fr.maxlego08.menu.api.inventory.ChestInventory;
+import fr.maxlego08.menu.api.inventory.ContainerInventory;
import fr.maxlego08.menu.api.pattern.Pattern;
import fr.maxlego08.menu.api.requirement.RefreshRequirement;
import fr.maxlego08.menu.api.utils.Placeholders;
@@ -44,7 +47,7 @@ public class InventoryDefault extends VInventory implements InventoryEngine {
private List updatedButtons = Collections.emptyList();
@Override
- public InventoryResult openInventory(ZMenuPlugin main, Player player, int page, Object... args) throws InventoryOpenException {
+ public InventoryResult openInventory(MenuPlugin main, Player player, int page, Object... args) throws InventoryOpenException {
this.inventory = (Inventory) args[0];
this.perfDebug = PerformanceDebug.create("inventory:" + this.inventory.getFileName());
@@ -56,8 +59,10 @@ public InventoryResult openInventory(ZMenuPlugin main, Player player, int page,
return result;
}
- super.setClearInvType(this.inventory.getClearInvType());
- super.setClickLimiterEnabled(this.inventory.isClickLimiterEnabled());
+ if (this.inventory instanceof ContainerInventory containerInventory) {
+ super.setClearInvType(containerInventory.getClearInvType());
+ super.setClickLimiterEnabled(containerInventory.isClickLimiterEnabled());
+ }
this.oldInventories = this.extractOldInventories(args);
@@ -112,27 +117,33 @@ public InventoryResult openInventory(ZMenuPlugin main, Player player, int page,
String parsedName = super.papi(placeholders.parse(inventoryName), targetPlayer, false);
this.perfDebug.end();
- this.perfDebug.start("openInventory.createMetaInventory");
- if (this.inventory.getType() == InventoryType.CHEST) {
- super.createMetaInventory(parsedName, this.inventory.size());
- } else {
- super.createMetaInventory(parsedName, this.inventory.getType());
- }
- super.setTitleAnimation(this.inventory.getTitleAnimation());
- this.perfDebug.end();
+ if (this.inventory instanceof ContainerInventory containerInventory) {
+ this.perfDebug.start("openInventory.createMetaInventory");
+ if (containerInventory.getType() == InventoryType.CHEST && containerInventory instanceof ChestInventory chestInventory) {
+ super.createMetaInventory(parsedName, chestInventory.size());
+ } else {
+ super.createMetaInventory(parsedName, containerInventory.getType());
+ }
+ this.perfDebug.end();
+
- // Display fill items
- this.perfDebug.start("openInventory.fillItems");
- if (this.inventory.getFillItemStack() != null) {
- ItemStack builtItem = this.inventory.getFillItemStack().build(player);
- if (builtItem != null) {
- ItemStack[] contents = super.getSpigotInventory().getContents();
- for (int slot = 0; slot < contents.length; slot++) {
- this.addItem(slot, builtItem.clone());
+ super.setTitleAnimation(containerInventory.getTitleAnimation());
+
+ // Display fill items
+ this.perfDebug.start("openInventory.fillItems");
+ MenuItemStack fillItemStack = containerInventory.getFillItemStack();
+ if (fillItemStack != null) {
+ ItemStack builtItem = fillItemStack.build(player);
+ if (builtItem != null) {
+ ItemStack[] contents = super.getSpigotInventory().getContents();
+ for (int slot = 0; slot < contents.length; slot++) {
+ this.addItem(slot, builtItem.clone());
+ }
}
}
+ this.perfDebug.end();
}
- this.perfDebug.end();
+
// Display buttons
for (Button button : this.buttons) {
@@ -160,24 +171,24 @@ public InventoryResult openInventory(ZMenuPlugin main, Player player, int page,
}
@Override
- public void postOpen(ZMenuPlugin plugin, Player player, int page, Object[] objects) {
+ public void postOpen(MenuPlugin plugin, Player player, int page, Object[] objects) {
this.inventory.postOpenInventory(player, this);
}
@Override
- protected void onClose(InventoryCloseEvent event, ZMenuPlugin plugin, Player player) {
+ protected void onClose(InventoryCloseEvent event, MenuPlugin plugin, Player player) {
this.inventory.closeInventory(player, this);
this.buttons.forEach(button -> button.onInventoryClose(player, this));
}
@Override
- protected void onDrag(InventoryDragEvent event, ZMenuPlugin plugin, Player player) {
+ protected void onDrag(InventoryDragEvent event, MenuPlugin plugin, Player player) {
this.buttons.forEach(button -> button.onDrag(event, player, this));
}
@Override
- public void onInventoryClick(InventoryClickEvent event, ZMenuPlugin plugin, Player player) {
+ public void onInventoryClick(InventoryClickEvent event, MenuPlugin plugin, Player player) {
this.buttons.forEach(button -> button.onInventoryClick(event, player, this));
}
@@ -197,15 +208,9 @@ public void buildButton(Button button, @NonNull Placeholders placeholders) {
return;
}
final Player targetPlayer = this.getTargetPlayer();
- if (button.hasCustomRender()) {
- this.perfDebug.start("onRender." + button.getName());
- button.onRender(targetPlayer, this);
- this.perfDebug.end();
- return;
- }
this.perfDebug.start("getDisplayButton." + button.getName());
- button = button.getDisplayButton(this, this.player);
+ button = button.getDisplayButton(this, targetPlayer);
this.perfDebug.end();
if (button == null) {
return;
@@ -231,13 +236,25 @@ public void buildButton(Button button, @NonNull Placeholders placeholders) {
} else {
// If the player has the permission, the button
- this.displayButton(button, placeholders);
+ if (button.hasCustomRender()) {
+ this.perfDebug.start("onRender." + button.getName());
+ button.onRender(targetPlayer, this);
+ this.perfDebug.end();
+ } else {
+ this.displayButton(button, placeholders);
+ }
}
} else {
// If there is no permission, then the button
- this.displayButton(button, placeholders);
+ if (button.hasCustomRender()) {
+ this.perfDebug.start("onRender." + button.getName());
+ button.onRender(targetPlayer, this);
+ this.perfDebug.end();
+ } else {
+ this.displayButton(button, placeholders);
+ }
}
}
@@ -266,7 +283,18 @@ public void displayButton(@NotNull Button button, @NotNull Placeholders placehol
runnable = w -> {
this.perfDebug.start("getRealSlot." + button.getName());
- int slot = button.getRealSlot(button.isPlayerInventory() ? 36 : this.inventory.size(), this.page);
+ int slot;
+ if (button.isPlayerInventory()) {
+ slot = button.getRealSlot(36, this.page);
+ } else {
+ if (this.inventory instanceof ChestInventory chestInventory) {
+ slot = button.getRealSlot(chestInventory.size(), this.page);
+ } else {
+ //noinspection deprecation
+ slot = button.getRealSlot(this.inventory.size(), this.page);
+ }
+ }
+
this.perfDebug.end();
this.displayFinalButton(button, placeholders, slot);
};
@@ -343,7 +371,7 @@ public void displayFinalButton(@NotNull Button button, @NotNull Placeholders pla
}
if (button.isDraggable()) {
- //If one button is draggrable enable click
+ //If one button is draggable enable click
super.setDisablePlayerInventoryClick(false);
}
diff --git a/Common/src/main/java/fr/maxlego08/menu/inventory/setter/AnvilInventorySetter.java b/Common/src/main/java/fr/maxlego08/menu/inventory/setter/AnvilInventorySetter.java
new file mode 100644
index 00000000..6f19ea79
--- /dev/null
+++ b/Common/src/main/java/fr/maxlego08/menu/inventory/setter/AnvilInventorySetter.java
@@ -0,0 +1,6 @@
+package fr.maxlego08.menu.inventory.setter;
+
+import fr.maxlego08.menu.api.inventory.AnvilInventory;
+
+public interface AnvilInventorySetter extends AnvilInventory, ContainerInventorySetter {
+}
diff --git a/Common/src/main/java/fr/maxlego08/menu/inventory/setter/ChestInventorySetter.java b/Common/src/main/java/fr/maxlego08/menu/inventory/setter/ChestInventorySetter.java
new file mode 100644
index 00000000..54dd236b
--- /dev/null
+++ b/Common/src/main/java/fr/maxlego08/menu/inventory/setter/ChestInventorySetter.java
@@ -0,0 +1,6 @@
+package fr.maxlego08.menu.inventory.setter;
+
+import fr.maxlego08.menu.api.inventory.ChestInventory;
+
+public interface ChestInventorySetter extends ChestInventory, ContainerInventorySetter {
+}
diff --git a/Common/src/main/java/fr/maxlego08/menu/inventory/setter/ContainerInventorySetter.java b/Common/src/main/java/fr/maxlego08/menu/inventory/setter/ContainerInventorySetter.java
new file mode 100644
index 00000000..1dd0ce63
--- /dev/null
+++ b/Common/src/main/java/fr/maxlego08/menu/inventory/setter/ContainerInventorySetter.java
@@ -0,0 +1,46 @@
+package fr.maxlego08.menu.inventory.setter;
+
+import fr.maxlego08.menu.api.MenuItemStack;
+import fr.maxlego08.menu.api.inventory.ContainerInventory;
+import fr.maxlego08.menu.api.pattern.Pattern;
+import fr.maxlego08.menu.api.requirement.Action;
+import fr.maxlego08.menu.api.requirement.Requirement;
+import fr.maxlego08.menu.api.utils.ClearInvType;
+import fr.maxlego08.menu.api.utils.OpenWithItem;
+import org.bukkit.event.inventory.InventoryType;
+
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+
+public interface ContainerInventorySetter extends ContainerInventory {
+ void setType(InventoryType type);
+
+ void setCancelItemPickup(boolean ItemPickupDisabled);
+
+ void setFillItemStack(MenuItemStack fillItemStack);
+
+ void setUpdateInterval(int updateInterval);
+
+ void setFile(File file);
+
+ void setOpenRequirement(Requirement openRequirement);
+
+ void setOpenWithItem(OpenWithItem openWithItem);
+
+ void setTranslatedNames(Map translatedNames);
+
+ void setClearInventory(boolean clearInventory);
+
+ void setPatterns(List patterns);
+
+ void setTargetPlayerNamePlaceholder(String targetPlaceholder);
+
+ void setOpenActions(List openActions);
+
+ void setCloseActions(List closeActions);
+
+ void setClickLimiterEnabled(boolean enabled);
+
+ void setClearInvType(ClearInvType clearInvType);
+}
diff --git a/Common/src/main/java/fr/maxlego08/menu/inventory/zinv/ZAnvilInventory.java b/Common/src/main/java/fr/maxlego08/menu/inventory/zinv/ZAnvilInventory.java
new file mode 100644
index 00000000..a199a75e
--- /dev/null
+++ b/Common/src/main/java/fr/maxlego08/menu/inventory/zinv/ZAnvilInventory.java
@@ -0,0 +1,23 @@
+package fr.maxlego08.menu.inventory.zinv;
+
+import fr.maxlego08.menu.api.button.Button;
+import fr.maxlego08.menu.api.requirement.Requirement;
+import fr.maxlego08.menu.inventory.setter.AnvilInventorySetter;
+import org.bukkit.plugin.Plugin;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+public class ZAnvilInventory extends ZInventory implements AnvilInventorySetter {
+ private final List renameRequirements;
+
+ public ZAnvilInventory(Plugin plugin, String name, String fileName, int size, List buttons, List renameRequirements) {
+ super(plugin, name, fileName, size, buttons);
+ this.renameRequirements = renameRequirements;
+ }
+
+ @Override
+ public @NotNull List getRenameRequirements() {
+ return renameRequirements;
+ }
+}
diff --git a/Common/src/main/java/fr/maxlego08/menu/inventory/zinv/ZChestInventory.java b/Common/src/main/java/fr/maxlego08/menu/inventory/zinv/ZChestInventory.java
new file mode 100644
index 00000000..dc669b4b
--- /dev/null
+++ b/Common/src/main/java/fr/maxlego08/menu/inventory/zinv/ZChestInventory.java
@@ -0,0 +1,22 @@
+package fr.maxlego08.menu.inventory.zinv;
+
+import fr.maxlego08.menu.api.button.Button;
+import fr.maxlego08.menu.inventory.setter.ChestInventorySetter;
+import org.bukkit.plugin.Plugin;
+
+import java.util.List;
+
+public class ZChestInventory extends ZInventory implements ChestInventorySetter {
+ /**
+ * @param plugin The plugin where the inventory comes from
+ * @param name Inventory name
+ * @param fileName Inventory file name
+ * @param size Inventory size
+ * @param buttons List of {@link Button}
+ */
+ public ZChestInventory(Plugin plugin, String name, String fileName, int size, List buttons) {
+ super(plugin, name, fileName, size, buttons);
+ }
+
+
+}
diff --git a/src/main/java/fr/maxlego08/menu/ZInventory.java b/Common/src/main/java/fr/maxlego08/menu/inventory/zinv/ZInventory.java
similarity index 88%
rename from src/main/java/fr/maxlego08/menu/ZInventory.java
rename to Common/src/main/java/fr/maxlego08/menu/inventory/zinv/ZInventory.java
index b2349474..0150c1b4 100644
--- a/src/main/java/fr/maxlego08/menu/ZInventory.java
+++ b/Common/src/main/java/fr/maxlego08/menu/inventory/zinv/ZInventory.java
@@ -1,13 +1,14 @@
-package fr.maxlego08.menu;
+package fr.maxlego08.menu.inventory.zinv;
-import fr.maxlego08.menu.api.Inventory;
import fr.maxlego08.menu.api.MenuItemStack;
+import fr.maxlego08.menu.api.MenuPlugin;
import fr.maxlego08.menu.api.animation.TitleAnimation;
import fr.maxlego08.menu.api.button.Button;
import fr.maxlego08.menu.api.button.PaginateButton;
import fr.maxlego08.menu.api.configuration.Configuration;
import fr.maxlego08.menu.api.engine.InventoryEngine;
import fr.maxlego08.menu.api.engine.InventoryResult;
+import fr.maxlego08.menu.api.inventory.ContainerInventory;
import fr.maxlego08.menu.api.pattern.Pattern;
import fr.maxlego08.menu.api.players.inventory.InventoriesPlayer;
import fr.maxlego08.menu.api.requirement.Action;
@@ -16,16 +17,18 @@
import fr.maxlego08.menu.api.utils.*;
import fr.maxlego08.menu.common.utils.ZUtils;
import fr.maxlego08.menu.inventory.inventories.InventoryDefault;
+import fr.maxlego08.menu.inventory.setter.ContainerInventorySetter;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.plugin.Plugin;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.util.*;
-public class ZInventory extends ZUtils implements Inventory {
+public class ZInventory extends ZUtils implements ContainerInventorySetter {
private final Plugin plugin;
private final String name;
@@ -46,7 +49,7 @@ public class ZInventory extends ZUtils implements Inventory {
private Requirement openRequirement;
private OpenWithItem openWithItem;
private InventoryType type = InventoryType.CHEST;
- private String targetPlayerNamePlaceholder;
+ private String targetPlayerNamePlaceholder = null;
private TitleAnimation titleAnimation;
private List openActions = new ArrayList<>();
private List closeActions = new ArrayList<>();
@@ -78,7 +81,7 @@ public String getName() {
}
@Override
- public String getName(Player player, InventoryEngine inventoryDefault, Placeholders placeholders) {
+ public String getName(@NotNull Player player, InventoryEngine inventoryDefault, Placeholders placeholders) {
if (!this.conditionalNames.isEmpty()) {
ConditionalName selected = null;
@@ -106,7 +109,8 @@ public InventoryType getType() {
return this.type;
}
- public void setType(InventoryType type) {
+ @Override
+ public void setType(@NotNull InventoryType type) {
this.type = type;
}
@@ -115,6 +119,7 @@ public boolean shouldCancelItemPickup() {
return this.ItemPickupDisabled;
}
+ @Override
public void setCancelItemPickup(boolean ItemPickupDisabled) {
this.ItemPickupDisabled = ItemPickupDisabled;
}
@@ -228,27 +233,21 @@ public InventoryResult openInventory(Player player, InventoryEngine inventoryDef
if (holder instanceof InventoryDefault inventoryHolder) {
this.clearPlayerInventoryButtons(player, inventoryHolder);
- if (inventoryHolder.getMenuInventory().cleanInventory() && !this.clearInventory) {
+ if (inventoryHolder.getMenuInventory() instanceof ContainerInventory containerInventory && containerInventory.clearInventory() && !this.clearInventory) {
inventoriesPlayer.giveInventory(player);
} else if (this.clearInventory) {
if (this.clearInvType == ClearInvType.DEFAULT){
inventoriesPlayer.storeInventory(player);
} else {
- if (inventoriesPlayer.hasSavedInventory(player.getUniqueId())) {
- inventoriesPlayer.getPlayerInventory(player.getUniqueId()).ifPresent(inventoryPlayer -> {
- for (int slot : inventoryPlayer.getItems().keySet()) {
- player.getInventory().setItem(slot, null);
- this.clearInvType.getRemoveItem().accept(player, slot, player.getInventory());
- }
- });
- } else {
- removePlayerInventoryButtons(player, inventoryHolder);
- inventoriesPlayer.storeInventory(player);
- }
+ inventoriesPlayer.storeInventoryTemporaryOrClear(player);
}
}
} else if (this.clearInventory) {
- inventoriesPlayer.storeInventory(player);
+ if (this.clearInvType == ClearInvType.DEFAULT) {
+ inventoriesPlayer.storeInventory(player);
+ } else {
+ inventoriesPlayer.storeInventoryTemporary(player);
+ }
}
var placeholders = new Placeholders();
@@ -269,12 +268,6 @@ private void clearPlayerInventoryButtons(Player player, InventoryEngine inventor
}
}
- private void removePlayerInventoryButtons(Player player, InventoryEngine inventoryDefault) {
- for (int slot : inventoryDefault.getPlayerInventoryItems().keySet()) {
- player.getInventory().setItem(slot, null);
- }
- }
-
@Override
public void postOpenInventory(Player player, InventoryEngine inventoryDefault) {
@@ -283,15 +276,16 @@ public void postOpenInventory(Player player, InventoryEngine inventoryDefault) {
@Override
public void closeInventory(Player player, InventoryEngine inventoryDefault) {
- ZMenuPlugin.getInstance().getScheduler().runAtEntityLater(player, task -> {
+ MenuPlugin menuPlugin = inventoryDefault.getPlugin();
+ menuPlugin.getScheduler().runAtEntityLater(player, task -> {
InventoryHolder newHolder = CompatibilityUtil.getTopInventory(player).getHolder();
boolean isInNewzMenuInventory = newHolder instanceof InventoryDefault;
if (newHolder != null && !(newHolder instanceof InventoryDefault)) {
this.clearPlayerInventoryButtons(player, inventoryDefault);
if (this.clearInventory) {
- InventoriesPlayer inventoriesPlayer = inventoryDefault.getPlugin().getInventoriesPlayer();
- inventoriesPlayer.giveInventory(player);
+ InventoriesPlayer inventoriesPlayer = menuPlugin.getInventoriesPlayer();
+ this.clearInvType.getOnInventoryClose().accept(inventoriesPlayer, player);
}
}
var placeholders = new Placeholders();
@@ -313,6 +307,7 @@ public MenuItemStack getFillItemStack() {
return this.fillItemStack;
}
+ @Override
public void setFillItemStack(MenuItemStack fillItemStack) {
this.fillItemStack = fillItemStack;
}
@@ -322,6 +317,7 @@ public int getUpdateInterval() {
return this.updateInterval;
}
+ @Override
public void setUpdateInterval(int updateInterval) {
this.updateInterval = updateInterval;
}
@@ -340,6 +336,7 @@ public File getFile() {
return this.file;
}
+ @Override
public void setFile(File file) {
this.file = file;
}
@@ -354,6 +351,7 @@ public Requirement getOpenRequirement() {
return this.openRequirement;
}
+ @Override
public void setOpenRequirement(Requirement openRequirement) {
this.openRequirement = openRequirement;
}
@@ -363,6 +361,7 @@ public OpenWithItem getOpenWithItem() {
return this.openWithItem;
}
+ @Override
public void setOpenWithItem(OpenWithItem openWithItem) {
this.openWithItem = openWithItem;
}
@@ -372,6 +371,7 @@ public Map getTranslatedNames() {
return this.translatedNames;
}
+ @Override
public void setTranslatedNames(Map translatedNames) {
this.translatedNames = translatedNames;
}
@@ -381,6 +381,7 @@ public List getConditionalNames() {
return this.conditionalNames;
}
+ @Override
public void setClearInventory(boolean clearInventory) {
this.clearInventory = clearInventory;
}
@@ -390,6 +391,7 @@ public List getPatterns() {
return this.patterns;
}
+ @Override
public void setPatterns(List patterns) {
this.patterns = patterns;
}
@@ -409,6 +411,7 @@ public TitleAnimation getTitleAnimation() {
return this.titleAnimation;
}
+ @Override
public void setTargetPlayerNamePlaceholder(String targetPlaceholder) {
this.targetPlayerNamePlaceholder = targetPlaceholder;
}
@@ -418,6 +421,7 @@ public List getOpenActions() {
return this.openActions;
}
+ @Override
public void setOpenActions(List openActions) {
this.openActions = openActions;
}
@@ -427,6 +431,7 @@ public List getCloseActions() {
return this.closeActions;
}
+ @Override
public void setCloseActions(List closeActions) {
this.closeActions = closeActions;
}
@@ -451,10 +456,12 @@ public void setInventoryReplacement(InventoryReplacement inventoryReplacement) {
this.inventoryReplacement = inventoryReplacement;
}
+ @Override
public void setClickLimiterEnabled(boolean enabled) {
this.isClickLimiterEnabled = enabled;
}
+ @Override
public void setClearInvType(ClearInvType clearInvType) {
this.clearInvType = clearInvType;
}
diff --git a/src/main/java/fr/maxlego08/menu/loader/components/spigot/SpigotAttackRangeItemComponentLoader.java b/Common/src/main/java/fr/maxlego08/menu/loader/components/AbstractAttackRangeItemComponentLoader.java
similarity index 58%
rename from src/main/java/fr/maxlego08/menu/loader/components/spigot/SpigotAttackRangeItemComponentLoader.java
rename to Common/src/main/java/fr/maxlego08/menu/loader/components/AbstractAttackRangeItemComponentLoader.java
index 00f75342..4a469a33 100644
--- a/src/main/java/fr/maxlego08/menu/loader/components/spigot/SpigotAttackRangeItemComponentLoader.java
+++ b/Common/src/main/java/fr/maxlego08/menu/loader/components/AbstractAttackRangeItemComponentLoader.java
@@ -1,72 +1,73 @@
-package fr.maxlego08.menu.loader.components.spigot;
+package fr.maxlego08.menu.loader.components;
import fr.maxlego08.menu.api.configuration.Configuration;
-import fr.maxlego08.menu.api.context.MenuItemStackContext;
-import fr.maxlego08.menu.api.itemstack.ItemComponent;
-import fr.maxlego08.menu.api.itemstack.components.AttackRangeComponent;
import fr.maxlego08.menu.api.loader.ItemComponentLoader;
import fr.maxlego08.menu.zcore.logger.Logger;
import org.bukkit.configuration.ConfigurationSection;
-import org.bukkit.configuration.file.YamlConfiguration;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import java.io.File;
+public abstract class AbstractAttackRangeItemComponentLoader extends ItemComponentLoader {
-public class SpigotAttackRangeItemComponentLoader extends ItemComponentLoader {
-
- public SpigotAttackRangeItemComponentLoader() {
+ public AbstractAttackRangeItemComponentLoader() {
super("attack-range");
}
- @Override
- public @Nullable ItemComponent load(@NotNull MenuItemStackContext context, @NotNull File file, @NotNull YamlConfiguration configuration, @NotNull String path, @Nullable ConfigurationSection componentSection) {
- if (componentSection == null) {
- return null;
- }
- double minReach = componentSection.getDouble("min-reach", 0f);
+ protected float getMinReach(ConfigurationSection section, String path) {
+ double minReach = section.getDouble("min-reach", 0f);
if (minReach > 64f || minReach < 0f) {
if (Configuration.enableDebug)
Logger.info("Invalid min-reach value in attack-range component at path: " + path + ". Value: " + minReach + ". It must be between 0 and 64. Using default value 0f.");
minReach = 0f;
}
- double maxReach = componentSection.getDouble("max-reach", 3f);
+ return (float) minReach;
+ }
+
+ protected float getMaxReach(ConfigurationSection section, String path) {
+ double maxReach = section.getDouble("max-reach", 3f);
if (maxReach > 64f || maxReach < 0f) {
if (Configuration.enableDebug)
Logger.info("Invalid max-reach value in attack-range component at path: " + path + ". Value: " + maxReach + ". It must be between 0 and 64. Using default value 3f.");
maxReach = 3f;
}
- double minCreativeReach = componentSection.getDouble("min-creative-reach", 0f);
+ return (float) maxReach;
+ }
+
+ protected float getMinCreativeReach(ConfigurationSection section, String path) {
+ double minCreativeReach = section.getDouble("min-creative-reach", 0f);
if (minCreativeReach > 64f || minCreativeReach < 0f) {
if (Configuration.enableDebug)
Logger.info("Invalid min-creative-reach value in attack-range component at path: " + path + ". Value: " + minCreativeReach + ". It must be between 0 and 64. Using default value 0f.");
minCreativeReach = 0f;
}
- double maxCreativeReach = componentSection.getDouble("max-creative-reach", 5f);
+ return (float) minCreativeReach;
+ }
+
+ protected float getMaxCreativeReach(ConfigurationSection section, String path) {
+ double maxCreativeReach = section.getDouble("max-creative-reach", 5f);
if (maxCreativeReach > 64f || maxCreativeReach < 0f) {
if (Configuration.enableDebug)
Logger.info("Invalid max-creative-reach value in attack-range component at path: " + path + ". Value: " + maxCreativeReach + ". It must be between 0 and 64. Using default value 5f.");
maxCreativeReach = 5f;
}
- double hitboxMargin = componentSection.getDouble("hitbox-margin", 0.3f);
+ return (float) maxCreativeReach;
+ }
+
+ protected float getHitboxMargin(ConfigurationSection section, String path) {
+ double hitboxMargin = section.getDouble("hitbox-margin", 0.3f);
if (hitboxMargin < 0f || hitboxMargin > 1f) {
if (Configuration.enableDebug)
Logger.info("Invalid hitbox-margin value in attack-range component at path: " + path + ". Value: " + hitboxMargin + ". It must be between 0 and 1. Using default value 0.3f.");
hitboxMargin = 0.3f;
}
- double mobFactor = componentSection.getDouble("mob-factor", 1f);
+ return (float) hitboxMargin;
+ }
+
+ protected float getMobFactor(ConfigurationSection section, String path) {
+ double mobFactor = section.getDouble("mob-factor", 1f);
if (mobFactor < 0f || mobFactor > 2f) {
if (Configuration.enableDebug)
Logger.info("Invalid mob-factor value in attack-range component at path: " + path + ". Value: " + mobFactor + ". It must be between 0 and 2. Using default value 1f.");
mobFactor = 1f;
}
- return new AttackRangeComponent(
- (float) minReach,
- (float) maxReach,
- (float) minCreativeReach,
- (float) maxCreativeReach,
- (float) hitboxMargin,
- (float) mobFactor
- );
+ return (float) mobFactor;
}
}
diff --git a/Common/src/main/java/fr/maxlego08/menu/loader/components/spigot/SpigotCustomModelDataItemComponentLoader.java b/Common/src/main/java/fr/maxlego08/menu/loader/components/SpigotCustomModelDataItemComponentLoader.java
similarity index 90%
rename from Common/src/main/java/fr/maxlego08/menu/loader/components/spigot/SpigotCustomModelDataItemComponentLoader.java
rename to Common/src/main/java/fr/maxlego08/menu/loader/components/SpigotCustomModelDataItemComponentLoader.java
index 0443b04c..bd1cc7cd 100644
--- a/Common/src/main/java/fr/maxlego08/menu/loader/components/spigot/SpigotCustomModelDataItemComponentLoader.java
+++ b/Common/src/main/java/fr/maxlego08/menu/loader/components/SpigotCustomModelDataItemComponentLoader.java
@@ -1,9 +1,11 @@
-package fr.maxlego08.menu.loader.components.spigot;
+package fr.maxlego08.menu.loader.components;
+import fr.maxlego08.menu.api.annotations.ComponentLoader;
+import fr.maxlego08.menu.api.annotations.SinceVersion;
+import fr.maxlego08.menu.api.annotations.SpigotOnly;
import fr.maxlego08.menu.api.context.MenuItemStackContext;
import fr.maxlego08.menu.api.itemstack.ItemComponent;
import fr.maxlego08.menu.api.itemstack.components.CustomModelDataComponent;
-import fr.maxlego08.menu.loader.components.AbstractColorItemComponentLoader;
import org.bukkit.Color;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
@@ -14,6 +16,9 @@
import java.util.ArrayList;
import java.util.List;
+@ComponentLoader
+@SinceVersion("1.20.5")
+@SpigotOnly
public class SpigotCustomModelDataItemComponentLoader extends AbstractColorItemComponentLoader {
public SpigotCustomModelDataItemComponentLoader(){
diff --git a/Common/src/main/java/fr/maxlego08/menu/loader/components/spigot/SpigotVariantItemComponentLoader.java b/Common/src/main/java/fr/maxlego08/menu/loader/components/spigot/SpigotVariantItemComponentLoader.java
deleted file mode 100644
index c6c61cff..00000000
--- a/Common/src/main/java/fr/maxlego08/menu/loader/components/spigot/SpigotVariantItemComponentLoader.java
+++ /dev/null
@@ -1,411 +0,0 @@
-package fr.maxlego08.menu.loader.components.spigot;
-
-import fr.maxlego08.menu.api.context.MenuItemStackContext;
-import fr.maxlego08.menu.api.itemstack.ItemComponent;
-import fr.maxlego08.menu.api.loader.ItemComponentLoader;
-import fr.maxlego08.menu.common.factory.VariantItemComponentLoaderFactory;
-import fr.maxlego08.menu.common.interfaces.VariantComponent;
-import fr.maxlego08.menu.loader.components.AbstractColorItemComponentLoader;
-import org.bukkit.*;
-import org.bukkit.configuration.ConfigurationSection;
-import org.bukkit.configuration.file.YamlConfiguration;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.jspecify.annotations.NonNull;
-
-import java.io.File;
-import java.util.function.Function;
-
-public class SpigotVariantItemComponentLoader implements VariantItemComponentLoaderFactory {
-
- protected final VariantComponent variantFactory;
-
- public SpigotVariantItemComponentLoader(VariantComponent variantFactory) {
- this.variantFactory = variantFactory;
- }
-
- @Override
- public @NonNull ItemComponentLoader getLoaderAxolotl() {
- return new Axolotl();
- }
-
-
- @Override
- public @NotNull ItemComponentLoader getLoaderCatCollar() {
- return new Cat(this.variantFactory).new Collar();
- }
-
-
- @Override
- public @NonNull ItemComponentLoader getLoaderCatVariant() {
- return new Cat(this.variantFactory).new Variant();
- }
-
-
- @Override
- public @NonNull ItemComponentLoader getLoaderChicken() {
- return new Chicken();
- }
-
-
- @Override
- public @NonNull ItemComponentLoader getLoaderCow() {
- return new Cow();
- }
-
-
- @Override
- public @NonNull ItemComponentLoader getLoaderFox() {
- return new Fox();
- }
-
-
- @Override
- public @NonNull ItemComponentLoader getLoaderFrog() {
- return new Frog();
- }
-
-
- @Override
- public @NonNull ItemComponentLoader getLoaderHorse() {
- return new Horse();
- }
-
-
- @Override
- public @NonNull ItemComponentLoader getLoaderLlama() {
- return new Llama();
- }
-
-
- @Override
- public @NonNull ItemComponentLoader getLoaderMushroomCow() {
- return new MushroomCow();
- }
-
-
- @Override
- public @NonNull ItemComponentLoader getLoaderPainting() {
- return new Painting();
- }
-
-
- @Override
- public @NotNull ItemComponentLoader getLoaderParrot() {
- return new Parrot();
- }
-
-
- @Override
- public @NonNull ItemComponentLoader getLoaderPig() {
- return new Pig();
- }
-
-
- @Override
- public @NonNull ItemComponentLoader getLoaderRabbit() {
- return new Rabbit();
- }
-
-
- @Override
- public @NonNull ItemComponentLoader getLoaderSalmon() {
- return new Salmon();
- }
-
-
- @Override
- public @NonNull ItemComponentLoader getLoaderSheep() {
- return new Sheep();
- }
-
-
- @Override
- public @NonNull ItemComponentLoader getLoaderShulkerBox() {
- return new ShulkerBox();
- }
-
-
- @Override
- public @NonNull ItemComponentLoader getLoaderTropicalFishBaseColor() {
- return new TropicalFish(this.variantFactory).new BaseColor();
- }
-
- @Override
- public @NonNull ItemComponentLoader getLoaderTropicalFishPatternColor() {
- return new TropicalFish(this.variantFactory).new PatternColor();
- }
-
- @Override
- public @NonNull ItemComponentLoader getLoaderVillager() {
- return new Villager();
- }
-
-
- @Override
- public @NonNull ItemComponentLoader getLoaderWolfCollar() {
- return new Wolf(this.variantFactory).new Collar();
- }
-
- @Override
- public @NonNull ItemComponentLoader getLoaderWolfVariant() {
- return new Wolf(this.variantFactory).new Variant();
- }
-
- private static abstract class EnumVariantLoader> extends ItemComponentLoader {
- private final Class enumClass;
- private final Function componentFactory;
-
- protected EnumVariantLoader(String path, Class enumClass, Function componentFactory) {
- super(path);
- this.enumClass = enumClass;
- this.componentFactory = componentFactory;
- }
-
- @Override
- public @Nullable ItemComponent load(@NotNull MenuItemStackContext context, @NotNull File file, @NotNull YamlConfiguration configuration, @NotNull String path, @Nullable ConfigurationSection componentSection) {
- path = this.normalizePath(path);
- String value = configuration.getString(path);
- if (value == null) return null;
- try {
- T variant = Enum.valueOf(this.enumClass, value.toUpperCase());
- return this.componentFactory.apply(variant);
- } catch (IllegalArgumentException e) {
- return null;
- }
- }
- }
-
- protected static abstract class RegistryVariantLoader extends ItemComponentLoader {
- private final Registry registry;
- private final Function componentFactory;
-
- protected RegistryVariantLoader(String path, Registry registry, Function componentFactory) {
- super(path);
- this.registry = registry;
- this.componentFactory = componentFactory;
- }
-
- @Override
- public @Nullable ItemComponent load(@NotNull MenuItemStackContext context, @NotNull File file, @NotNull YamlConfiguration configuration, @NotNull String path, @Nullable ConfigurationSection componentSection) {
- path = this.normalizePath(path);
- String value = configuration.getString(path);
- if (value == null) return null;
- NamespacedKey key = NamespacedKey.fromString(value.toLowerCase());
- if (key == null) return null;
- try {
- return this.componentFactory.apply(this.registry.getOrThrow(key));
- } catch (IllegalArgumentException e) {
- return null;
- }
- }
- }
-
- private static abstract class DyeColorVariantLoader extends ItemComponentLoader {
- private final Function componentFactory;
-
- protected DyeColorVariantLoader(String path, Function componentFactory) {
- super(path);
- this.componentFactory = componentFactory;
- }
-
- @Override
- public @Nullable ItemComponent load(@NotNull MenuItemStackContext context, @NotNull File file, @NotNull YamlConfiguration configuration, @NotNull String path, @Nullable ConfigurationSection componentSection) {
- path = this.normalizePath(path);
- String value = configuration.getString(path);
- if (value == null) return null;
- try {
- DyeColor dyeColor = DyeColor.valueOf(value.toUpperCase());
- return this.componentFactory.apply(dyeColor);
- } catch (IllegalArgumentException e) {
- return null;
- }
- }
- }
-
- private static abstract class CollarColorLoader extends AbstractColorItemComponentLoader {
- private final Function componentFactory;
-
- protected CollarColorLoader(String path, Function componentFactory) {
- super(path);
- this.componentFactory = componentFactory;
- }
-
- @Override
- public @Nullable ItemComponent load(@NotNull MenuItemStackContext context, @NotNull File file, @NotNull YamlConfiguration configuration, @NotNull String path, @Nullable ConfigurationSection componentSection) {
- path = this.normalizePath(path);
- Object rawColor = configuration.get(path);
- if (rawColor == null) return null;
- Color color = this.parseColor(rawColor);
- DyeColor dyeColor;
- if (color == null) {
- try {
- dyeColor = DyeColor.valueOf(rawColor.toString().toUpperCase());
- } catch (IllegalArgumentException e) {
- return null;
- }
- } else {
- dyeColor = DyeColor.getByColor(color);
- }
- if (dyeColor == null) return null;
- return this.componentFactory.apply(dyeColor);
- }
- }
-
- // Specific loaders
- public class Axolotl extends EnumVariantLoader {
- public Axolotl() {
- super("axolotl/variant", org.bukkit.entity.Axolotl.Variant.class, SpigotVariantItemComponentLoader.this.variantFactory::createAxolotl);
- }
- }
-
- public static class Cat {
- private final VariantComponent variantFactory;
-
- public Cat(VariantComponent variantFactory) {
- this.variantFactory = variantFactory;
- }
-
- public class Collar extends CollarColorLoader {
- public Collar() {
- super("cat/collar", Cat.this.variantFactory::createCatCollar);
- }
- }
-
- public class Variant extends RegistryVariantLoader {
- public Variant() {
- super("cat/variant", Registry.CAT_VARIANT, Cat.this.variantFactory::createCatVariant);
- }
- }
- }
-
- public class Chicken extends RegistryVariantLoader {
- public Chicken() {
- super("chicken/variant", Registry.CHICKEN_VARIANT, SpigotVariantItemComponentLoader.this.variantFactory::createChicken);
- }
- }
-
- public class Cow extends RegistryVariantLoader {
- public Cow() {
- super("cow/variant", Registry.COW_VARIANT, SpigotVariantItemComponentLoader.this.variantFactory::createCow);
- }
- }
-
- public class Fox extends EnumVariantLoader {
- public Fox() {
- super("fox/variant", org.bukkit.entity.Fox.Type.class, SpigotVariantItemComponentLoader.this.variantFactory::createFox);
- }
- }
-
- public class Frog extends RegistryVariantLoader {
- public Frog() {
- super("frog/variant", Registry.FROG_VARIANT, SpigotVariantItemComponentLoader.this.variantFactory::createFrog);
- }
- }
-
- public class Horse extends EnumVariantLoader {
- public Horse() {
- super("horse/variant", org.bukkit.entity.Horse.Color.class, SpigotVariantItemComponentLoader.this.variantFactory::createHorse);
- }
- }
-
- public class Llama extends EnumVariantLoader {
- public Llama() {
- super("llama/variant", org.bukkit.entity.Llama.Color.class, SpigotVariantItemComponentLoader.this.variantFactory::createLlama);
- }
- }
-
- public class MushroomCow extends EnumVariantLoader {
- public MushroomCow() {
- super("mooshroom/variant", org.bukkit.entity.MushroomCow.Variant.class, SpigotVariantItemComponentLoader.this.variantFactory::createMushroomCow);
- }
- }
-
- public class Painting extends RegistryVariantLoader {
- public Painting() {
- super("painting/variant", Registry.ART, SpigotVariantItemComponentLoader.this.variantFactory::createPainting);
- }
- }
-
- public class Parrot extends EnumVariantLoader {
- public Parrot() {
- super("parrot/variant", org.bukkit.entity.Parrot.Variant.class, SpigotVariantItemComponentLoader.this.variantFactory::createParrot);
- }
- }
-
- public class Pig extends RegistryVariantLoader {
- public Pig() {
- super("pig/variant", Registry.PIG_VARIANT, SpigotVariantItemComponentLoader.this.variantFactory::createPig);
- }
- }
-
- public class Rabbit extends EnumVariantLoader {
- public Rabbit() {
- super("rabbit/variant", org.bukkit.entity.Rabbit.Type.class, SpigotVariantItemComponentLoader.this.variantFactory::createRabbit);
- }
- }
-
- public class Salmon extends EnumVariantLoader {
- public Salmon() {
- super("salmon/size", org.bukkit.entity.Salmon.Variant.class, SpigotVariantItemComponentLoader.this.variantFactory::createSalmon);
- }
- }
-
- public class Sheep extends DyeColorVariantLoader {
- public Sheep() {
- super("sheep/color", SpigotVariantItemComponentLoader.this.variantFactory::createSheep);
- }
- }
-
- public class ShulkerBox extends DyeColorVariantLoader {
- public ShulkerBox() {
- super("shulker/color", SpigotVariantItemComponentLoader.this.variantFactory::createShulkerBox);
- }
- }
-
- public static class TropicalFish {
- private final VariantComponent variantFactory;
-
- public TropicalFish(VariantComponent variantFactory) {
- this.variantFactory = variantFactory;
- }
-
- public class BaseColor extends DyeColorVariantLoader {
- public BaseColor() {
- super("tropical_fish/base_color", TropicalFish.this.variantFactory::createTropicalFishBaseColor);
- }
- }
-
- public class PatternColor extends DyeColorVariantLoader {
- public PatternColor() {
- super("tropical_fish/pattern_color", TropicalFish.this.variantFactory::createTropicalFishPatternColor);
- }
- }
- }
-
- public class Villager extends RegistryVariantLoader {
- public Villager() {
- super("villager/variant", Registry.VILLAGER_TYPE, SpigotVariantItemComponentLoader.this.variantFactory::createVillager);
- }
- }
-
- public static class Wolf {
- private final VariantComponent variantFactory;
-
- public Wolf(VariantComponent variantFactory) {
- this.variantFactory = variantFactory;
- }
-
- public class Collar extends CollarColorLoader {
- public Collar() {
- super("wolf/collar", Wolf.this.variantFactory::createWolfCollar);
- }
- }
-
- public class Variant extends RegistryVariantLoader {
- public Variant() {
- super("wolf/variant", Registry.WOLF_VARIANT, Wolf.this.variantFactory::createWolfVariant);
- }
- }
- }
-}
\ No newline at end of file
diff --git a/Common/src/main/java/fr/maxlego08/menu/loader/components/variants/base/CollarColorLoader.java b/Common/src/main/java/fr/maxlego08/menu/loader/components/variants/base/CollarColorLoader.java
new file mode 100644
index 00000000..0d49c8ce
--- /dev/null
+++ b/Common/src/main/java/fr/maxlego08/menu/loader/components/variants/base/CollarColorLoader.java
@@ -0,0 +1,43 @@
+package fr.maxlego08.menu.loader.components.variants.base;
+
+import fr.maxlego08.menu.api.context.MenuItemStackContext;
+import fr.maxlego08.menu.api.itemstack.ItemComponent;
+import fr.maxlego08.menu.loader.components.AbstractColorItemComponentLoader;
+import org.bukkit.Color;
+import org.bukkit.DyeColor;
+import org.bukkit.configuration.ConfigurationSection;
+import org.bukkit.configuration.file.YamlConfiguration;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+import java.util.function.Function;
+
+public abstract class CollarColorLoader extends AbstractColorItemComponentLoader {
+ private final Function componentFactory;
+
+ protected CollarColorLoader(String path, Function componentFactory) {
+ super(path);
+ this.componentFactory = componentFactory;
+ }
+
+ @Override
+ public @Nullable ItemComponent load(@NotNull MenuItemStackContext context, @NotNull File file, @NotNull YamlConfiguration configuration, @NotNull String path, @Nullable ConfigurationSection componentSection) {
+ path = normalizePath(path);
+ Object rawColor = configuration.get(path);
+ if (rawColor == null) return null;
+ Color color = parseColor(rawColor);
+ DyeColor dyeColor;
+ if (color == null) {
+ try {
+ dyeColor = DyeColor.valueOf(rawColor.toString().toUpperCase());
+ } catch (IllegalArgumentException e) {
+ return null;
+ }
+ } else {
+ dyeColor = DyeColor.getByColor(color);
+ }
+ if (dyeColor == null) return null;
+ return componentFactory.apply(dyeColor);
+ }
+}
diff --git a/Common/src/main/java/fr/maxlego08/menu/loader/components/variants/base/DyeColorVariantLoader.java b/Common/src/main/java/fr/maxlego08/menu/loader/components/variants/base/DyeColorVariantLoader.java
new file mode 100644
index 00000000..5714771f
--- /dev/null
+++ b/Common/src/main/java/fr/maxlego08/menu/loader/components/variants/base/DyeColorVariantLoader.java
@@ -0,0 +1,35 @@
+package fr.maxlego08.menu.loader.components.variants.base;
+
+import fr.maxlego08.menu.api.context.MenuItemStackContext;
+import fr.maxlego08.menu.api.itemstack.ItemComponent;
+import fr.maxlego08.menu.api.loader.ItemComponentLoader;
+import org.bukkit.DyeColor;
+import org.bukkit.configuration.ConfigurationSection;
+import org.bukkit.configuration.file.YamlConfiguration;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+import java.util.function.Function;
+
+public abstract class DyeColorVariantLoader extends ItemComponentLoader {
+ private final Function componentFactory;
+
+ protected DyeColorVariantLoader(String path, Function componentFactory) {
+ super(path);
+ this.componentFactory = componentFactory;
+ }
+
+ @Override
+ public @Nullable ItemComponent load(@NotNull MenuItemStackContext context, @NotNull File file, @NotNull YamlConfiguration configuration, @NotNull String path, @Nullable ConfigurationSection componentSection) {
+ path = normalizePath(path);
+ String value = configuration.getString(path);
+ if (value == null) return null;
+ try {
+ DyeColor dyeColor = DyeColor.valueOf(value.toUpperCase());
+ return componentFactory.apply(dyeColor);
+ } catch (IllegalArgumentException e) {
+ return null;
+ }
+ }
+}
diff --git a/Common/src/main/java/fr/maxlego08/menu/loader/components/variants/base/EnumVariantLoader.java b/Common/src/main/java/fr/maxlego08/menu/loader/components/variants/base/EnumVariantLoader.java
new file mode 100644
index 00000000..9fdef0f3
--- /dev/null
+++ b/Common/src/main/java/fr/maxlego08/menu/loader/components/variants/base/EnumVariantLoader.java
@@ -0,0 +1,36 @@
+package fr.maxlego08.menu.loader.components.variants.base;
+
+import fr.maxlego08.menu.api.context.MenuItemStackContext;
+import fr.maxlego08.menu.api.itemstack.ItemComponent;
+import fr.maxlego08.menu.api.loader.ItemComponentLoader;
+import org.bukkit.configuration.ConfigurationSection;
+import org.bukkit.configuration.file.YamlConfiguration;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+import java.util.function.Function;
+
+public abstract class EnumVariantLoader> extends ItemComponentLoader {
+ private final Class enumClass;
+ private final Function componentFactory;
+
+ protected EnumVariantLoader(String path, Class enumClass, Function componentFactory) {
+ super(path);
+ this.enumClass = enumClass;
+ this.componentFactory = componentFactory;
+ }
+
+ @Override
+ public @Nullable ItemComponent load(@NotNull MenuItemStackContext context, @NotNull File file, @NotNull YamlConfiguration configuration, @NotNull String path, @Nullable ConfigurationSection componentSection) {
+ path = normalizePath(path);
+ String value = configuration.getString(path);
+ if (value == null) return null;
+ try {
+ T variant = Enum.valueOf(enumClass, value.toUpperCase());
+ return componentFactory.apply(variant);
+ } catch (IllegalArgumentException e) {
+ return null;
+ }
+ }
+}
diff --git a/Common/src/main/java/fr/maxlego08/menu/loader/components/variants/base/RegistryVariantLoader.java b/Common/src/main/java/fr/maxlego08/menu/loader/components/variants/base/RegistryVariantLoader.java
new file mode 100644
index 00000000..2016af75
--- /dev/null
+++ b/Common/src/main/java/fr/maxlego08/menu/loader/components/variants/base/RegistryVariantLoader.java
@@ -0,0 +1,40 @@
+package fr.maxlego08.menu.loader.components.variants.base;
+
+import fr.maxlego08.menu.api.context.MenuItemStackContext;
+import fr.maxlego08.menu.api.itemstack.ItemComponent;
+import fr.maxlego08.menu.api.loader.ItemComponentLoader;
+import org.bukkit.Keyed;
+import org.bukkit.NamespacedKey;
+import org.bukkit.Registry;
+import org.bukkit.configuration.ConfigurationSection;
+import org.bukkit.configuration.file.YamlConfiguration;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+import java.util.function.Function;
+
+public abstract class RegistryVariantLoader extends ItemComponentLoader {
+ private final Registry registry;
+ private final Function componentFactory;
+
+ protected RegistryVariantLoader(String path, Registry registry, Function componentFactory) {
+ super(path);
+ this.registry = registry;
+ this.componentFactory = componentFactory;
+ }
+
+ @Override
+ public @Nullable ItemComponent load(@NotNull MenuItemStackContext context, @NotNull File file, @NotNull YamlConfiguration configuration, @NotNull String path, @Nullable ConfigurationSection componentSection) {
+ path = normalizePath(path);
+ String value = configuration.getString(path);
+ if (value == null) return null;
+ NamespacedKey key = NamespacedKey.fromString(value.toLowerCase());
+ if (key == null) return null;
+ try {
+ return componentFactory.apply(registry.getOrThrow(key));
+ } catch (IllegalArgumentException e) {
+ return null;
+ }
+ }
+}
diff --git a/Hooks/Bedrock/build.gradle.kts b/Hooks/Bedrock/build.gradle.kts
index 1540df23..8aad0a48 100644
--- a/Hooks/Bedrock/build.gradle.kts
+++ b/Hooks/Bedrock/build.gradle.kts
@@ -7,5 +7,5 @@ repositories {
dependencies {
compileOnly(projects.api)
- compileOnly("org.geysermc.floodgate:api:2.2.4-SNAPSHOT")
+ compileOnly(libs.floodgate)
}
\ No newline at end of file
diff --git a/Hooks/Bedrock/src/main/java/fr/maxlego08/menu/hooks/bedrock/ZBedrockInventory.java b/Hooks/Bedrock/src/main/java/fr/maxlego08/menu/hooks/bedrock/ZBedrockInventory.java
index ef5e1002..87ee568d 100644
--- a/Hooks/Bedrock/src/main/java/fr/maxlego08/menu/hooks/bedrock/ZBedrockInventory.java
+++ b/Hooks/Bedrock/src/main/java/fr/maxlego08/menu/hooks/bedrock/ZBedrockInventory.java
@@ -1,6 +1,5 @@
package fr.maxlego08.menu.hooks.bedrock;
-import fr.maxlego08.menu.api.BedrockInventory;
import fr.maxlego08.menu.api.MenuPlugin;
import fr.maxlego08.menu.api.animation.TitleAnimation;
import fr.maxlego08.menu.api.button.Button;
@@ -8,6 +7,7 @@
import fr.maxlego08.menu.api.button.dialogs.InputButton;
import fr.maxlego08.menu.api.engine.InventoryEngine;
import fr.maxlego08.menu.api.enums.bedrock.BedrockType;
+import fr.maxlego08.menu.api.inventory.bedrock.BedrockInventory;
import fr.maxlego08.menu.api.requirement.Action;
import fr.maxlego08.menu.api.requirement.ConditionalName;
import fr.maxlego08.menu.api.requirement.Requirement;
@@ -15,6 +15,7 @@
import fr.maxlego08.menu.api.utils.InventoryReplacement;
import fr.maxlego08.menu.api.utils.Placeholders;
import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.util.ArrayList;
@@ -57,7 +58,7 @@ public String getName() {
}
@Override
- public String getName(Player player, InventoryEngine inventoryDefault, Placeholders placeholders) {
+ public String getName(@NotNull Player player, InventoryEngine inventoryDefault, Placeholders placeholders) {
if (!this.conditionalNames.isEmpty()) {
Optional optional = this.conditionalNames.stream().filter(conditionalName -> conditionalName.hasPermission(player, null, inventoryDefault, placeholders)).max(Comparator.comparingInt(ConditionalName::priority));
diff --git a/Hooks/Bedrock/src/main/java/fr/maxlego08/menu/hooks/bedrock/ZBedrockManager.java b/Hooks/Bedrock/src/main/java/fr/maxlego08/menu/hooks/bedrock/ZBedrockManager.java
index e71833b0..d2ceb18d 100644
--- a/Hooks/Bedrock/src/main/java/fr/maxlego08/menu/hooks/bedrock/ZBedrockManager.java
+++ b/Hooks/Bedrock/src/main/java/fr/maxlego08/menu/hooks/bedrock/ZBedrockManager.java
@@ -1,6 +1,9 @@
package fr.maxlego08.menu.hooks.bedrock;
-import fr.maxlego08.menu.api.*;
+import fr.maxlego08.menu.api.BedrockManager;
+import fr.maxlego08.menu.api.Inventory;
+import fr.maxlego08.menu.api.InventoryManager;
+import fr.maxlego08.menu.api.MenuPlugin;
import fr.maxlego08.menu.api.button.bedrock.BedrockButton;
import fr.maxlego08.menu.api.button.dialogs.InputButton;
import fr.maxlego08.menu.api.configuration.Configuration;
@@ -9,6 +12,7 @@
import fr.maxlego08.menu.api.exceptions.DialogException;
import fr.maxlego08.menu.api.exceptions.DialogFileNotFound;
import fr.maxlego08.menu.api.exceptions.InventoryException;
+import fr.maxlego08.menu.api.inventory.bedrock.BedrockInventory;
import fr.maxlego08.menu.api.requirement.Requirement;
import fr.maxlego08.menu.api.utils.Loader;
import fr.maxlego08.menu.api.utils.Message;
diff --git a/Hooks/Bedrock/src/main/java/fr/maxlego08/menu/hooks/bedrock/listener/BedrockReplacementListener.java b/Hooks/Bedrock/src/main/java/fr/maxlego08/menu/hooks/bedrock/listener/BedrockReplacementListener.java
index af4c0013..f2f4f5e5 100644
--- a/Hooks/Bedrock/src/main/java/fr/maxlego08/menu/hooks/bedrock/listener/BedrockReplacementListener.java
+++ b/Hooks/Bedrock/src/main/java/fr/maxlego08/menu/hooks/bedrock/listener/BedrockReplacementListener.java
@@ -1,11 +1,10 @@
package fr.maxlego08.menu.hooks.bedrock.listener;
-import fr.maxlego08.menu.api.BedrockInventory;
import fr.maxlego08.menu.api.BedrockManager;
import fr.maxlego08.menu.api.Inventory;
import fr.maxlego08.menu.api.event.events.PlayerOpenInventoryEvent;
+import fr.maxlego08.menu.api.inventory.bedrock.BedrockInventory;
import fr.maxlego08.menu.api.utils.InventoryReplacement;
-import fr.maxlego08.menu.zcore.logger.Logger;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
@@ -28,9 +27,8 @@ public void onPlayerOpenInventory(PlayerOpenInventoryEvent event) {
if (this.bedrockManager.isBedrockPlayer(event.getPlayer())) {
InventoryReplacement inventoryReplacement = inventory.getInventoryReplacement();
if (inventoryReplacement != null) {
- Optional optionalBedrockInventory = this.bedrockManager.getBedrockInventory(inventoryReplacement.getPlugin(), inventoryReplacement.getInventoryName());
+ Optional optionalBedrockInventory = this.bedrockManager.getBedrockInventory(inventoryReplacement.plugin(), inventoryReplacement.inventoryName());
if (optionalBedrockInventory.isEmpty()) {
- Logger.info("Bedrock inventory not found for replacement: " + inventoryReplacement.getInventoryName() + " (plugin: " + inventoryReplacement.getPlugin() + ")");
return;
}
BedrockInventory bedrockInventory = optionalBedrockInventory.get();
diff --git a/Hooks/Bedrock/src/main/java/fr/maxlego08/menu/hooks/bedrock/loader/BedrockLoader.java b/Hooks/Bedrock/src/main/java/fr/maxlego08/menu/hooks/bedrock/loader/BedrockLoader.java
index 98f968b5..bbf2e893 100644
--- a/Hooks/Bedrock/src/main/java/fr/maxlego08/menu/hooks/bedrock/loader/BedrockLoader.java
+++ b/Hooks/Bedrock/src/main/java/fr/maxlego08/menu/hooks/bedrock/loader/BedrockLoader.java
@@ -1,6 +1,5 @@
package fr.maxlego08.menu.hooks.bedrock.loader;
-import fr.maxlego08.menu.api.BedrockInventory;
import fr.maxlego08.menu.api.InventoryOption;
import fr.maxlego08.menu.api.MenuPlugin;
import fr.maxlego08.menu.api.button.Button;
@@ -9,6 +8,7 @@
import fr.maxlego08.menu.api.enums.bedrock.BedrockType;
import fr.maxlego08.menu.api.exceptions.InventoryButtonException;
import fr.maxlego08.menu.api.exceptions.InventoryException;
+import fr.maxlego08.menu.api.inventory.bedrock.BedrockInventory;
import fr.maxlego08.menu.api.requirement.Requirement;
import fr.maxlego08.menu.api.utils.Loader;
import fr.maxlego08.menu.hooks.bedrock.ZBedrockInventory;
diff --git a/Hooks/BreweryX/build.gradle.kts b/Hooks/BreweryX/build.gradle.kts
index e29bce7e..15f811ae 100644
--- a/Hooks/BreweryX/build.gradle.kts
+++ b/Hooks/BreweryX/build.gradle.kts
@@ -6,5 +6,5 @@ repositories {
dependencies {
compileOnly(projects.common)
- compileOnly("com.dre.brewery:BreweryX:3.6.0")
+ compileOnly(libs.breweryx)
}
diff --git a/Hooks/CraftEngine/build.gradle.kts b/Hooks/CraftEngine/build.gradle.kts
index fe85d461..6e70e0e7 100644
--- a/Hooks/CraftEngine/build.gradle.kts
+++ b/Hooks/CraftEngine/build.gradle.kts
@@ -6,6 +6,6 @@ repositories {
dependencies {
compileOnly(projects.common)
- compileOnly("net.momirealms:craft-engine-core:26.5")
- compileOnly("net.momirealms:craft-engine-bukkit:26.5")
+ compileOnly(libs.craft.engine.core)
+ compileOnly(libs.craft.engine.bukkit)
}
\ No newline at end of file
diff --git a/Hooks/Eco/build.gradle.kts b/Hooks/Eco/build.gradle.kts
index ce261eb6..155af982 100644
--- a/Hooks/Eco/build.gradle.kts
+++ b/Hooks/Eco/build.gradle.kts
@@ -7,5 +7,5 @@ repositories {
dependencies {
compileOnly(projects.common)
- compileOnly("com.willfp:eco:6.53.0")
+ compileOnly(libs.eco)
}
\ No newline at end of file
diff --git a/Hooks/ExecutableBlocks/build.gradle.kts b/Hooks/ExecutableBlocks/build.gradle.kts
index 463dc1c2..2347a6ce 100644
--- a/Hooks/ExecutableBlocks/build.gradle.kts
+++ b/Hooks/ExecutableBlocks/build.gradle.kts
@@ -16,5 +16,5 @@ repositories {
dependencies {
compileOnly(projects.common)
- compileOnly("maven.modrinth:SCore:5.25.6.9")
+ compileOnly(libs.score)
}
\ No newline at end of file
diff --git a/Hooks/ExecutableItems/build.gradle.kts b/Hooks/ExecutableItems/build.gradle.kts
index 9ce1a81c..8f0ded40 100644
--- a/Hooks/ExecutableItems/build.gradle.kts
+++ b/Hooks/ExecutableItems/build.gradle.kts
@@ -16,5 +16,5 @@ repositories {
dependencies {
compileOnly(projects.common)
- compileOnly("maven.modrinth:SCore:5.25.6.9")
+ compileOnly(libs.score)
}
\ No newline at end of file
diff --git a/Hooks/HeadDataBase/build.gradle.kts b/Hooks/HeadDataBase/build.gradle.kts
index a2fef0d5..1337c49d 100644
--- a/Hooks/HeadDataBase/build.gradle.kts
+++ b/Hooks/HeadDataBase/build.gradle.kts
@@ -2,5 +2,5 @@ group = "Hooks:HeadDataBase"
dependencies {
compileOnly(projects.common)
- compileOnly("com.arcaniax:HeadDatabase-API:1.3.2")
+ compileOnly(libs.headdatabase)
}
\ No newline at end of file
diff --git a/Hooks/Hmccosmetics/build.gradle.kts b/Hooks/Hmccosmetics/build.gradle.kts
index f949571e..a09cde85 100644
--- a/Hooks/Hmccosmetics/build.gradle.kts
+++ b/Hooks/Hmccosmetics/build.gradle.kts
@@ -7,5 +7,5 @@ repositories {
dependencies {
compileOnly(projects.common)
- compileOnly("com.hibiscusmc:HMCCosmetics:2.7.7")
+ compileOnly(libs.hmccosmetics)
}
\ No newline at end of file
diff --git a/Hooks/ItemsAdder/build.gradle.kts b/Hooks/ItemsAdder/build.gradle.kts
index 47400fbf..a5366b4f 100644
--- a/Hooks/ItemsAdder/build.gradle.kts
+++ b/Hooks/ItemsAdder/build.gradle.kts
@@ -6,5 +6,5 @@ repositories {
dependencies {
compileOnly(projects.common)
- compileOnly("com.github.LoneDev6:api-itemsadder:3.6.1")
+ compileOnly(libs.itemsadder)
}
\ No newline at end of file
diff --git a/Hooks/ItemsAdder/src/main/java/fr/maxlego08/menu/hooks/itemsadder/ItemsAdderLoader.java b/Hooks/ItemsAdder/src/main/java/fr/maxlego08/menu/hooks/itemsadder/ItemsAdderLoader.java
index e99887fe..53ef9a7d 100644
--- a/Hooks/ItemsAdder/src/main/java/fr/maxlego08/menu/hooks/itemsadder/ItemsAdderLoader.java
+++ b/Hooks/ItemsAdder/src/main/java/fr/maxlego08/menu/hooks/itemsadder/ItemsAdderLoader.java
@@ -1,7 +1,9 @@
package fr.maxlego08.menu.hooks.itemsadder;
import dev.lone.itemsadder.api.CustomStack;
+import fr.maxlego08.menu.api.configuration.Configuration;
import fr.maxlego08.menu.api.loader.MaterialLoader;
+import fr.maxlego08.menu.zcore.logger.Logger;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
@@ -21,7 +23,8 @@ public ItemsAdderLoader(Plugin plugin) {
public ItemStack load(@NonNull Player player, @NonNull YamlConfiguration configuration, @NonNull String path, @NonNull String materialString) {
CustomStack customStack = CustomStack.getInstance(materialString);
if (customStack == null) {
- this.plugin.getLogger().severe("Impossible to find the item " + materialString);
+ if (Configuration.enableDebug)
+ Logger.info("ItemsAdderLoader: Item '" + materialString + "' not found, available items: " + CustomStack.getNamespacedIdsInRegistry());
return null;
}
return customStack.getItemStack().clone();
diff --git a/Hooks/Jobs/src/main/java/fr/maxlego08/menu/hooks/jobs/ZJobPermissible.java b/Hooks/Jobs/src/main/java/fr/maxlego08/menu/hooks/jobs/ZJobPermissible.java
index 62b9b1dd..dcea907d 100644
--- a/Hooks/Jobs/src/main/java/fr/maxlego08/menu/hooks/jobs/ZJobPermissible.java
+++ b/Hooks/Jobs/src/main/java/fr/maxlego08/menu/hooks/jobs/ZJobPermissible.java
@@ -8,6 +8,7 @@
import fr.maxlego08.menu.api.requirement.Action;
import fr.maxlego08.menu.api.requirement.permissible.JobPermissible;
import fr.maxlego08.menu.api.utils.Placeholders;
+import fr.maxlego08.menu.zcore.logger.Logger;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;
import org.jspecify.annotations.NonNull;
@@ -28,7 +29,7 @@ public boolean hasPermission(@NonNull Player player, Button button, @NonNull Inv
MenuPlugin plugin = inventory.getPlugin();
Job job = Jobs.getJob(plugin.parse(player, placeholders.parse(this.jobName)));
if (job == null) {
- plugin.getLogger().severe("Job " + this.jobName + " was not found !");
+ Logger.info("Job " + this.jobName + " was not found !", Logger.LogType.ERROR);
return true;
}
return Jobs.getPlayerManager().getJobsPlayer(player.getUniqueId()).isInJob(job);
diff --git a/Hooks/LuckPerms/build.gradle.kts b/Hooks/LuckPerms/build.gradle.kts
index 86ef5d06..f172dad5 100644
--- a/Hooks/LuckPerms/build.gradle.kts
+++ b/Hooks/LuckPerms/build.gradle.kts
@@ -2,5 +2,5 @@ group = "Hooks:LuckPerms"
dependencies {
compileOnly(projects.common)
- compileOnly("net.luckperms:api:5.4")
+ compileOnly(libs.luckperms)
}
\ No newline at end of file
diff --git a/Hooks/MMOItems/build.gradle.kts b/Hooks/MMOItems/build.gradle.kts
index 5c0dd921..eb3c8bf2 100644
--- a/Hooks/MMOItems/build.gradle.kts
+++ b/Hooks/MMOItems/build.gradle.kts
@@ -8,5 +8,5 @@ repositories {
dependencies {
compileOnly(projects.common)
- compileOnly("net.Indyuce:MMOItems-API:6.9.5-SNAPSHOT")
+ compileOnly(libs.mmoitems)
}
\ No newline at end of file
diff --git a/Hooks/MMOItems/src/main/java/fr/maxlego08/menu/hooks/mmoitems/MMOItemsLoader.java b/Hooks/MMOItems/src/main/java/fr/maxlego08/menu/hooks/mmoitems/MMOItemsLoader.java
index cde9cdb6..b5be3f8e 100644
--- a/Hooks/MMOItems/src/main/java/fr/maxlego08/menu/hooks/mmoitems/MMOItemsLoader.java
+++ b/Hooks/MMOItems/src/main/java/fr/maxlego08/menu/hooks/mmoitems/MMOItemsLoader.java
@@ -1,6 +1,8 @@
package fr.maxlego08.menu.hooks.mmoitems;
+import fr.maxlego08.menu.api.configuration.Configuration;
import fr.maxlego08.menu.api.loader.MaterialLoader;
+import fr.maxlego08.menu.zcore.logger.Logger;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.Type;
import org.bukkit.configuration.file.YamlConfiguration;
@@ -21,9 +23,21 @@ public MMOItemsLoader() {
if (split.length != 2) return null;
try {
final Type type = MMOItems.plugin.getTypes().get(split[0]);
- if (type == null) return null;
- return MMOItems.plugin.getItem(type, split[1]);
+ if (type == null) {
+ if (Configuration.enableDebug)
+ Logger.info(String.format("Invalid MMOItems type '%s' for material '%s', available types: %s", split[0], materialString, MMOItems.plugin.getTypes().getAllTypeNames()));
+ return null;
+ }
+ ItemStack item = MMOItems.plugin.getItem(type, split[1]);
+ if (item == null) {
+ if (Configuration.enableDebug)
+ Logger.info(String.format("Invalid MMOItems item '%s' for type '%s', available items: %s", split[1], split[0], MMOItems.plugin.getTemplates().getTemplateNames(type)));
+ return null;
+ }
+ return item;
} catch (Exception e) {
+ if (Configuration.enableDebug)
+ Logger.info(String.format("Error loading MMOItems material '%s': %s", materialString, e.getMessage()));
return null;
}
}
diff --git a/Hooks/MagicCosmetics/build.gradle.kts b/Hooks/MagicCosmetics/build.gradle.kts
index cfab7017..362fb619 100644
--- a/Hooks/MagicCosmetics/build.gradle.kts
+++ b/Hooks/MagicCosmetics/build.gradle.kts
@@ -2,5 +2,5 @@ group = "Hooks:MagicCosmetics"
dependencies {
compileOnly(projects.common)
- compileOnly("com.github.FrancoBM12:API-MagicCosmetics:2.2.8")
+ compileOnly(libs.magiccosmetics)
}
\ No newline at end of file
diff --git a/Hooks/MythicMobs/build.gradle.kts b/Hooks/MythicMobs/build.gradle.kts
index 183569b9..75c77ba8 100644
--- a/Hooks/MythicMobs/build.gradle.kts
+++ b/Hooks/MythicMobs/build.gradle.kts
@@ -8,5 +8,5 @@ repositories {
dependencies {
compileOnly(projects.common)
- compileOnly("io.lumine:Mythic-Dist:5.6.1")
+ compileOnly(libs.mythicmobs)
}
\ No newline at end of file
diff --git a/Hooks/MythicMobs/src/main/java/fr/maxlego08/menu/hooks/mythicmobs/MythicMobsItemsLoader.java b/Hooks/MythicMobs/src/main/java/fr/maxlego08/menu/hooks/mythicmobs/MythicMobsItemsLoader.java
index b9773ed3..999cbd6a 100644
--- a/Hooks/MythicMobs/src/main/java/fr/maxlego08/menu/hooks/mythicmobs/MythicMobsItemsLoader.java
+++ b/Hooks/MythicMobs/src/main/java/fr/maxlego08/menu/hooks/mythicmobs/MythicMobsItemsLoader.java
@@ -1,6 +1,8 @@
package fr.maxlego08.menu.hooks.mythicmobs;
+import fr.maxlego08.menu.api.configuration.Configuration;
import fr.maxlego08.menu.api.loader.MaterialLoader;
+import fr.maxlego08.menu.zcore.logger.Logger;
import io.lumine.mythic.bukkit.MythicBukkit;
import io.lumine.mythic.core.items.ItemExecutor;
import io.lumine.mythic.core.items.MythicItem;
@@ -22,6 +24,12 @@ public MythicMobsItemsLoader() {
@Override
public ItemStack load(@NonNull Player player, @NonNull YamlConfiguration configuration, @NonNull String path, @NonNull String materialString) {
Optional mythicItem = this.itemManager.getItem(materialString);
- return mythicItem.map(MythicItem::getCachedBaseItem).orElse(null);
+ if (mythicItem.isEmpty()) {
+
+ if (Configuration.enableDebug)
+ Logger.info("MythicMobsItemsLoader: Mythic item '" + materialString + "' not found, available items: " + this.itemManager.getItemNames());
+ return null;
+ }
+ return mythicItem.get().getCachedBaseItem();
}
}
diff --git a/Hooks/Nexo/build.gradle.kts b/Hooks/Nexo/build.gradle.kts
index c5c7a4d0..90e2e211 100644
--- a/Hooks/Nexo/build.gradle.kts
+++ b/Hooks/Nexo/build.gradle.kts
@@ -6,5 +6,5 @@ repositories {
dependencies {
compileOnly(projects.common)
- compileOnly("com.nexomc:nexo:1.21.0")
+ compileOnly(libs.nexo)
}
\ No newline at end of file
diff --git a/Hooks/Nova/build.gradle.kts b/Hooks/Nova/build.gradle.kts
index 800b58a8..e54b4cba 100644
--- a/Hooks/Nova/build.gradle.kts
+++ b/Hooks/Nova/build.gradle.kts
@@ -6,5 +6,5 @@ repositories {
dependencies {
compileOnly(projects.common)
- compileOnly("xyz.xenondevs.nova:nova-api:0.14.10")
+ compileOnly(libs.nova.api)
}
\ No newline at end of file
diff --git a/Hooks/Oraxen/build.gradle.kts b/Hooks/Oraxen/build.gradle.kts
index 3a9fcaf8..b2875aa7 100644
--- a/Hooks/Oraxen/build.gradle.kts
+++ b/Hooks/Oraxen/build.gradle.kts
@@ -6,5 +6,5 @@ repositories {
dependencies {
compileOnly(projects.common)
- compileOnly("io.th0rgal:oraxen:1.190.0")
+ compileOnly(libs.oraxen)
}
\ No newline at end of file
diff --git a/Hooks/PacketEvents/build.gradle.kts b/Hooks/PacketEvents/build.gradle.kts
index 064786d9..b6240730 100644
--- a/Hooks/PacketEvents/build.gradle.kts
+++ b/Hooks/PacketEvents/build.gradle.kts
@@ -2,5 +2,5 @@ group = "Hooks:PacketEvents"
dependencies {
compileOnly(projects.common)
- compileOnly("com.github.retrooper:packetevents-spigot:2.11.2")
+ compileOnly(libs.packetevents)
}
\ No newline at end of file
diff --git a/Hooks/PacketEvents/src/main/java/fr/maxlego08/menu/hooks/packetevents/PacketEventPlayerInventoryManager.java b/Hooks/PacketEvents/src/main/java/fr/maxlego08/menu/hooks/packetevents/PacketEventPlayerInventoryManager.java
index 91b49d76..f551dba2 100644
--- a/Hooks/PacketEvents/src/main/java/fr/maxlego08/menu/hooks/packetevents/PacketEventPlayerInventoryManager.java
+++ b/Hooks/PacketEvents/src/main/java/fr/maxlego08/menu/hooks/packetevents/PacketEventPlayerInventoryManager.java
@@ -3,6 +3,7 @@
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSetPlayerInventory;
import fr.maxlego08.menu.api.InventoryListener;
+import fr.maxlego08.menu.api.MenuPlugin;
import fr.maxlego08.menu.api.engine.BaseInventory;
import fr.maxlego08.menu.api.engine.ItemButton;
import fr.maxlego08.menu.api.players.inventory.InventoryPlayer;
@@ -20,9 +21,11 @@
import java.util.UUID;
public class PacketEventPlayerInventoryManager implements InventoryListener {
+ private final MenuPlugin plugin;
private final Map> pendingInventoryUpdates = new HashMap<>();
- public PacketEventPlayerInventoryManager() {
+ public PacketEventPlayerInventoryManager(MenuPlugin plugin) {
+ this.plugin = plugin;
ClearInvType packetEvent = ClearInvType.PACKET_EVENT;
packetEvent.setOnButtonClear((player, slot)->this.addItemInstantly(player,slot,new ItemStack(Material.AIR)));
packetEvent.setOnInventoryClose(((inventoriesPlayer, player) -> {
@@ -56,11 +59,15 @@ public void onInventoryPreOpen(Player player, BaseInventory baseInventory, int p
public void onInventoryPostOpen(Player player, BaseInventory baseInventory){
UUID playerUniqueId = player.getUniqueId();
if (this.pendingInventoryUpdates.containsKey(playerUniqueId)) {
- Map wrappers = this.pendingInventoryUpdates.get(playerUniqueId);
- for (WrapperPlayServerSetPlayerInventory wrapper : wrappers.values()) {
- PacketEvents.getAPI().getPlayerManager().sendPacket(player, wrapper);
- }
- this.pendingInventoryUpdates.remove(playerUniqueId);
+ this.plugin.getScheduler().runAtEntityLater(player, () -> {
+ Map wrappers = this.pendingInventoryUpdates.get(playerUniqueId);
+ if (wrappers != null) {
+ for (WrapperPlayServerSetPlayerInventory wrapper : wrappers.values()) {
+ PacketEvents.getAPI().getPlayerManager().sendPacket(player, wrapper);
+ }
+ this.pendingInventoryUpdates.remove(playerUniqueId);
+ }
+ }, 1);
}
}
diff --git a/Hooks/PacketEvents/src/main/java/fr/maxlego08/menu/hooks/packetevents/PacketListener.java b/Hooks/PacketEvents/src/main/java/fr/maxlego08/menu/hooks/packetevents/PacketListener.java
index cc9a0cef..312abfd8 100644
--- a/Hooks/PacketEvents/src/main/java/fr/maxlego08/menu/hooks/packetevents/PacketListener.java
+++ b/Hooks/PacketEvents/src/main/java/fr/maxlego08/menu/hooks/packetevents/PacketListener.java
@@ -30,7 +30,8 @@ public void onPacketSend(PacketSendEvent event) {
FakeInventory fakeInventory = PacketUtils.fakeContents.get(event.getUser().getUUID());
for (int i = 0; i != 36; i++) {
org.bukkit.inventory.ItemStack itemStack = fakeInventory.getFrom(i);
- items.add(SpigotConversionUtil.fromBukkitItemStack(itemStack));
+ if (itemStack != null)
+ items.add(SpigotConversionUtil.fromBukkitItemStack(itemStack));
}
wrapper.setItems(items);
diff --git a/Hooks/PacketEvents/src/main/java/fr/maxlego08/menu/hooks/packetevents/PacketUtils.java b/Hooks/PacketEvents/src/main/java/fr/maxlego08/menu/hooks/packetevents/PacketUtils.java
index 62d2211d..044a7ebb 100644
--- a/Hooks/PacketEvents/src/main/java/fr/maxlego08/menu/hooks/packetevents/PacketUtils.java
+++ b/Hooks/PacketEvents/src/main/java/fr/maxlego08/menu/hooks/packetevents/PacketUtils.java
@@ -54,7 +54,6 @@ public void onEnable() {
PacketEvents.getAPI().init();
EventManager eventManager = PacketEvents.getAPI().getEventManager();
// eventManager.registerListener(new PacketListener(), PacketListenerPriority.LOW);
- ;
eventManager.registerListener(this.packetAnimationListener = new PacketAnimationListener(this.plugin), PacketListenerPriority.LOW);
eventManager.registerListener(this.packetTitleListener = new PacketTitleListener(), PacketListenerPriority.LOW);
if (Configuration.enablePacketEventClickLimiter){
diff --git a/Hooks/Paper/build.gradle.kts b/Hooks/Paper/build.gradle.kts
index a7eedea5..fffe52fa 100644
--- a/Hooks/Paper/build.gradle.kts
+++ b/Hooks/Paper/build.gradle.kts
@@ -6,6 +6,6 @@ repositories {
dependencies {
compileOnly(projects.common)
- compileOnly("net.kyori:adventure-text-minimessage:4.21.0")
- compileOnly("io.papermc.paper:paper-api:1.21.11-R0.1-SNAPSHOT")
+ compileOnly(libs.adventure.text.minimessage)
+ compileOnly(libs.paper.api)
}
\ No newline at end of file
diff --git a/Hooks/Paper/src/main/java/fr/maxlego08/menu/hooks/dialogs/ZDialogInventory.java b/Hooks/Paper/src/main/java/fr/maxlego08/menu/hooks/dialogs/ZDialogInventory.java
index 7950e7f2..d30e2e2f 100644
--- a/Hooks/Paper/src/main/java/fr/maxlego08/menu/hooks/dialogs/ZDialogInventory.java
+++ b/Hooks/Paper/src/main/java/fr/maxlego08/menu/hooks/dialogs/ZDialogInventory.java
@@ -1,6 +1,5 @@
package fr.maxlego08.menu.hooks.dialogs;
-import fr.maxlego08.menu.api.DialogInventory;
import fr.maxlego08.menu.api.MenuPlugin;
import fr.maxlego08.menu.api.animation.TitleAnimation;
import fr.maxlego08.menu.api.button.Button;
@@ -8,6 +7,7 @@
import fr.maxlego08.menu.api.button.dialogs.InputButton;
import fr.maxlego08.menu.api.engine.InventoryEngine;
import fr.maxlego08.menu.api.enums.dialog.DialogType;
+import fr.maxlego08.menu.api.inventory.dialog.DialogInventory;
import fr.maxlego08.menu.api.requirement.Action;
import fr.maxlego08.menu.api.requirement.ConditionalName;
import fr.maxlego08.menu.api.requirement.Requirement;
@@ -19,6 +19,7 @@
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.NonNull;
import java.io.File;
import java.util.ArrayList;
@@ -71,7 +72,7 @@ public class ZDialogInventory implements DialogInventory {
private String targetPlayerNamePlaceholder;
private Requirement openRequirement;
- public ZDialogInventory(MenuPlugin plugin, String name, String fileName, String externalTitle) {
+ public ZDialogInventory(@NotNull MenuPlugin plugin,@NotNull String name,@NotNull String fileName,@NotNull String externalTitle) {
this.menuPlugin = plugin;
this.name = name;
this.fileName = fileName.endsWith(".yml") ? fileName.replace(".yml", "") : fileName;
@@ -84,7 +85,7 @@ public String getName() {
}
@Override
- public String getName(Player player, InventoryEngine inventoryDefault, Placeholders placeholders) {
+ public String getName(@NotNull Player player, InventoryEngine inventoryDefault, Placeholders placeholders) {
if (!this.conditionalNames.isEmpty()) {
Optional optional = this.conditionalNames.stream().filter(conditionalName -> conditionalName.hasPermission(player, null, inventoryDefault, placeholders)).max(Comparator.comparingInt(ConditionalName::priority));
@@ -135,7 +136,7 @@ public void setCanCloseWithEscape(boolean canCloseWithEscape) {
this.canCloseWithEscape = canCloseWithEscape;
}
@Override
- public String getExternalTitle() {
+ public @NonNull String getExternalTitle() {
return this.externalTitle;
}
@Override
diff --git a/Hooks/Paper/src/main/java/fr/maxlego08/menu/hooks/dialogs/ZDialogManager.java b/Hooks/Paper/src/main/java/fr/maxlego08/menu/hooks/dialogs/ZDialogManager.java
index f610e3ae..915f54ec 100644
--- a/Hooks/Paper/src/main/java/fr/maxlego08/menu/hooks/dialogs/ZDialogManager.java
+++ b/Hooks/Paper/src/main/java/fr/maxlego08/menu/hooks/dialogs/ZDialogManager.java
@@ -1,6 +1,9 @@
package fr.maxlego08.menu.hooks.dialogs;
-import fr.maxlego08.menu.api.*;
+import fr.maxlego08.menu.api.DialogManager;
+import fr.maxlego08.menu.api.Inventory;
+import fr.maxlego08.menu.api.InventoryManager;
+import fr.maxlego08.menu.api.MenuPlugin;
import fr.maxlego08.menu.api.button.dialogs.BodyButton;
import fr.maxlego08.menu.api.configuration.ConfigManagerInt;
import fr.maxlego08.menu.api.configuration.Configuration;
@@ -11,6 +14,7 @@
import fr.maxlego08.menu.api.exceptions.DialogException;
import fr.maxlego08.menu.api.exceptions.DialogFileNotFound;
import fr.maxlego08.menu.api.exceptions.InventoryException;
+import fr.maxlego08.menu.api.inventory.dialog.DialogInventory;
import fr.maxlego08.menu.api.requirement.Requirement;
import fr.maxlego08.menu.api.utils.Loader;
import fr.maxlego08.menu.api.utils.Placeholders;
diff --git a/Hooks/Paper/src/main/java/fr/maxlego08/menu/hooks/dialogs/button/loader/DialogBooleanInputLoader.java b/Hooks/Paper/src/main/java/fr/maxlego08/menu/hooks/dialogs/button/loader/DialogBooleanInputLoader.java
index 27294765..5837dba4 100644
--- a/Hooks/Paper/src/main/java/fr/maxlego08/menu/hooks/dialogs/button/loader/DialogBooleanInputLoader.java
+++ b/Hooks/Paper/src/main/java/fr/maxlego08/menu/hooks/dialogs/button/loader/DialogBooleanInputLoader.java
@@ -2,8 +2,6 @@
import fr.maxlego08.menu.api.button.Button;
import fr.maxlego08.menu.api.button.DefaultButtonValue;
-import fr.maxlego08.menu.api.button.dialogs.InputButton;
-import fr.maxlego08.menu.api.enums.dialog.DialogInputType;
import fr.maxlego08.menu.api.loader.ButtonLoader;
import fr.maxlego08.menu.hooks.dialogs.button.buttons.ZDialogBooleanInput;
import org.bukkit.configuration.file.YamlConfiguration;
diff --git a/Hooks/Paper/src/main/java/fr/maxlego08/menu/hooks/dialogs/button/loader/DialogItemBodyLoader.java b/Hooks/Paper/src/main/java/fr/maxlego08/menu/hooks/dialogs/button/loader/DialogItemBodyLoader.java
index d80d4212..2ec72dcf 100644
--- a/Hooks/Paper/src/main/java/fr/maxlego08/menu/hooks/dialogs/button/loader/DialogItemBodyLoader.java
+++ b/Hooks/Paper/src/main/java/fr/maxlego08/menu/hooks/dialogs/button/loader/DialogItemBodyLoader.java
@@ -13,7 +13,7 @@
public class DialogItemBodyLoader extends ButtonLoader {
public DialogItemBodyLoader(Plugin plugin) {
- super(plugin, "dialog_item");
+ super(plugin, "dialog_item", "item");
}
@Override
diff --git a/Hooks/Paper/src/main/java/fr/maxlego08/menu/hooks/dialogs/button/loader/DialogPlainMessageBodyLoader.java b/Hooks/Paper/src/main/java/fr/maxlego08/menu/hooks/dialogs/button/loader/DialogPlainMessageBodyLoader.java
index 9814badf..914b6b13 100644
--- a/Hooks/Paper/src/main/java/fr/maxlego08/menu/hooks/dialogs/button/loader/DialogPlainMessageBodyLoader.java
+++ b/Hooks/Paper/src/main/java/fr/maxlego08/menu/hooks/dialogs/button/loader/DialogPlainMessageBodyLoader.java
@@ -2,8 +2,6 @@
import fr.maxlego08.menu.api.button.Button;
import fr.maxlego08.menu.api.button.DefaultButtonValue;
-import fr.maxlego08.menu.api.button.dialogs.BodyButton;
-import fr.maxlego08.menu.api.enums.dialog.DialogBodyType;
import fr.maxlego08.menu.api.loader.ButtonLoader;
import fr.maxlego08.menu.hooks.dialogs.button.buttons.ZDialogPlainMessageBody;
import org.bukkit.configuration.file.YamlConfiguration;
@@ -15,7 +13,7 @@
public class DialogPlainMessageBodyLoader extends ButtonLoader {
public DialogPlainMessageBodyLoader(Plugin plugin) {
- super(plugin, "dialog_plain_message");
+ super(plugin, "dialog_plain_message", "plain_message");
}
@Override
diff --git a/Hooks/Paper/src/main/java/fr/maxlego08/menu/hooks/dialogs/button/loader/DialogTextInputLoader.java b/Hooks/Paper/src/main/java/fr/maxlego08/menu/hooks/dialogs/button/loader/DialogTextInputLoader.java
index 0de388a7..a700d02e 100644
--- a/Hooks/Paper/src/main/java/fr/maxlego08/menu/hooks/dialogs/button/loader/DialogTextInputLoader.java
+++ b/Hooks/Paper/src/main/java/fr/maxlego08/menu/hooks/dialogs/button/loader/DialogTextInputLoader.java
@@ -2,8 +2,6 @@
import fr.maxlego08.menu.api.button.Button;
import fr.maxlego08.menu.api.button.DefaultButtonValue;
-import fr.maxlego08.menu.api.button.dialogs.InputButton;
-import fr.maxlego08.menu.api.enums.dialog.DialogInputType;
import fr.maxlego08.menu.api.loader.ButtonLoader;
import fr.maxlego08.menu.hooks.dialogs.button.buttons.ZDialogTextInput;
import org.bukkit.configuration.file.YamlConfiguration;
diff --git a/Hooks/Paper/src/main/java/fr/maxlego08/menu/hooks/dialogs/loader/DialogLoader.java b/Hooks/Paper/src/main/java/fr/maxlego08/menu/hooks/dialogs/loader/DialogLoader.java
index 5d9374e1..0daff538 100644
--- a/Hooks/Paper/src/main/java/fr/maxlego08/menu/hooks/dialogs/loader/DialogLoader.java
+++ b/Hooks/Paper/src/main/java/fr/maxlego08/menu/hooks/dialogs/loader/DialogLoader.java
@@ -1,6 +1,5 @@
package fr.maxlego08.menu.hooks.dialogs.loader;
-import fr.maxlego08.menu.api.DialogInventory;
import fr.maxlego08.menu.api.InventoryOption;
import fr.maxlego08.menu.api.MenuPlugin;
import fr.maxlego08.menu.api.button.Button;
@@ -10,6 +9,7 @@
import fr.maxlego08.menu.api.enums.dialog.DialogType;
import fr.maxlego08.menu.api.exceptions.InventoryButtonException;
import fr.maxlego08.menu.api.exceptions.InventoryException;
+import fr.maxlego08.menu.api.inventory.dialog.DialogInventory;
import fr.maxlego08.menu.api.requirement.Requirement;
import fr.maxlego08.menu.api.utils.InventoryReplacement;
import fr.maxlego08.menu.api.utils.Loader;
diff --git a/Hooks/Paper/src/main/java/fr/maxlego08/menu/hooks/dialogs/loader/builder/DialogBuilderManager.java b/Hooks/Paper/src/main/java/fr/maxlego08/menu/hooks/dialogs/loader/builder/DialogBuilderManager.java
index 721d14c7..37660f65 100644
--- a/Hooks/Paper/src/main/java/fr/maxlego08/menu/hooks/dialogs/loader/builder/DialogBuilderManager.java
+++ b/Hooks/Paper/src/main/java/fr/maxlego08/menu/hooks/dialogs/loader/builder/DialogBuilderManager.java
@@ -7,6 +7,7 @@
import io.papermc.paper.registry.data.dialog.input.DialogInput;
import net.kyori.adventure.text.Component;
import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.Optional;
@@ -56,13 +57,12 @@ protected List buildDialogs(
return results;
}
- protected DialogBase.Builder createDialogBase(String dialogName, String externalTitle, boolean canCloseWithEscape, boolean canPauseGame, String afterAction){
- DialogBase.Builder dialogBuilder = DialogBase.builder(this.toComponent(dialogName))
+ protected DialogBase.Builder createDialogBase(@NotNull String dialogName,@NotNull String externalTitle, boolean canCloseWithEscape, boolean canPauseGame,@NotNull String afterAction){
+ return DialogBase.builder(this.toComponent(dialogName))
.externalTitle(this.toComponent(externalTitle))
.canCloseWithEscape(canCloseWithEscape)
.pause(canPauseGame)
- .afterAction(DialogBase.DialogAfterAction.valueOf(afterAction));
- return dialogBuilder;
+ .afterAction(DialogBase.DialogAfterAction.valueOf(afterAction.toUpperCase()));
}
public ComponentMeta getPaperComponent() {
diff --git a/Hooks/Paper/src/main/java/fr/maxlego08/menu/itemstack/components/paper/PaperAttackRangeComponent.java b/Hooks/Paper/src/main/java/fr/maxlego08/menu/itemstack/components/paper/PaperAttackRangeComponent.java
new file mode 100644
index 00000000..136bc2c6
--- /dev/null
+++ b/Hooks/Paper/src/main/java/fr/maxlego08/menu/itemstack/components/paper/PaperAttackRangeComponent.java
@@ -0,0 +1,25 @@
+package fr.maxlego08.menu.itemstack.components.paper;
+
+import fr.maxlego08.menu.api.context.BuildContext;
+import fr.maxlego08.menu.api.itemstack.components.AttackRangeComponent;
+import io.papermc.paper.datacomponent.DataComponentTypes;
+import io.papermc.paper.datacomponent.item.AttackRange;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemStack;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class PaperAttackRangeComponent extends AttackRangeComponent {
+ private final AttackRange attackRange;
+
+ public PaperAttackRangeComponent(AttackRange attackRange) {
+ super(attackRange.minReach(), attackRange.maxReach(), attackRange.minCreativeReach(), attackRange.maxCreativeReach(), attackRange.hitboxMargin(), attackRange.mobFactor());
+ this.attackRange = attackRange;
+ }
+
+
+ @Override
+ public void apply(@NotNull BuildContext context, @NotNull ItemStack itemStack, @Nullable Player player) {
+ itemStack.setData(DataComponentTypes.ATTACK_RANGE, this.attackRange);
+ }
+}
diff --git a/Hooks/Paper/src/main/java/fr/maxlego08/menu/itemstack/components/paper/PaperMaxStackSizeComponent.java b/Hooks/Paper/src/main/java/fr/maxlego08/menu/itemstack/components/paper/PaperMaxStackSizeComponent.java
new file mode 100644
index 00000000..8c588c2a
--- /dev/null
+++ b/Hooks/Paper/src/main/java/fr/maxlego08/menu/itemstack/components/paper/PaperMaxStackSizeComponent.java
@@ -0,0 +1,21 @@
+package fr.maxlego08.menu.itemstack.components.paper;
+
+import fr.maxlego08.menu.api.context.BuildContext;
+import fr.maxlego08.menu.api.itemstack.components.MaxStackSizeComponent;
+import io.papermc.paper.datacomponent.DataComponentTypes;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemStack;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class PaperMaxStackSizeComponent extends MaxStackSizeComponent {
+
+ public PaperMaxStackSizeComponent(int maxStackSize) {
+ super(maxStackSize);
+ }
+
+ @Override
+ public void apply(@NotNull BuildContext context, @NotNull ItemStack itemStack, @Nullable Player player) {
+ itemStack.setData(DataComponentTypes.MAX_STACK_SIZE, this.maxStackSize);
+ }
+}
diff --git a/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperAttackRangeItemComponentLoader.java b/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperAttackRangeItemComponentLoader.java
new file mode 100644
index 00000000..d9b4db12
--- /dev/null
+++ b/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperAttackRangeItemComponentLoader.java
@@ -0,0 +1,40 @@
+package fr.maxlego08.menu.loader.components.paper;
+
+import fr.maxlego08.menu.api.annotations.ComponentLoader;
+import fr.maxlego08.menu.api.annotations.PaperOnly;
+import fr.maxlego08.menu.api.annotations.SinceVersion;
+import fr.maxlego08.menu.api.context.MenuItemStackContext;
+import fr.maxlego08.menu.api.itemstack.ItemComponent;
+import fr.maxlego08.menu.itemstack.components.paper.PaperAttackRangeComponent;
+import fr.maxlego08.menu.loader.components.AbstractAttackRangeItemComponentLoader;
+import io.papermc.paper.datacomponent.item.AttackRange;
+import org.bukkit.configuration.ConfigurationSection;
+import org.bukkit.configuration.file.YamlConfiguration;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+
+@ComponentLoader
+@SinceVersion("1.21.11")
+@PaperOnly
+public class PaperAttackRangeItemComponentLoader extends AbstractAttackRangeItemComponentLoader {
+
+ @Override
+ public @Nullable ItemComponent load(@NotNull MenuItemStackContext context, @NotNull File file, @NotNull YamlConfiguration configuration, @NotNull String path, @Nullable ConfigurationSection componentSection) {
+ if (componentSection == null) {
+ return null;
+ }
+
+ AttackRange.Builder builder = AttackRange.attackRange();
+
+ builder.minReach(getMinReach(componentSection, path));
+ builder.maxReach(getMaxReach(componentSection, path));
+ builder.minCreativeReach(getMinCreativeReach(componentSection, path));
+ builder.maxCreativeReach(getMaxCreativeReach(componentSection, path));
+ builder.hitboxMargin(getHitboxMargin(componentSection, path));
+ builder.mobFactor(getMobFactor(componentSection, path));
+
+ return new PaperAttackRangeComponent(builder.build());
+ }
+}
diff --git a/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperChickenVariantLoader.java b/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperChickenVariantLoader.java
new file mode 100644
index 00000000..5dd739c0
--- /dev/null
+++ b/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperChickenVariantLoader.java
@@ -0,0 +1,19 @@
+package fr.maxlego08.menu.loader.components.paper;
+
+import fr.maxlego08.menu.api.MenuPlugin;
+import fr.maxlego08.menu.api.annotations.ComponentLoader;
+import fr.maxlego08.menu.api.annotations.PaperOnly;
+import fr.maxlego08.menu.api.annotations.SinceVersion;
+import fr.maxlego08.menu.common.interfaces.VariantComponent;
+import fr.maxlego08.menu.loader.components.variants.base.PaperRegistryVariantLoader;
+import io.papermc.paper.registry.RegistryKey;
+import org.bukkit.entity.Chicken;
+
+@ComponentLoader
+@PaperOnly
+@SinceVersion("1.21.5")
+public class PaperChickenVariantLoader extends PaperRegistryVariantLoader {
+ public PaperChickenVariantLoader(MenuPlugin plugin, VariantComponent variantFactory) {
+ super("chicken/variant", RegistryKey.CHICKEN_VARIANT, variantFactory::createChicken);
+ }
+}
diff --git a/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperCowVariantLoader.java b/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperCowVariantLoader.java
new file mode 100644
index 00000000..0713a7b7
--- /dev/null
+++ b/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperCowVariantLoader.java
@@ -0,0 +1,19 @@
+package fr.maxlego08.menu.loader.components.paper;
+
+import fr.maxlego08.menu.api.MenuPlugin;
+import fr.maxlego08.menu.api.annotations.ComponentLoader;
+import fr.maxlego08.menu.api.annotations.PaperOnly;
+import fr.maxlego08.menu.api.annotations.SinceVersion;
+import fr.maxlego08.menu.common.interfaces.VariantComponent;
+import fr.maxlego08.menu.loader.components.variants.base.PaperRegistryVariantLoader;
+import io.papermc.paper.registry.RegistryKey;
+import org.bukkit.entity.Cow;
+
+@ComponentLoader
+@PaperOnly
+@SinceVersion("1.21.5")
+public class PaperCowVariantLoader extends PaperRegistryVariantLoader {
+ public PaperCowVariantLoader(MenuPlugin plugin, VariantComponent variantFactory) {
+ super("cow/variant", RegistryKey.COW_VARIANT, variantFactory::createCow);
+ }
+}
diff --git a/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperCustomModelDataComponentLoader.java b/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperCustomModelDataComponentLoader.java
index 6ce124e0..3c1ed44d 100644
--- a/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperCustomModelDataComponentLoader.java
+++ b/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperCustomModelDataComponentLoader.java
@@ -1,9 +1,12 @@
package fr.maxlego08.menu.loader.components.paper;
+import fr.maxlego08.menu.api.annotations.ComponentLoader;
+import fr.maxlego08.menu.api.annotations.PaperOnly;
+import fr.maxlego08.menu.api.annotations.SinceVersion;
import fr.maxlego08.menu.api.context.MenuItemStackContext;
import fr.maxlego08.menu.api.itemstack.ItemComponent;
import fr.maxlego08.menu.itemstack.components.paper.PaperCustomModelDataComponent;
-import fr.maxlego08.menu.loader.components.spigot.SpigotCustomModelDataItemComponentLoader;
+import fr.maxlego08.menu.loader.components.SpigotCustomModelDataItemComponentLoader;
import io.papermc.paper.datacomponent.item.CustomModelData;
import org.bukkit.Color;
import org.bukkit.configuration.ConfigurationSection;
@@ -14,6 +17,9 @@
import java.io.File;
import java.util.List;
+@ComponentLoader
+@SinceVersion("1.20.5")
+@PaperOnly
public class PaperCustomModelDataComponentLoader extends SpigotCustomModelDataItemComponentLoader {
@Override
diff --git a/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperCustomNameItemComponentLoader.java b/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperCustomNameItemComponentLoader.java
index 7e5d4de3..09f6e741 100644
--- a/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperCustomNameItemComponentLoader.java
+++ b/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperCustomNameItemComponentLoader.java
@@ -1,6 +1,9 @@
package fr.maxlego08.menu.loader.components.paper;
import fr.maxlego08.menu.api.MenuPlugin;
+import fr.maxlego08.menu.api.annotations.ComponentLoader;
+import fr.maxlego08.menu.api.annotations.PaperOnly;
+import fr.maxlego08.menu.api.annotations.SinceVersion;
import fr.maxlego08.menu.api.context.MenuItemStackContext;
import fr.maxlego08.menu.api.itemstack.ItemComponent;
import fr.maxlego08.menu.api.loader.ItemComponentLoader;
@@ -13,6 +16,9 @@
import java.io.File;
+@ComponentLoader
+@SinceVersion("1.20.5")
+@PaperOnly
public class PaperCustomNameItemComponentLoader extends ItemComponentLoader {
private final PaperMetaUpdater metaUpdater;
diff --git a/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperDeathProtectionItemComponentLoader.java b/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperDeathProtectionItemComponentLoader.java
index 5c9615f4..0f5c2082 100644
--- a/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperDeathProtectionItemComponentLoader.java
+++ b/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperDeathProtectionItemComponentLoader.java
@@ -1,5 +1,8 @@
package fr.maxlego08.menu.loader.components.paper;
+import fr.maxlego08.menu.api.annotations.ComponentLoader;
+import fr.maxlego08.menu.api.annotations.PaperOnly;
+import fr.maxlego08.menu.api.annotations.SinceVersion;
import fr.maxlego08.menu.api.context.MenuItemStackContext;
import fr.maxlego08.menu.api.itemstack.ItemComponent;
import fr.maxlego08.menu.common.enums.ConsumeEffectType;
@@ -24,6 +27,9 @@
import java.util.List;
import java.util.Map;
+@ComponentLoader
+@SinceVersion("1.21.2")
+@PaperOnly
public class PaperDeathProtectionItemComponentLoader extends AbstractEffectItemComponentLoader {
public PaperDeathProtectionItemComponentLoader(){
diff --git a/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperIntangibleProjectileItemComponentLoader.java b/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperIntangibleProjectileItemComponentLoader.java
index 2b360dc1..1cfc38ac 100644
--- a/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperIntangibleProjectileItemComponentLoader.java
+++ b/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperIntangibleProjectileItemComponentLoader.java
@@ -1,5 +1,8 @@
package fr.maxlego08.menu.loader.components.paper;
+import fr.maxlego08.menu.api.annotations.ComponentLoader;
+import fr.maxlego08.menu.api.annotations.PaperOnly;
+import fr.maxlego08.menu.api.annotations.SinceVersion;
import fr.maxlego08.menu.api.context.MenuItemStackContext;
import fr.maxlego08.menu.api.itemstack.ItemComponent;
import fr.maxlego08.menu.api.loader.ItemComponentLoader;
@@ -11,6 +14,9 @@
import java.io.File;
+@ComponentLoader
+@SinceVersion("1.20.5")
+@PaperOnly
public class PaperIntangibleProjectileItemComponentLoader extends ItemComponentLoader {
public PaperIntangibleProjectileItemComponentLoader(){
diff --git a/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperMapDecorationsItemComponentLoader.java b/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperMapDecorationsItemComponentLoader.java
index 9cfd9215..456b5684 100644
--- a/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperMapDecorationsItemComponentLoader.java
+++ b/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperMapDecorationsItemComponentLoader.java
@@ -1,5 +1,8 @@
package fr.maxlego08.menu.loader.components.paper;
+import fr.maxlego08.menu.api.annotations.ComponentLoader;
+import fr.maxlego08.menu.api.annotations.PaperOnly;
+import fr.maxlego08.menu.api.annotations.SinceVersion;
import fr.maxlego08.menu.api.context.MenuItemStackContext;
import fr.maxlego08.menu.api.itemstack.ItemComponent;
import fr.maxlego08.menu.api.loader.ItemComponentLoader;
@@ -18,6 +21,9 @@
import java.util.HashMap;
import java.util.Map;
+@ComponentLoader
+@SinceVersion("1.20.5")
+@PaperOnly
public class PaperMapDecorationsItemComponentLoader extends ItemComponentLoader {
public PaperMapDecorationsItemComponentLoader(){
diff --git a/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperNoteBlockSoundItemComponentLoader.java b/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperNoteBlockSoundItemComponentLoader.java
index 2690215f..c36af59c 100644
--- a/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperNoteBlockSoundItemComponentLoader.java
+++ b/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperNoteBlockSoundItemComponentLoader.java
@@ -1,5 +1,8 @@
package fr.maxlego08.menu.loader.components.paper;
+import fr.maxlego08.menu.api.annotations.ComponentLoader;
+import fr.maxlego08.menu.api.annotations.PaperOnly;
+import fr.maxlego08.menu.api.annotations.SinceVersion;
import fr.maxlego08.menu.api.context.MenuItemStackContext;
import fr.maxlego08.menu.api.itemstack.ItemComponent;
import fr.maxlego08.menu.api.loader.ItemComponentLoader;
@@ -12,6 +15,9 @@
import java.io.File;
+@ComponentLoader
+@SinceVersion("1.20.5")
+@PaperOnly
public class PaperNoteBlockSoundItemComponentLoader extends ItemComponentLoader {
public PaperNoteBlockSoundItemComponentLoader(){
diff --git a/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperPigVariantLoader.java b/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperPigVariantLoader.java
new file mode 100644
index 00000000..ea201743
--- /dev/null
+++ b/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperPigVariantLoader.java
@@ -0,0 +1,19 @@
+package fr.maxlego08.menu.loader.components.paper;
+
+import fr.maxlego08.menu.api.MenuPlugin;
+import fr.maxlego08.menu.api.annotations.ComponentLoader;
+import fr.maxlego08.menu.api.annotations.PaperOnly;
+import fr.maxlego08.menu.api.annotations.SinceVersion;
+import fr.maxlego08.menu.common.interfaces.VariantComponent;
+import fr.maxlego08.menu.loader.components.variants.base.PaperRegistryVariantLoader;
+import io.papermc.paper.registry.RegistryKey;
+import org.bukkit.entity.Pig;
+
+@ComponentLoader
+@PaperOnly
+@SinceVersion("1.21.5")
+public class PaperPigVariantLoader extends PaperRegistryVariantLoader {
+ public PaperPigVariantLoader(MenuPlugin plugin, VariantComponent variantFactory) {
+ super("pig/variant", RegistryKey.PIG_VARIANT, variantFactory::createPig);
+ }
+}
diff --git a/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperPotDecorationsItemComponentLoader.java b/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperPotDecorationsItemComponentLoader.java
index cf6928af..159bd61b 100644
--- a/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperPotDecorationsItemComponentLoader.java
+++ b/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperPotDecorationsItemComponentLoader.java
@@ -1,5 +1,8 @@
package fr.maxlego08.menu.loader.components.paper;
+import fr.maxlego08.menu.api.annotations.ComponentLoader;
+import fr.maxlego08.menu.api.annotations.PaperOnly;
+import fr.maxlego08.menu.api.annotations.SinceVersion;
import fr.maxlego08.menu.api.context.MenuItemStackContext;
import fr.maxlego08.menu.api.itemstack.ItemComponent;
import fr.maxlego08.menu.api.loader.ItemComponentLoader;
@@ -16,6 +19,9 @@
import java.io.File;
import java.util.List;
+@ComponentLoader
+@SinceVersion("1.20.5")
+@PaperOnly
public class PaperPotDecorationsItemComponentLoader extends ItemComponentLoader {
private static final int SIDES = 4;
diff --git a/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperProvidesBannerPatternsItemComponentLoader.java b/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperProvidesBannerPatternsItemComponentLoader.java
index 4d77b9ee..872df11c 100644
--- a/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperProvidesBannerPatternsItemComponentLoader.java
+++ b/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperProvidesBannerPatternsItemComponentLoader.java
@@ -1,5 +1,8 @@
package fr.maxlego08.menu.loader.components.paper;
+import fr.maxlego08.menu.api.annotations.ComponentLoader;
+import fr.maxlego08.menu.api.annotations.PaperOnly;
+import fr.maxlego08.menu.api.annotations.SinceVersion;
import fr.maxlego08.menu.api.context.MenuItemStackContext;
import fr.maxlego08.menu.api.itemstack.ItemComponent;
import fr.maxlego08.menu.api.loader.ItemComponentLoader;
@@ -15,6 +18,9 @@
import java.io.File;
+@ComponentLoader
+@SinceVersion("1.21.5")
+@PaperOnly
public class PaperProvidesBannerPatternsItemComponentLoader extends ItemComponentLoader {
public PaperProvidesBannerPatternsItemComponentLoader(){
diff --git a/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperProvidesTrimMaterialItemComponentLoader.java b/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperProvidesTrimMaterialItemComponentLoader.java
index 4f5b471f..8f83b7c8 100644
--- a/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperProvidesTrimMaterialItemComponentLoader.java
+++ b/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperProvidesTrimMaterialItemComponentLoader.java
@@ -1,5 +1,8 @@
package fr.maxlego08.menu.loader.components.paper;
+import fr.maxlego08.menu.api.annotations.ComponentLoader;
+import fr.maxlego08.menu.api.annotations.PaperOnly;
+import fr.maxlego08.menu.api.annotations.SinceVersion;
import fr.maxlego08.menu.api.context.MenuItemStackContext;
import fr.maxlego08.menu.api.itemstack.ItemComponent;
import fr.maxlego08.menu.api.loader.ItemComponentLoader;
@@ -14,6 +17,9 @@
import java.io.File;
+@ComponentLoader
+@SinceVersion("1.21.5")
+@PaperOnly
public class PaperProvidesTrimMaterialItemComponentLoader extends ItemComponentLoader {
public PaperProvidesTrimMaterialItemComponentLoader(){
diff --git a/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperRepairableItemComponentLoader.java b/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperRepairableItemComponentLoader.java
index bb3df527..4069b84f 100644
--- a/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperRepairableItemComponentLoader.java
+++ b/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperRepairableItemComponentLoader.java
@@ -1,5 +1,8 @@
package fr.maxlego08.menu.loader.components.paper;
+import fr.maxlego08.menu.api.annotations.ComponentLoader;
+import fr.maxlego08.menu.api.annotations.PaperOnly;
+import fr.maxlego08.menu.api.annotations.SinceVersion;
import fr.maxlego08.menu.api.context.MenuItemStackContext;
import fr.maxlego08.menu.api.itemstack.ItemComponent;
import fr.maxlego08.menu.api.loader.ItemComponentLoader;
@@ -19,6 +22,9 @@
import java.util.ArrayList;
import java.util.List;
+@ComponentLoader
+@SinceVersion("1.21.2")
+@PaperOnly
public class PaperRepairableItemComponentLoader extends ItemComponentLoader {
public PaperRepairableItemComponentLoader(){
diff --git a/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperTooltipDisplayItemComponentLoader.java b/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperTooltipDisplayItemComponentLoader.java
index bf6b1aba..6c7c63c2 100644
--- a/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperTooltipDisplayItemComponentLoader.java
+++ b/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperTooltipDisplayItemComponentLoader.java
@@ -1,5 +1,8 @@
package fr.maxlego08.menu.loader.components.paper;
+import fr.maxlego08.menu.api.annotations.ComponentLoader;
+import fr.maxlego08.menu.api.annotations.PaperOnly;
+import fr.maxlego08.menu.api.annotations.SinceVersion;
import fr.maxlego08.menu.api.context.MenuItemStackContext;
import fr.maxlego08.menu.api.itemstack.ItemComponent;
import fr.maxlego08.menu.api.loader.ItemComponentLoader;
@@ -16,6 +19,9 @@
import java.io.File;
import java.util.List;
+@ComponentLoader
+@SinceVersion("1.21.5")
+@PaperOnly
public class PaperTooltipDisplayItemComponentLoader extends ItemComponentLoader {
public PaperTooltipDisplayItemComponentLoader(){
diff --git a/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperVariantItemComponentLoader.java b/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperVariantItemComponentLoader.java
index 461863e8..e69de29b 100644
--- a/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperVariantItemComponentLoader.java
+++ b/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/paper/PaperVariantItemComponentLoader.java
@@ -1,89 +0,0 @@
-package fr.maxlego08.menu.loader.components.paper;
-
-import fr.maxlego08.menu.api.context.MenuItemStackContext;
-import fr.maxlego08.menu.api.itemstack.ItemComponent;
-import fr.maxlego08.menu.api.loader.ItemComponentLoader;
-import fr.maxlego08.menu.common.factory.VariantItemComponentLoaderFactory;
-import fr.maxlego08.menu.common.interfaces.VariantComponent;
-import fr.maxlego08.menu.loader.components.spigot.SpigotVariantItemComponentLoader;
-import io.papermc.paper.registry.RegistryAccess;
-import io.papermc.paper.registry.RegistryKey;
-import org.bukkit.Keyed;
-import org.bukkit.NamespacedKey;
-import org.bukkit.configuration.ConfigurationSection;
-import org.bukkit.configuration.file.YamlConfiguration;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.io.File;
-import java.util.function.Function;
-
-/**
- * Paper-specific variant component loader that uses Paper's RegistryAccess API
- * for better performance and compatibility.
- */
-public class PaperVariantItemComponentLoader extends SpigotVariantItemComponentLoader implements VariantItemComponentLoaderFactory {
-
- public PaperVariantItemComponentLoader(VariantComponent variantFactory) {
- super(variantFactory);
- }
-
- @Override
- public @NotNull ItemComponentLoader getLoaderChicken() {
- return new Chicken();
- }
-
- @Override
- public @NotNull ItemComponentLoader getLoaderCow() {
- return new Cow();
- }
- @Override
- public @NotNull ItemComponentLoader getLoaderPig() {
- return new Pig();
- }
-
-
- private static abstract class PaperRegistryVariantLoader extends ItemComponentLoader {
- private final RegistryKey registryKey;
- private final Function componentFactory;
-
- protected PaperRegistryVariantLoader(String path, RegistryKey registryKey, Function componentFactory) {
- super(path);
- this.registryKey = registryKey;
- this.componentFactory = componentFactory;
- }
-
- @Override
- public @Nullable ItemComponent load(@NotNull MenuItemStackContext context, @NotNull File file, @NotNull YamlConfiguration configuration, @NotNull String path, @Nullable ConfigurationSection componentSection) {
- path = this.normalizePath(path);
- String value = configuration.getString(path);
- if (value == null) return null;
- NamespacedKey key = NamespacedKey.fromString(value);
- if (key == null) return null;
- try {
- T registryValue = RegistryAccess.registryAccess().getRegistry(this.registryKey).getOrThrow(key);
- return this.componentFactory.apply(registryValue);
- } catch (IllegalArgumentException e) {
- return null;
- }
- }
- }
-
- public class Chicken extends PaperRegistryVariantLoader {
- public Chicken() {
- super("chicken/variant", RegistryKey.CHICKEN_VARIANT, PaperVariantItemComponentLoader.this.variantFactory::createChicken);
- }
- }
-
- public class Cow extends PaperRegistryVariantLoader {
- public Cow() {
- super("cow/variant", RegistryKey.COW_VARIANT, PaperVariantItemComponentLoader.this.variantFactory::createCow);
- }
- }
-
- public class Pig extends PaperRegistryVariantLoader {
- public Pig() {
- super("pig/variant", RegistryKey.PIG_VARIANT, PaperVariantItemComponentLoader.this.variantFactory::createPig);
- }
- }
-}
\ No newline at end of file
diff --git a/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/variants/base/PaperRegistryVariantLoader.java b/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/variants/base/PaperRegistryVariantLoader.java
new file mode 100644
index 00000000..d749a3fe
--- /dev/null
+++ b/Hooks/Paper/src/main/java/fr/maxlego08/menu/loader/components/variants/base/PaperRegistryVariantLoader.java
@@ -0,0 +1,42 @@
+package fr.maxlego08.menu.loader.components.variants.base;
+
+import fr.maxlego08.menu.api.context.MenuItemStackContext;
+import fr.maxlego08.menu.api.itemstack.ItemComponent;
+import fr.maxlego08.menu.api.loader.ItemComponentLoader;
+import io.papermc.paper.registry.RegistryAccess;
+import io.papermc.paper.registry.RegistryKey;
+import org.bukkit.Keyed;
+import org.bukkit.NamespacedKey;
+import org.bukkit.configuration.ConfigurationSection;
+import org.bukkit.configuration.file.YamlConfiguration;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+import java.util.function.Function;
+
+public abstract class PaperRegistryVariantLoader extends ItemComponentLoader {
+ private final RegistryKey registryKey;
+ private final Function componentFactory;
+
+ protected PaperRegistryVariantLoader(String path, RegistryKey registryKey, Function componentFactory) {
+ super(path);
+ this.registryKey = registryKey;
+ this.componentFactory = componentFactory;
+ }
+
+ @Override
+ public @Nullable ItemComponent load(@NotNull MenuItemStackContext context, @NotNull File file, @NotNull YamlConfiguration configuration, @NotNull String path, @Nullable ConfigurationSection componentSection) {
+ path = normalizePath(path);
+ String value = configuration.getString(path);
+ if (value == null) return null;
+ NamespacedKey key = NamespacedKey.fromString(value);
+ if (key == null) return null;
+ try {
+ T registryValue = RegistryAccess.registryAccess().getRegistry(this.registryKey).getOrThrow(key);
+ return componentFactory.apply(registryValue);
+ } catch (IllegalArgumentException e) {
+ return null;
+ }
+ }
+}
diff --git a/Hooks/Paper/src/main/java/fr/maxlego08/menu/zcore/logger/ComponentLogger.java b/Hooks/Paper/src/main/java/fr/maxlego08/menu/zcore/logger/ComponentLogger.java
new file mode 100644
index 00000000..69c1028f
--- /dev/null
+++ b/Hooks/Paper/src/main/java/fr/maxlego08/menu/zcore/logger/ComponentLogger.java
@@ -0,0 +1,21 @@
+package fr.maxlego08.menu.zcore.logger;
+
+import fr.maxlego08.menu.hooks.ComponentMeta;
+import org.bukkit.Bukkit;
+import org.jetbrains.annotations.NotNull;
+
+public class ComponentLogger extends Logger {
+ private final ComponentMeta componentMeta;
+
+ public ComponentLogger(@NotNull String prefix,@NotNull ComponentMeta componentMeta) {
+ super(prefix);
+
+ this.componentMeta = componentMeta;
+ LogType.setIsAdventure(true);
+ }
+
+ @Override
+ public void log(@NotNull String message, @NotNull LogType type, Object... args) {
+ Bukkit.getConsoleSender().sendMessage(this.componentMeta.getComponent("[" + this.prefix + " ] " + type.getColor() + this.getColoredMessage(String.format(message, args))));
+ }
+}
diff --git a/Hooks/Shopkeepers/src/main/java/fr/maxlego08/menu/hooks/ShopkeeperAction.java b/Hooks/Shopkeepers/src/main/java/fr/maxlego08/menu/hooks/ShopkeeperAction.java
index 94408ae2..3dda4a62 100644
--- a/Hooks/Shopkeepers/src/main/java/fr/maxlego08/menu/hooks/ShopkeeperAction.java
+++ b/Hooks/Shopkeepers/src/main/java/fr/maxlego08/menu/hooks/ShopkeeperAction.java
@@ -4,9 +4,11 @@
import com.nisovin.shopkeepers.api.shopkeeper.Shopkeeper;
import fr.maxlego08.menu.api.MenuPlugin;
import fr.maxlego08.menu.api.button.Button;
+import fr.maxlego08.menu.api.configuration.Configuration;
import fr.maxlego08.menu.api.engine.InventoryEngine;
import fr.maxlego08.menu.api.requirement.Action;
import fr.maxlego08.menu.api.utils.Placeholders;
+import fr.maxlego08.menu.zcore.logger.Logger;
import org.bukkit.entity.Player;
import org.jspecify.annotations.NonNull;
@@ -28,8 +30,9 @@ protected void execute(@NonNull Player player, Button button, @NonNull Inventory
if (optional.isPresent()) {
optional.get().openTradingWindow(player);
} else {
- this.plugin.getLogger().severe("ShopKeeper " + this.shopName + " was not found !");
- player.sendMessage("ยงcShopKeeper " + this.shopName + " was not found !");
+ if (Configuration.enableDebug) {
+ Logger.info("ShopKeeper " + this.shopName + " was not found ! Available ShopKeepers: " + ShopkeepersAPI.getShopkeeperRegistry().getAllShopkeepers().stream().map(Shopkeeper::getName).toList());
+ }
}
}
}
diff --git a/Hooks/SlimeFun/build.gradle.kts b/Hooks/SlimeFun/build.gradle.kts
index ecb7d5e3..b63e8488 100644
--- a/Hooks/SlimeFun/build.gradle.kts
+++ b/Hooks/SlimeFun/build.gradle.kts
@@ -2,5 +2,5 @@ group = "Hooks:SlimeFun"
dependencies {
compileOnly(projects.common)
- compileOnly("com.github.Slimefun:Slimefun4:RC-34")
+ compileOnly(libs.slimefun4)
}
\ No newline at end of file
diff --git a/NMS/Base/build.gradle.kts b/NMS/Base/build.gradle.kts
new file mode 100644
index 00000000..34ca63b4
--- /dev/null
+++ b/NMS/Base/build.gradle.kts
@@ -0,0 +1,4 @@
+group = "fr.maxlego08.menu.nms"
+
+dependencies {
+}
diff --git a/NMS/Base/src/main/java/fr/maxlego08/menu/nms/NMSHandler.java b/NMS/Base/src/main/java/fr/maxlego08/menu/nms/NMSHandler.java
new file mode 100644
index 00000000..cd81d68a
--- /dev/null
+++ b/NMS/Base/src/main/java/fr/maxlego08/menu/nms/NMSHandler.java
@@ -0,0 +1,33 @@
+package fr.maxlego08.menu.nms;
+
+import org.bukkit.inventory.ItemStack;
+
+public interface NMSHandler {
+
+ ItemStack setString(ItemStack itemStack, String key, String value);
+
+ String getString(ItemStack itemStack, String key);
+
+ ItemStack setInt(ItemStack itemStack, String key, int value);
+
+ int getInt(ItemStack itemStack, String key);
+
+ ItemStack setDouble(ItemStack itemStack, String key, double value);
+
+ double getDouble(ItemStack itemStack, String key);
+
+ ItemStack setLong(ItemStack itemStack, String key, long value);
+
+ long getLong(ItemStack itemStack, String key);
+
+ ItemStack setFloat(ItemStack itemStack, String key, float value);
+
+ float getFloat(ItemStack itemStack, String key);
+
+ ItemStack setBoolean(ItemStack itemStack, String key, boolean value);
+
+ boolean getBoolean(ItemStack itemStack, String key);
+
+ boolean hasKey(ItemStack itemStack, String key);
+
+}
diff --git a/NMS/Base/src/main/java/fr/maxlego08/menu/nms/NMSVersion.java b/NMS/Base/src/main/java/fr/maxlego08/menu/nms/NMSVersion.java
new file mode 100644
index 00000000..48b47277
--- /dev/null
+++ b/NMS/Base/src/main/java/fr/maxlego08/menu/nms/NMSVersion.java
@@ -0,0 +1,16 @@
+package fr.maxlego08.menu.nms;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface NMSVersion {
+ /**
+ * The minimum Minecraft version required for this implementation.
+ * Format: "major.minor.patch" (e.g., "1.21", "1.20.5")
+ */
+ String value();
+}
diff --git a/NMS/v1_20_R3/build.gradle.kts b/NMS/v1_20_R3/build.gradle.kts
new file mode 100644
index 00000000..454437c8
--- /dev/null
+++ b/NMS/v1_20_R3/build.gradle.kts
@@ -0,0 +1,11 @@
+plugins {
+ alias(libs.plugins.paperweight)
+}
+
+group = "fr.maxlego08.menu.nms.v1_20_R3"
+
+dependencies {
+ compileOnly(projects.common)
+ compileOnly(projects.nms.base)
+ paperweightDevelopmentBundle(libs.paperDevBundle120R3)
+}
diff --git a/NMS/v1_20_R3/src/main/java/fr/maxlego08/menu/nms/v1_20_R3/NMSHandlerImpl.java b/NMS/v1_20_R3/src/main/java/fr/maxlego08/menu/nms/v1_20_R3/NMSHandlerImpl.java
new file mode 100644
index 00000000..8e3455d6
--- /dev/null
+++ b/NMS/v1_20_R3/src/main/java/fr/maxlego08/menu/nms/v1_20_R3/NMSHandlerImpl.java
@@ -0,0 +1,110 @@
+package fr.maxlego08.menu.nms.v1_20_R3;
+
+import fr.maxlego08.menu.nms.NMSHandler;
+import fr.maxlego08.menu.nms.NMSVersion;
+import net.minecraft.nbt.CompoundTag;
+import org.bukkit.craftbukkit.v1_20_R3.inventory.CraftItemStack;
+import org.bukkit.inventory.ItemStack;
+
+@NMSVersion("1.20")
+public class NMSHandlerImpl implements NMSHandler {
+
+ private net.minecraft.world.item.ItemStack asNMS(ItemStack itemStack) {
+ return CraftItemStack.asNMSCopy(itemStack);
+ }
+
+ private ItemStack asBukkit(net.minecraft.world.item.ItemStack nmsItem) {
+ return CraftItemStack.asBukkitCopy(nmsItem);
+ }
+
+ @Override
+ public ItemStack setString(ItemStack itemStack, String key, String value) {
+ net.minecraft.world.item.ItemStack nmsItem = asNMS(itemStack);
+ nmsItem.getOrCreateTag().putString(key, value);
+ return asBukkit(nmsItem);
+ }
+
+ @Override
+ public String getString(ItemStack itemStack, String key) {
+ net.minecraft.world.item.ItemStack nmsItem = asNMS(itemStack);
+ CompoundTag tag = nmsItem.getTag();
+ return (tag != null && tag.contains(key)) ? tag.getString(key) : null;
+ }
+
+ @Override
+ public ItemStack setInt(ItemStack itemStack, String key, int value) {
+ net.minecraft.world.item.ItemStack nmsItem = asNMS(itemStack);
+ nmsItem.getOrCreateTag().putInt(key, value);
+ return asBukkit(nmsItem);
+ }
+
+ @Override
+ public int getInt(ItemStack itemStack, String key) {
+ net.minecraft.world.item.ItemStack nmsItem = asNMS(itemStack);
+ CompoundTag tag = nmsItem.getTag();
+ return (tag != null && tag.contains(key)) ? tag.getInt(key) : 0;
+ }
+
+ @Override
+ public ItemStack setDouble(ItemStack itemStack, String key, double value) {
+ net.minecraft.world.item.ItemStack nmsItem = asNMS(itemStack);
+ nmsItem.getOrCreateTag().putDouble(key, value);
+ return asBukkit(nmsItem);
+ }
+
+ @Override
+ public double getDouble(ItemStack itemStack, String key) {
+ net.minecraft.world.item.ItemStack nmsItem = asNMS(itemStack);
+ CompoundTag tag = nmsItem.getTag();
+ return (tag != null && tag.contains(key)) ? tag.getDouble(key) : 0;
+ }
+
+ @Override
+ public ItemStack setLong(ItemStack itemStack, String key, long value) {
+ net.minecraft.world.item.ItemStack nmsItem = asNMS(itemStack);
+ nmsItem.getOrCreateTag().putLong(key, value);
+ return asBukkit(nmsItem);
+ }
+
+ @Override
+ public long getLong(ItemStack itemStack, String key) {
+ net.minecraft.world.item.ItemStack nmsItem = asNMS(itemStack);
+ CompoundTag tag = nmsItem.getTag();
+ return (tag != null && tag.contains(key)) ? tag.getLong(key) : 0;
+ }
+
+ @Override
+ public ItemStack setFloat(ItemStack itemStack, String key, float value) {
+ net.minecraft.world.item.ItemStack nmsItem = asNMS(itemStack);
+ nmsItem.getOrCreateTag().putFloat(key, value);
+ return asBukkit(nmsItem);
+ }
+
+ @Override
+ public float getFloat(ItemStack itemStack, String key) {
+ net.minecraft.world.item.ItemStack nmsItem = asNMS(itemStack);
+ CompoundTag tag = nmsItem.getTag();
+ return (tag != null && tag.contains(key)) ? tag.getFloat(key) : 0;
+ }
+
+ @Override
+ public ItemStack setBoolean(ItemStack itemStack, String key, boolean value) {
+ net.minecraft.world.item.ItemStack nmsItem = asNMS(itemStack);
+ nmsItem.getOrCreateTag().putBoolean(key, value);
+ return asBukkit(nmsItem);
+ }
+
+ @Override
+ public boolean getBoolean(ItemStack itemStack, String key) {
+ net.minecraft.world.item.ItemStack nmsItem = asNMS(itemStack);
+ CompoundTag tag = nmsItem.getTag();
+ return (tag != null && tag.contains(key)) && tag.getBoolean(key);
+ }
+
+ @Override
+ public boolean hasKey(ItemStack itemStack, String key) {
+ net.minecraft.world.item.ItemStack nmsItem = asNMS(itemStack);
+ CompoundTag tag = nmsItem.getTag();
+ return tag != null && tag.contains(key);
+ }
+}
diff --git a/NMS/v1_20_R4/build.gradle.kts b/NMS/v1_20_R4/build.gradle.kts
new file mode 100644
index 00000000..f1f42efd
--- /dev/null
+++ b/NMS/v1_20_R4/build.gradle.kts
@@ -0,0 +1,11 @@
+plugins {
+ alias(libs.plugins.paperweight)
+}
+
+group = "fr.maxlego08.menu.nms.v1_20_R4"
+
+dependencies {
+ compileOnly(projects.common)
+ compileOnly(projects.nms.base)
+ paperweightDevelopmentBundle(libs.paperDevBundle120R4)
+}
diff --git a/NMS/v1_20_R4/src/main/java/fr/maxlego08/menu/nms/v1_20_R4/NMSHandlerImpl.java b/NMS/v1_20_R4/src/main/java/fr/maxlego08/menu/nms/v1_20_R4/NMSHandlerImpl.java
new file mode 100644
index 00000000..67229d3d
--- /dev/null
+++ b/NMS/v1_20_R4/src/main/java/fr/maxlego08/menu/nms/v1_20_R4/NMSHandlerImpl.java
@@ -0,0 +1,147 @@
+package fr.maxlego08.menu.nms.v1_20_R4;
+
+import fr.maxlego08.menu.nms.NMSHandler;
+import fr.maxlego08.menu.nms.NMSVersion;
+import net.minecraft.core.component.DataComponents;
+import net.minecraft.nbt.CompoundTag;
+import net.minecraft.world.item.component.CustomData;
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
+import org.bukkit.inventory.ItemStack;
+
+@NMSVersion("1.20.5")
+public class NMSHandlerImpl implements NMSHandler {
+
+ private net.minecraft.world.item.ItemStack asNMS(ItemStack itemStack) {
+ return CraftItemStack.asNMSCopy(itemStack);
+ }
+
+ private ItemStack asBukkit(net.minecraft.world.item.ItemStack nmsItem) {
+ return CraftItemStack.asBukkitCopy(nmsItem);
+ }
+
+ private CompoundTag getTag(net.minecraft.world.item.ItemStack nmsItem) {
+ CustomData customData = nmsItem.get(DataComponents.CUSTOM_DATA);
+ return customData != null ? customData.copyTag() : new CompoundTag();
+ }
+
+ private void setTag(net.minecraft.world.item.ItemStack nmsItem, CompoundTag tag) {
+ nmsItem.set(DataComponents.CUSTOM_DATA, CustomData.of(tag));
+ }
+
+ @Override
+ public ItemStack setString(ItemStack itemStack, String key, String value) {
+ net.minecraft.world.item.ItemStack nmsItem = asNMS(itemStack);
+ CompoundTag tag = getTag(nmsItem);
+ tag.putString(key, value);
+ setTag(nmsItem, tag);
+ return asBukkit(nmsItem);
+ }
+
+ @Override
+ public String getString(ItemStack itemStack, String key) {
+ net.minecraft.world.item.ItemStack nmsItem = asNMS(itemStack);
+ CustomData customData = nmsItem.get(DataComponents.CUSTOM_DATA);
+ if (customData == null) return null;
+ CompoundTag tag = customData.copyTag();
+ return tag.contains(key) ? tag.getString(key) : null;
+ }
+
+ @Override
+ public ItemStack setInt(ItemStack itemStack, String key, int value) {
+ net.minecraft.world.item.ItemStack nmsItem = asNMS(itemStack);
+ CompoundTag tag = getTag(nmsItem);
+ tag.putInt(key, value);
+ setTag(nmsItem, tag);
+ return asBukkit(nmsItem);
+ }
+
+ @Override
+ public int getInt(ItemStack itemStack, String key) {
+ net.minecraft.world.item.ItemStack nmsItem = asNMS(itemStack);
+ CustomData customData = nmsItem.get(DataComponents.CUSTOM_DATA);
+ if (customData == null) return 0;
+ CompoundTag tag = customData.copyTag();
+ return tag.getInt(key);
+ }
+
+ @Override
+ public ItemStack setDouble(ItemStack itemStack, String key, double value) {
+ net.minecraft.world.item.ItemStack nmsItem = asNMS(itemStack);
+ CompoundTag tag = getTag(nmsItem);
+ tag.putDouble(key, value);
+ setTag(nmsItem, tag);
+ return asBukkit(nmsItem);
+ }
+
+ @Override
+ public double getDouble(ItemStack itemStack, String key) {
+ net.minecraft.world.item.ItemStack nmsItem = asNMS(itemStack);
+ CustomData customData = nmsItem.get(DataComponents.CUSTOM_DATA);
+ if (customData == null) return 0;
+ CompoundTag tag = customData.copyTag();
+ return tag.getDouble(key);
+ }
+
+ @Override
+ public ItemStack setLong(ItemStack itemStack, String key, long value) {
+ net.minecraft.world.item.ItemStack nmsItem = asNMS(itemStack);
+ CompoundTag tag = getTag(nmsItem);
+ tag.putLong(key, value);
+ setTag(nmsItem, tag);
+ return asBukkit(nmsItem);
+ }
+
+ @Override
+ public long getLong(ItemStack itemStack, String key) {
+ net.minecraft.world.item.ItemStack nmsItem = asNMS(itemStack);
+ CustomData customData = nmsItem.get(DataComponents.CUSTOM_DATA);
+ if (customData == null) return 0;
+ CompoundTag tag = customData.copyTag();
+ return tag.getLong(key);
+ }
+
+ @Override
+ public ItemStack setFloat(ItemStack itemStack, String key, float value) {
+ net.minecraft.world.item.ItemStack nmsItem = asNMS(itemStack);
+ CompoundTag tag = getTag(nmsItem);
+ tag.putFloat(key, value);
+ setTag(nmsItem, tag);
+ return asBukkit(nmsItem);
+ }
+
+ @Override
+ public float getFloat(ItemStack itemStack, String key) {
+ net.minecraft.world.item.ItemStack nmsItem = asNMS(itemStack);
+ CustomData customData = nmsItem.get(DataComponents.CUSTOM_DATA);
+ if (customData == null) return 0;
+ CompoundTag tag = customData.copyTag();
+ return tag.getFloat(key);
+ }
+
+ @Override
+ public ItemStack setBoolean(ItemStack itemStack, String key, boolean value) {
+ net.minecraft.world.item.ItemStack nmsItem = asNMS(itemStack);
+ CompoundTag tag = getTag(nmsItem);
+ tag.putBoolean(key, value);
+ setTag(nmsItem, tag);
+ return asBukkit(nmsItem);
+ }
+
+ @Override
+ public boolean getBoolean(ItemStack itemStack, String key) {
+ net.minecraft.world.item.ItemStack nmsItem = asNMS(itemStack);
+ CustomData customData = nmsItem.get(DataComponents.CUSTOM_DATA);
+ if (customData == null) return false;
+ CompoundTag tag = customData.copyTag();
+ return tag.getBoolean(key);
+ }
+
+ @Override
+ public boolean hasKey(ItemStack itemStack, String key) {
+ net.minecraft.world.item.ItemStack nmsItem = asNMS(itemStack);
+ CustomData customData = nmsItem.get(DataComponents.CUSTOM_DATA);
+ if (customData == null) return false;
+ CompoundTag tag = customData.copyTag();
+ return tag.contains(key);
+ }
+}
diff --git a/NMS/v1_21_R1/build.gradle.kts b/NMS/v1_21_R1/build.gradle.kts
new file mode 100644
index 00000000..eec8ca5b
--- /dev/null
+++ b/NMS/v1_21_R1/build.gradle.kts
@@ -0,0 +1,11 @@
+plugins {
+ alias(libs.plugins.paperweight)
+}
+
+group = "fr.maxlego08.menu.nms.v1_21_R1"
+
+dependencies {
+ compileOnly(projects.common)
+ compileOnly(projects.nms.base)
+ paperweightDevelopmentBundle(libs.paperDevBundle121R1)
+}
diff --git a/NMS/v1_21_R1/src/main/java/fr/maxlego08/menu/nms/v1_21_R1/NMSHandlerImpl.java b/NMS/v1_21_R1/src/main/java/fr/maxlego08/menu/nms/v1_21_R1/NMSHandlerImpl.java
new file mode 100644
index 00000000..0f1c4e5a
--- /dev/null
+++ b/NMS/v1_21_R1/src/main/java/fr/maxlego08/menu/nms/v1_21_R1/NMSHandlerImpl.java
@@ -0,0 +1,147 @@
+package fr.maxlego08.menu.nms.v1_21_R1;
+
+import fr.maxlego08.menu.nms.NMSHandler;
+import fr.maxlego08.menu.nms.NMSVersion;
+import net.minecraft.core.component.DataComponents;
+import net.minecraft.nbt.CompoundTag;
+import net.minecraft.world.item.component.CustomData;
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
+import org.bukkit.inventory.ItemStack;
+
+@NMSVersion("1.21")
+public class NMSHandlerImpl implements NMSHandler {
+
+ private net.minecraft.world.item.ItemStack asNMS(ItemStack itemStack) {
+ return CraftItemStack.asNMSCopy(itemStack);
+ }
+
+ private ItemStack asBukkit(net.minecraft.world.item.ItemStack nmsItem) {
+ return CraftItemStack.asBukkitCopy(nmsItem);
+ }
+
+ private CompoundTag getTag(net.minecraft.world.item.ItemStack nmsItem) {
+ CustomData customData = nmsItem.get(DataComponents.CUSTOM_DATA);
+ return customData != null ? customData.copyTag() : new CompoundTag();
+ }
+
+ private void setTag(net.minecraft.world.item.ItemStack nmsItem, CompoundTag tag) {
+ nmsItem.set(DataComponents.CUSTOM_DATA, CustomData.of(tag));
+ }
+
+ @Override
+ public ItemStack setString(ItemStack itemStack, String key, String value) {
+ net.minecraft.world.item.ItemStack nmsItem = asNMS(itemStack);
+ CompoundTag tag = getTag(nmsItem);
+ tag.putString(key, value);
+ setTag(nmsItem, tag);
+ return asBukkit(nmsItem);
+ }
+
+ @Override
+ public String getString(ItemStack itemStack, String key) {
+ net.minecraft.world.item.ItemStack nmsItem = asNMS(itemStack);
+ CustomData customData = nmsItem.get(DataComponents.CUSTOM_DATA);
+ if (customData == null) return null;
+ CompoundTag tag = customData.copyTag();
+ return tag.contains(key) ? tag.getString(key) : null;
+ }
+
+ @Override
+ public ItemStack setInt(ItemStack itemStack, String key, int value) {
+ net.minecraft.world.item.ItemStack nmsItem = asNMS(itemStack);
+ CompoundTag tag = getTag(nmsItem);
+ tag.putInt(key, value);
+ setTag(nmsItem, tag);
+ return asBukkit(nmsItem);
+ }
+
+ @Override
+ public int getInt(ItemStack itemStack, String key) {
+ net.minecraft.world.item.ItemStack nmsItem = asNMS(itemStack);
+ CustomData customData = nmsItem.get(DataComponents.CUSTOM_DATA);
+ if (customData == null) return 0;
+ CompoundTag tag = customData.copyTag();
+ return tag.getInt(key);
+ }
+
+ @Override
+ public ItemStack setDouble(ItemStack itemStack, String key, double value) {
+ net.minecraft.world.item.ItemStack nmsItem = asNMS(itemStack);
+ CompoundTag tag = getTag(nmsItem);
+ tag.putDouble(key, value);
+ setTag(nmsItem, tag);
+ return asBukkit(nmsItem);
+ }
+
+ @Override
+ public double getDouble(ItemStack itemStack, String key) {
+ net.minecraft.world.item.ItemStack nmsItem = asNMS(itemStack);
+ CustomData customData = nmsItem.get(DataComponents.CUSTOM_DATA);
+ if (customData == null) return 0;
+ CompoundTag tag = customData.copyTag();
+ return tag.getDouble(key);
+ }
+
+ @Override
+ public ItemStack setLong(ItemStack itemStack, String key, long value) {
+ net.minecraft.world.item.ItemStack nmsItem = asNMS(itemStack);
+ CompoundTag tag = getTag(nmsItem);
+ tag.putLong(key, value);
+ setTag(nmsItem, tag);
+ return asBukkit(nmsItem);
+ }
+
+ @Override
+ public long getLong(ItemStack itemStack, String key) {
+ net.minecraft.world.item.ItemStack nmsItem = asNMS(itemStack);
+ CustomData customData = nmsItem.get(DataComponents.CUSTOM_DATA);
+ if (customData == null) return 0;
+ CompoundTag tag = customData.copyTag();
+ return tag.getLong(key);
+ }
+
+ @Override
+ public ItemStack setFloat(ItemStack itemStack, String key, float value) {
+ net.minecraft.world.item.ItemStack nmsItem = asNMS(itemStack);
+ CompoundTag tag = getTag(nmsItem);
+ tag.putFloat(key, value);
+ setTag(nmsItem, tag);
+ return asBukkit(nmsItem);
+ }
+
+ @Override
+ public float getFloat(ItemStack itemStack, String key) {
+ net.minecraft.world.item.ItemStack nmsItem = asNMS(itemStack);
+ CustomData customData = nmsItem.get(DataComponents.CUSTOM_DATA);
+ if (customData == null) return 0;
+ CompoundTag tag = customData.copyTag();
+ return tag.getFloat(key);
+ }
+
+ @Override
+ public ItemStack setBoolean(ItemStack itemStack, String key, boolean value) {
+ net.minecraft.world.item.ItemStack nmsItem = asNMS(itemStack);
+ CompoundTag tag = getTag(nmsItem);
+ tag.putBoolean(key, value);
+ setTag(nmsItem, tag);
+ return asBukkit(nmsItem);
+ }
+
+ @Override
+ public boolean getBoolean(ItemStack itemStack, String key) {
+ net.minecraft.world.item.ItemStack nmsItem = asNMS(itemStack);
+ CustomData customData = nmsItem.get(DataComponents.CUSTOM_DATA);
+ if (customData == null) return false;
+ CompoundTag tag = customData.copyTag();
+ return tag.getBoolean(key);
+ }
+
+ @Override
+ public boolean hasKey(ItemStack itemStack, String key) {
+ net.minecraft.world.item.ItemStack nmsItem = asNMS(itemStack);
+ CustomData customData = nmsItem.get(DataComponents.CUSTOM_DATA);
+ if (customData == null) return false;
+ CompoundTag tag = customData.copyTag();
+ return tag.contains(key);
+ }
+}
diff --git a/build.gradle.kts b/build.gradle.kts
index b664e832..aa0c8ccf 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,7 +1,7 @@
plugins {
`java-library`
- id("com.gradleup.shadow") version "9.0.0"
- id("re.alwyn974.groupez.repository") version "1.0.0"
+ alias(libs.plugins.shadow)
+ alias(libs.plugins.groupez.repository)
}
group = "fr.maxlego08.menu"
@@ -12,6 +12,8 @@ extra.set("apiFolder", file("target-api/"))
extra.set("classifier", System.getProperty("archive.classifier"))
extra.set("sha", System.getProperty("github.sha"))
+val rootLibs = libs
+
allprojects {
apply(plugin = "java-library")
apply(plugin = "com.gradleup.shadow")
@@ -31,6 +33,7 @@ allprojects {
maven(url = "https://repo.tcoded.com/releases")
maven(url = "https://repo.codemc.io/repository/maven-releases/")
maven(url = "https://repo.codemc.io/repository/maven-snapshots/")
+ maven(url = "https://repo.papermc.io/repository/maven-public/")
maven(url = "https://hub.spigotmc.org/nexus/content/repositories/snapshots/")
maven(url = "https://hub.spigotmc.org/nexus/content/groups/public/")
maven(url = "https://repo.extendedclip.com/content/repositories/placeholderapi/")
@@ -46,7 +49,7 @@ allprojects {
java {
toolchain {
- languageVersion.set(JavaLanguageVersion.of(21))
+ languageVersion.set(JavaLanguageVersion.of(25))
}
withSourcesJar()
if (project.name == "API") {
@@ -103,21 +106,22 @@ allprojects {
}
dependencies {
- if (project.name != "Paper") {
- compileOnly("org.spigotmc:spigot-api:26.1-R0.1-SNAPSHOT")
+ if (project.name != "Paper" && project.name != "Common") {
+ compileOnly(rootLibs.spigot.api)
}
- compileOnly("me.clip:placeholderapi:2.11.6")
+ compileOnly(rootLibs.placeholderapi)
+ compileOnly(rootLibs.reflections)
- implementation("fr.maxlego08.sarah:sarah:1.22")
- implementation("fr.traqueur.currencies:currenciesapi:1.0.13")
- implementation("com.tcoded:FoliaLib:0.5.1")
+ implementation(rootLibs.sarah)
+ implementation(rootLibs.currenciesapi)
+ implementation(rootLibs.folialib)
- implementation("com.github.cryptomorin:XSeries:13.3.0")
- implementation("net.objecthunter:exp4j:0.4.8")
+ implementation(rootLibs.xseries)
+ implementation(rootLibs.exp4j)
- testImplementation(platform("org.junit:junit-bom:5.10.0"))
- testImplementation("org.junit.jupiter:junit-jupiter")
- testRuntimeOnly("org.junit.platform:junit-platform-launcher")
+ testImplementation(platform(rootLibs.junit.bom))
+ testImplementation(rootLibs.junit.jupiter)
+ testRuntimeOnly(rootLibs.junit.platform.launcher)
}
}
@@ -129,7 +133,11 @@ dependencies {
api(projects.api)
api(projects.common)
api(projects.hooks)
- implementation("de.tr7zw:item-nbt-api:2.15.0")
+ implementation(projects.nms.base)
+ implementation(projects.nms.v121R1)
+ implementation(projects.nms.v120R4)
+ implementation(projects.nms.v120R3)
+ implementation(libs.item.nbt.api)
}
tasks {
diff --git a/changelog.md b/changelog.md
index b6d31799..f89902e8 100644
--- a/changelog.md
+++ b/changelog.md
@@ -42,6 +42,27 @@
# Unreleased
+- **Take Item Action**: New `take-item` action to remove a specified amount of an item from the player's inventory.
+```yaml
+- type: take-item
+ item:
+ material: DIAMOND
+ amount: 5
+```
+- **Custom Commands**: Add a new field `actions-requirements` for custom commands, allowing you to specify requirements that must be met for the command's actions to execute. This provides more control over argument conditions and enhances command functionality.
+
+**Internal Changes**
+
+- New Minecraft version detection system `MinecraftVersion` over old `NMSVersion` enum, allowing more flexible version checks and better support for future Minecraft versions without needing to update the plugin.
+- New utils annotations
+ - `@SinceVersion` | These annotations can be used to mark classes that should only be loaded for specific Minecraft versions, check in the `VersionFilter` class for more details.
+ - `@UntilVersion` | These annotations can be used to mark classes that should only be loaded for specific Minecraft versions, check in the `VersionFilter` class for more details.
+ - `@PaperOnly` | These annotations can be used to mark classes that should only be loaded if the server is a Paper version, check in the `VersionFilter` class for more details.
+ - `@SpigotOnly` | These annotations can be used to mark classes that should only be loaded if the server is a spigot version, check in the `VersionFilter` class for more details.
+ - `@ComponentLoader` | Allow to load dynamically all items component loader without having to register them one by one in the `ZComponentManager` class for "fr.maxlego08.zmenu" package, filtering by version and server type with the new annotations by the helper of `VersionFilter` class.
+ - `@AutoListener` | Allow to load dynamically all listeners who take a `MenuPlugin` in their constructor or no-arg constructor without having to register them one by one in the `ZListenerManager` class for "fr.maxlego08.zmenu" package, filtering by version and server type with the new annotations by the helper of `VersionFilter` class.
+
+
# 1.1.1.4
## New Features
@@ -53,7 +74,7 @@
## Bug Fixes
-- **Clear Inventory + BACK Button**: Fixed items being restored to the player when clicking a BACK button between two inventories with `clear-inventory: true` and `clear-inventory-type: PACKET_EVENT`. Items are now physically cleared from the player inventory during storage, ensuring container content packets don't reveal hidden items. The close handler also uses physical restoration (`giveInventory`) instead of packet-based restoration.
+- **Clear Inventory + BACK Button**: Fixed items being restored to the player when clicking a BACK button between two inventories with `clear-inventory: true` and `clear-inventory-type: PACKET_EVENT`.
- **Item Pickup with Clear Inventory**: Fixed items being picked up by the player when `clear-inventory` is enabled.
- **Lore Metadata Duplication**: Fixed "lore" metadata duplication when loading items.
- **Color Handling**: Fixed and simplified color handling for leather armor and banner patterns in `MenuItemStackLoader`.
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
new file mode 100644
index 00000000..16ad6402
--- /dev/null
+++ b/gradle/libs.versions.toml
@@ -0,0 +1,101 @@
+[versions]
+# Build / Plugins
+shadow = "9.0.0"
+groupez = "1.0.0"
+paperweight = "2.0.0-beta.21"
+
+# Platforms (Paper / Spigot / NMS)
+spigot = "26.1-R0.1-SNAPSHOT"
+paper-api = "1.21.11-R0.1-SNAPSHOT"
+paperDevBundle = "26.1.2.build.+"
+paperDevBundle120R3 = "1.20.4-R0.1-SNAPSHOT"
+paperDevBundle120R4 = "1.20.6-R0.1-SNAPSHOT"
+paperDevBundle121R1 = "1.21.1-R0.1-SNAPSHOT"
+adventure-api = "4.25.0"
+adventure-text-minimessage = "4.21.0"
+item-nbt-api = "2.15.0"
+
+# Utilities / Libraries
+sarah = "1.22"
+currenciesapi = "1.0.13"
+folialib = "0.5.1"
+xseries = "13.3.0"
+exp4j = "0.4.8"
+
+# Integration Hooks
+placeholderapi = "2.11.6"
+reflections = "0.10.2"
+slimefun4 = "RC-34"
+oraxen = "1.190.0"
+packetevents = "2.12.1"
+nova-api = "0.14.10"
+nexo = "1.21.0"
+mythicmobs = "5.6.1"
+mmoitems = "6.9.5-SNAPSHOT"
+luckperms = "5.4"
+magiccosmetics = "2.2.8"
+itemsadder = "3.6.1"
+hmccosmetics = "2.7.7"
+headdatabase = "1.3.2"
+score = "5.25.6.9"
+craft-engine = "26.5"
+eco = "6.53.0"
+floodgate = "2.2.4-SNAPSHOT"
+breweryx = "3.6.0"
+
+# Testing
+junit-bom = "5.10.0"
+
+[libraries]
+# Platforms (Paper / Spigot / NMS)
+spigot-api = { group = "org.spigotmc", name = "spigot-api", version.ref = "spigot" }
+paper-api = { group = "io.papermc.paper", name = "paper-api", version.ref = "paper-api" }
+paperDevBundle120R3 = { group = "io.papermc.paper", name = "dev-bundle", version.ref = "paperDevBundle120R3" }
+paperDevBundle120R4 = { group = "io.papermc.paper", name = "dev-bundle", version.ref = "paperDevBundle120R4" }
+paperDevBundle121R1 = { group = "io.papermc.paper", name = "dev-bundle", version.ref = "paperDevBundle121R1" }
+adventure-api = { group = "net.kyori", name = "adventure-api", version.ref = "adventure-api" }
+adventure-text-minimessage = { group = "net.kyori", name = "adventure-text-minimessage", version.ref = "adventure-text-minimessage" }
+item-nbt-api = { group = "de.tr7zw", name = "item-nbt-api", version.ref = "item-nbt-api" }
+
+# Utilities / Libraries
+sarah = { group = "fr.maxlego08.sarah", name = "sarah", version.ref = "sarah" }
+currenciesapi = { group = "fr.traqueur.currencies", name = "currenciesapi", version.ref = "currenciesapi" }
+folialib = { group = "com.tcoded", name = "FoliaLib", version.ref = "folialib" }
+xseries = { group = "com.github.cryptomorin", name = "XSeries", version.ref = "xseries" }
+exp4j = { group = "net.objecthunter", name = "exp4j", version.ref = "exp4j" }
+
+# Integration Hooks
+placeholderapi = { group = "me.clip", name = "placeholderapi", version.ref = "placeholderapi" }
+reflections = { group = "org.reflections", name = "reflections", version.ref = "reflections" }
+slimefun4 = { group = "com.github.Slimefun", name = "Slimefun4", version.ref = "slimefun4" }
+oraxen = { group = "io.th0rgal", name = "oraxen", version.ref = "oraxen" }
+packetevents = { group = "com.github.retrooper", name = "packetevents-spigot", version.ref = "packetevents" }
+nova-api = { group = "xyz.xenondevs.nova", name = "nova-api", version.ref = "nova-api" }
+nexo = { group = "com.nexomc", name = "nexo", version.ref = "nexo" }
+mythicmobs = { group = "io.lumine", name = "Mythic-Dist", version.ref = "mythicmobs" }
+mmoitems = { group = "net.Indyuce", name = "MMOItems-API", version.ref = "mmoitems" }
+luckperms = { group = "net.luckperms", name = "api", version.ref = "luckperms" }
+magiccosmetics = { group = "com.github.FrancoBM12", name = "API-MagicCosmetics", version.ref = "magiccosmetics" }
+itemsadder = { group = "com.github.LoneDev6", name = "api-itemsadder", version.ref = "itemsadder" }
+hmccosmetics = { group = "com.hibiscusmc", name = "HMCCosmetics", version.ref = "hmccosmetics" }
+headdatabase = { group = "com.arcaniax", name = "HeadDatabase-API", version.ref = "headdatabase" }
+score = { group = "maven.modrinth", name = "SCore", version.ref = "score" }
+craft-engine-core = { group = "net.momirealms", name = "craft-engine-core", version.ref = "craft-engine" }
+craft-engine-bukkit = { group = "net.momirealms", name = "craft-engine-bukkit", version.ref = "craft-engine" }
+eco = { group = "com.willfp", name = "eco", version.ref = "eco" }
+floodgate = { group = "org.geysermc.floodgate", name = "api", version.ref = "floodgate" }
+breweryx = { group = "com.dre.brewery", name = "BreweryX", version.ref = "breweryx" }
+
+# Testing
+junit-bom = { group = "org.junit", name = "junit-bom", version.ref = "junit-bom" }
+junit-jupiter = { group = "org.junit.jupiter", name = "junit-jupiter" }
+junit-platform-launcher = { group = "org.junit.platform", name = "junit-platform-launcher" }
+
+[plugins]
+# Build Tools
+shadow = { id = "com.gradleup.shadow", version.ref = "shadow" }
+groupez-repository = { id = "re.alwyn974.groupez.repository", version.ref = "groupez" }
+groupez-publish = { id = "re.alwyn974.groupez.publish", version.ref = "groupez" }
+
+# Platforms
+paperweight = { id = "io.papermc.paperweight.userdev", version.ref = "paperweight" }
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index dbc3ce4a..33e2c671 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,7 +1,7 @@
+#Tue May 26 15:14:48 CEST 2026
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.0-bin.zip
-networkTimeout=10000
-validateDistributionUrl=true
+distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.0-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
+org.gradle.caching=true
\ No newline at end of file
diff --git a/settings.gradle.kts b/settings.gradle.kts
index e286f5ea..a16f62bc 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -16,6 +16,13 @@ pluginManagement {
include("API")
include("Common")
+file("NMS").listFiles()?.forEach { file ->
+ if (file.isDirectory && !file.name.equals("build") && !file.name.startsWith(".")) {
+ println("Include NMS:${file.name}")
+ include(":NMS:${file.name}")
+ }
+}
+
file("Hooks").listFiles()?.forEach { file ->
if (file.isDirectory and !file.name.equals("build") and !file.name.startsWith(".")) {
println("Include Hooks:${file.name}")
diff --git a/src/main/java/fr/maxlego08/menu/ZButtonManager.java b/src/main/java/fr/maxlego08/menu/ZButtonManager.java
index dce43834..836d6de5 100644
--- a/src/main/java/fr/maxlego08/menu/ZButtonManager.java
+++ b/src/main/java/fr/maxlego08/menu/ZButtonManager.java
@@ -46,18 +46,41 @@ public void register(@NonNull ButtonLoader button) {
ButtonLoader existingLoader = null;
for (List buttonLoaders : this.loaders.values()) {
for (ButtonLoader loader : buttonLoaders) {
+ // Check if name matches
if (loader.getName().equalsIgnoreCase(button.getName())) {
existingLoader = loader;
break;
}
+ // Check if any alias matches
+ for (String alias : loader.getAliases()) {
+ if (alias.equalsIgnoreCase(button.getName())) {
+ existingLoader = loader;
+ break;
+ }
+ }
+ // Check if any of the new button's aliases conflict with existing loader names/aliases
+ for (String newAlias : button.getAliases()) {
+ if (loader.getName().equalsIgnoreCase(newAlias)) {
+ existingLoader = loader;
+ break;
+ }
+ for (String existingAlias : loader.getAliases()) {
+ if (existingAlias.equalsIgnoreCase(newAlias)) {
+ existingLoader = loader;
+ break;
+ }
+ }
+ }
+ if (existingLoader != null) {
+ break;
+ }
}
if (existingLoader != null) {
break;
}
}
if (existingLoader != null) {
- var loader = existingLoader;
- throw new ButtonAlreadyRegisterException("Button " + button.getName() + " was already register in the " + loader.getPlugin().getName());
+ throw new ButtonAlreadyRegisterException("Button " + button.getName() + " was already register in the " + existingLoader.getPlugin().getName());
}
Plugin plugin = button.getPlugin();
@@ -101,6 +124,11 @@ public void unregisters(@NotNull Plugin plugin) {
if (loader.getName().equalsIgnoreCase(name)) {
return Optional.of(loader);
}
+ for (String alias : loader.getAliases()) {
+ if (alias.equalsIgnoreCase(name)) {
+ return Optional.of(loader);
+ }
+ }
}
return Optional.empty();
}
@@ -185,6 +213,7 @@ public void registerAction(@NotNull ActionLoader actionLoader) {
if (action != null) {
action.setDelay(accessor.getInt("delay", 0));
action.setChance(accessor.getFloat("chance", 100));
+ action.setDebug(accessor.getBoolean("debug", false));
action.setType(type);
List> denyChanceAction = accessor.getMapList("deny-chance-actions");
if (!denyChanceAction.isEmpty()) {
diff --git a/src/main/java/fr/maxlego08/menu/ZCommand.java b/src/main/java/fr/maxlego08/menu/ZCommand.java
index 98008ab8..90257fc5 100644
--- a/src/main/java/fr/maxlego08/menu/ZCommand.java
+++ b/src/main/java/fr/maxlego08/menu/ZCommand.java
@@ -3,6 +3,7 @@
import fr.maxlego08.menu.api.command.Command;
import fr.maxlego08.menu.api.command.CommandArgument;
import fr.maxlego08.menu.api.requirement.Action;
+import fr.maxlego08.menu.api.requirement.Requirement;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
@@ -24,11 +25,11 @@
* @param file File
*/
public record ZCommand(Plugin plugin, String command, List aliases, boolean consoleCanUse, String permission, String inventory, List arguments,
- List actions, List subCommands, String denyMessage, String path, File file) implements Command {
+ List actions, List subCommands, List actions_requirements, String denyMessage, String path, File file) implements Command {
@Override
public @NotNull String toString() {
- return "ZCommand{" + "plugin=" + this.plugin + ", command='" + this.command + '\'' + ", aliases=" + this.aliases + ", permission='" + this.permission + '\'' + ", inventory='" + this.inventory + '\'' + ", arguments=" + this.arguments + ", actions=" + this.actions + ", subCommands=" + this.subCommands + ", path='" + this.path + '\'' + ", file=" + this.file + '}';
+ return "ZCommand{" + "plugin=" + this.plugin + ", command='" + this.command + '\'' + ", aliases=" + this.aliases + ", permission='" + this.permission + '\'' + ", inventory='" + this.inventory + '\'' + ", arguments=" + this.arguments + ", actions=" + this.actions + ", subCommands=" + this.subCommands + ", actions-requirements=" + this.actions_requirements + ", path='" + this.path + '\'' + ", file=" + this.file + '}';
}
@Override
diff --git a/src/main/java/fr/maxlego08/menu/ZComponentsManager.java b/src/main/java/fr/maxlego08/menu/ZComponentsManager.java
index c9ef4d04..2759a7fd 100644
--- a/src/main/java/fr/maxlego08/menu/ZComponentsManager.java
+++ b/src/main/java/fr/maxlego08/menu/ZComponentsManager.java
@@ -2,218 +2,63 @@
import fr.maxlego08.menu.api.ComponentsManager;
import fr.maxlego08.menu.api.MenuPlugin;
+import fr.maxlego08.menu.api.annotations.ComponentLoader;
import fr.maxlego08.menu.api.configuration.Configuration;
import fr.maxlego08.menu.api.exceptions.ItemComponentAlreadyRegisterException;
import fr.maxlego08.menu.api.loader.ItemComponentLoader;
-import fr.maxlego08.menu.common.factory.VariantItemComponentLoaderFactory;
-import fr.maxlego08.menu.common.utils.nms.NmsVersion;
+import fr.maxlego08.menu.api.utils.ReflectionsCache;
+import fr.maxlego08.menu.common.MinecraftVersion;
+import fr.maxlego08.menu.common.VersionFilter;
+import fr.maxlego08.menu.common.interfaces.VariantComponent;
import fr.maxlego08.menu.itemstack.components.paper.PaperVariantComponent;
import fr.maxlego08.menu.itemstack.components.spigot.SpigotVariantComponent;
-import fr.maxlego08.menu.loader.components.paper.*;
-import fr.maxlego08.menu.loader.components.spigot.*;
import fr.maxlego08.menu.zcore.logger.Logger;
import org.jetbrains.annotations.NotNull;
+import org.reflections.Reflections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
+import java.util.*;
public class ZComponentsManager implements ComponentsManager {
private final Map components = new HashMap<>();
- private boolean isPaperAndMiniMessageEnabled(MenuPlugin plugin){
- return plugin.isPaperOrFolia() && Configuration.enableMiniMessageFormat;
- }
-
@Override
public void initializeDefaultComponents(MenuPlugin plugin) {
- NmsVersion currentVersion = NmsVersion.getCurrentVersion();
- if (currentVersion.isAttributItemStack()){ // 1.20.5+
- try {
- this.initializeVariantComponents(plugin);
- } catch (Exception e) {
- if (Configuration.enableDebug) {
- Logger.info("Failed to initialize variant item components:");
- e.printStackTrace();
- }
- }
-
- this.registerComponent(new SpigotBlockStateItemComponentLoader());
- this.registerComponent(new SpigotAttributeModifiersItemComponentLoader(plugin));
- this.registerComponent(new SpigotBannerPatternsItemComponentLoader());
- this.registerComponent(new SpigotBaseColorItemComponentLoader());
- this.registerComponent(new SpigotBundleContentsItemComponentLoader(plugin));
- this.registerComponent(new SpigotChargedProjectilesItemComponentLoader(plugin));
- this.registerComponent(new SpigotContainerItemComponentLoader(plugin));
- this.registerComponent(new SpigotContainerLootItemComponentLoader());
- this.registerComponent(new SpigotCustomDataItemComponentLoader());
- this.registerComponent(plugin.isPaperOrFolia() ? new PaperCustomModelDataComponentLoader() : new SpigotCustomModelDataItemComponentLoader());
- this.registerComponent(new SpigotDamageItemComponentLoader());
- this.registerComponent(new SpigotDamageResistantItemComponentLoader());
- this.registerComponent(new SpigotDyedColorItemComponentLoader());
- this.registerComponent(new SpigotEnchantmentGlintOverrideItemComponentLoader());
- this.registerComponent(new SpigotFireworkExplosionItemComponentLoader());
- this.registerComponent(new SpigotFireworksItemComponentLoader());
- this.registerComponent(new SpigotFoodItemComponentLoader());
- this.registerComponent(new SpigotInstrumentItemComponentLoader());
- this.registerComponent(new SpigotItemNameItemComponentLoader());
- this.registerComponent(new SpigotLodestoneTrackerItemComponentLoader());
- this.registerComponent(new SpigotLoreItemComponentLoader(plugin));
- this.registerComponent(new SpigotMapColorItemComponentLoader());
- this.registerComponent(new SpigotMapIdItemComponentLoader());
- this.registerComponent(new SpigotMaxDamageItemComponentLoader());
- this.registerComponent(new SpigotMaxStackSizeItemComponentLoader());
- this.registerComponent(new SpigotOminousBottleAmplifierItemComponentLoader());
- this.registerComponent(new SpigotPotionContentsItemComponentLoader());
- this.registerComponent(new SpigotRarityItemComponentLoader());
- this.registerComponent(new SpigotRecipesItemComponentLoader());
- this.registerComponent(new SpigotRepairCostItemComponentLoader());
- this.registerComponent(new SpigotStoredEnchantItemComponentLoader());
- this.registerComponent(new SpigotSuspiciousStewEffectsItemComponentLoader());
- this.registerComponent(new SpigotToolItemComponentLoader());
- this.registerComponent(new SpigotTrimItemComponentLoader());
- this.registerComponent(new SpigotUnbreakableItemComponentLoader());
- this.registerComponent(new SpigotWritableBookContentItemComponentLoader());
- this.registerComponent(new SpigotWrittenBookContentItemComponentLoader());
- this.registerComponent(new SpigotEnchantmentsItemComponentLoader());
-
- if (this.isPaperAndMiniMessageEnabled(plugin)) {
- this.registerComponent(new PaperCustomNameItemComponentLoader(plugin));
- }
- if (plugin.isPaperOrFolia()) {
- this.registerComponent(new PaperIntangibleProjectileItemComponentLoader());
- this.registerComponent(new PaperMapDecorationsItemComponentLoader());
- this.registerComponent(new PaperNoteBlockSoundItemComponentLoader());
- this.registerComponent(new PaperPotDecorationsItemComponentLoader());
- }
-
- if (currentVersion.isNewItemStackAPI()){ // 1.21+
- this.registerComponent(new SpigotJukeboxPlayableItemComponentLoader());
-
- if (currentVersion.is1_21_2OrNewer()){ // 1.21.2+
- this.registerComponent(new SpigotConsumableItemComponentLoader());
- this.registerComponent(new SpigotEnchantableItemComponentLoader());
- this.registerComponent(new SpigotEquippableItemComponentLoader());
- this.registerComponent(new SpigotGliderItemComponentLoader());
- this.registerComponent(new SpigotItemModelItemComponentLoader());
- this.registerComponent(new SpigotTooltipStyleItemComponentLoader());
- this.registerComponent(new SpigotUseCooldownItemComponentLoader());
- this.registerComponent(new SpigotUseRemainderItemComponentLoader(plugin));
-
- if (plugin.isPaperOrFolia()){
- this.registerComponent(new PaperDeathProtectionItemComponentLoader());
- this.registerComponent(new PaperRepairableItemComponentLoader());
- }
-
- if (currentVersion.is1_21_5OrNewer()){ // 1.21.5+
- this.registerComponent(new SpigotBlocksAttacksItemComponentLoader());
- this.registerComponent(new SpigotBreakSoundItemComponentLoader());
- this.registerComponent(new SpigotPotionDurationScaleItemComponentLoader());
- this.registerComponent(plugin.isPaperOrFolia() ? new PaperTooltipDisplayItemComponentLoader() : new SpigotTooltipDisplayComponentLoader()); // Bukkit does not have support for hidden components
- this.registerComponent(new SpigotWeaponItemComponentLoader());
-
- if (this.isPaperAndMiniMessageEnabled(plugin)){
- this.registerComponent(new PaperProvidesBannerPatternsItemComponentLoader());
- this.registerComponent(new PaperProvidesTrimMaterialItemComponentLoader());
- }
-
- if (currentVersion.is1_21_9OrNewer()){ // 1.21.9+
-
- this.registerComponent(plugin.isPaperOrFolia() ? new PaperProfileComponentLoader() : new SpigotProfileItemComponentLoader());
-
- if (currentVersion.is1_21_11OrNewer()){ // 1.21.11+
- this.registerComponent(new SpigotAttackRangeItemComponentLoader());
- this.registerComponent(new SpigotDamageTypeItemComponentLoader());
- this.registerComponent(new SpigotKineticWeaponItemComponentLoader());
- this.registerComponent(new SpigotMinimumAttackChargeItemComponentLoader());
- this.registerComponent(new SpigotPiercingWeaponItemComponentLoader());
- this.registerComponent(new SpigotSwingAnimationItemComponentLoader());
- this.registerComponent(new SpigotUseEffectsItemComponentLoader());
- }
+ MinecraftVersion minecraftVersion = MinecraftVersion.getCurrentVersion();
+
+ Reflections reflection = ReflectionsCache.getInstance().getOrCreate((ZMenuPlugin) plugin, "fr.maxlego08.menu");
+ VariantComponent variantComponent = plugin.isPaperOrFolia() ? new PaperVariantComponent() : new SpigotVariantComponent();
+
+ int count = 0;
+ Set> typesAnnotatedWith = reflection.getTypesAnnotatedWith(ComponentLoader.class);
+ for (Class> clazz : typesAnnotatedWith) {
+ if (ItemComponentLoader.class.isAssignableFrom(clazz)) {
+ if (!VersionFilter.passes(clazz)) continue;
+
+ try {
+ ItemComponentLoader loader;
+ try {
+ loader = (ItemComponentLoader) clazz.getDeclaredConstructor(MenuPlugin.class, VariantComponent.class).newInstance(plugin, variantComponent);
+ } catch (NoSuchMethodException e1) {
+ try {
+ loader = (ItemComponentLoader) clazz.getDeclaredConstructor().newInstance();
+ } catch (NoSuchMethodException e2) {
+ loader = (ItemComponentLoader) clazz.getDeclaredConstructor(MenuPlugin.class).newInstance(plugin);
}
-
+ }
+ this.registerComponent(loader);
+ count++;
+ } catch (Exception e) {
+ if (Configuration.enableDebug) {
+ Logger.info("Failed to instantiate component loader: " + clazz.getName());
+ e.printStackTrace();
}
}
}
}
- }
-
- private void initializeVariantComponents(MenuPlugin plugin) {
- NmsVersion currentVersion = NmsVersion.getCurrentVersion();
- VariantItemComponentLoaderFactory loaderFactory =
- plugin.isPaperOrFolia() ? new PaperVariantItemComponentLoader(new PaperVariantComponent())
- : new SpigotVariantItemComponentLoader(new SpigotVariantComponent());
-
- this.registerComponent(loaderFactory.getLoaderCatCollar());
- this.registerComponent(loaderFactory.getLoaderCatVariant());
- this.registerComponent(loaderFactory.getLoaderHorse());
- this.registerComponent(loaderFactory.getLoaderRabbit());
- this.registerComponent(loaderFactory.getLoaderSheep());
- this.registerComponent(loaderFactory.getLoaderTropicalFishBaseColor());
- this.registerComponent(loaderFactory.getLoaderTropicalFishPatternColor());
- this.registerComponent(loaderFactory.getLoaderVillager());
-
- if (currentVersion.isNewMaterial()){ // 1.13+
- this.registerComponent(loaderFactory.getLoaderFox());
- this.registerComponent(loaderFactory.getLoaderMushroomCow());
- }
- if (currentVersion.isNewNMSVersion()){ // 1.17+
- this.registerComponent(loaderFactory.getLoaderAxolotl());
- }
- if (currentVersion.isAttributItemStack()){ // 1.20.5+
- this.registerComponent(loaderFactory.getLoaderWolfCollar());
- this.registerComponent(loaderFactory.getLoaderWolfVariant());
- this.registerComponent(loaderFactory.getLoaderPainting());
- }
- if (currentVersion.is1_21_5OrNewer()){ // 1.21.5+
- try {
- this.registerComponent(loaderFactory.getLoaderChicken());
- } catch (Exception e) {
- if (Configuration.enableDebug){
- Logger.info("Failed to register Chicken variant component:");
- e.printStackTrace();
- }
- }
- try {
- this.registerComponent(loaderFactory.getLoaderCow());
- } catch (Exception e) {
- if (Configuration.enableDebug){
- Logger.info("Failed to register Cow variant component:");
- e.printStackTrace();
- }
- }
- try {
- this.registerComponent(loaderFactory.getLoaderPig());
- } catch (Exception e) {
- if (Configuration.enableDebug){
- Logger.info("Failed to register Pig variant component:");
- e.printStackTrace();
- }
- }
- try {
- this.registerComponent(loaderFactory.getLoaderSalmon());
- } catch (Exception e) {
- if (Configuration.enableDebug){
- Logger.info("Failed to register Salmon variant component:");
- e.printStackTrace();
- }
- }
- }
- if (currentVersion.isNewNBTVersion()) { // 1.18+
- this.registerComponent(loaderFactory.getLoaderFrog());
- }
- if (currentVersion.is1_11OrNewer()){ // 1.11+
- this.registerComponent(loaderFactory.getLoaderLlama());
- this.registerComponent(loaderFactory.getLoaderShulkerBox());
- }
- if (currentVersion.is1_12OrNewer()) { // 1.12+
- this.registerComponent(loaderFactory.getLoaderParrot());
- }
+ Logger.info("Registered " + count + " default component loaders for Minecraft version " + minecraftVersion + ".");
}
-
@Override
public void registerComponent(@NotNull ItemComponentLoader loader) throws ItemComponentAlreadyRegisterException {
List componentNames = loader.getComponentNames();
diff --git a/src/main/java/fr/maxlego08/menu/ZInventoryManager.java b/src/main/java/fr/maxlego08/menu/ZInventoryManager.java
index 2bcc4596..43efbecb 100644
--- a/src/main/java/fr/maxlego08/menu/ZInventoryManager.java
+++ b/src/main/java/fr/maxlego08/menu/ZInventoryManager.java
@@ -34,6 +34,7 @@
import fr.maxlego08.menu.hooks.dialogs.button.loader.*;
import fr.maxlego08.menu.hooks.packetevents.loader.PacketEventChangeTitleNameLoader;
import fr.maxlego08.menu.inventory.inventories.InventoryDefault;
+import fr.maxlego08.menu.inventory.zinv.ZInventory;
import fr.maxlego08.menu.itemstack.*;
import fr.maxlego08.menu.loader.InventoryLoader;
import fr.maxlego08.menu.loader.MenuItemStackLoader;
@@ -133,9 +134,14 @@ public MenuItemStack loadItemStack(YamlConfiguration configuration, String path,
@Override
public MenuItemStack loadItemStack(File file, String path, Map map) {
+ return this.loadItemStack(file, map);
+ }
+
+ @Override
+ public MenuItemStack loadItemStack(File file, Map map) {
YamlConfiguration configuration = new YamlConfiguration();
- configuration.set("item", map);
- return new MenuItemStackLoader(this).load(configuration, "item", file);
+ configuration.createSection("item", map);
+ return new MenuItemStackLoader(this).load(configuration, "item.", file);
}
@Override
@@ -195,7 +201,7 @@ public Inventory loadInventory(Plugin plugin, File file, Class extends Invento
Logger.info("Cannot load inventory " + file.getPath() + ", inventory is waiting.", LogType.WARNING);
InventoryLoadRequirement inventoryLoadRequirement = optional.get();
- plugin.getLogger().info("Inventory load requirement: " + inventoryLoadRequirement.getDisplayError());
+ Logger.info("Inventory load requirement: " + inventoryLoadRequirement.getDisplayError(), LogType.WARNING);
}
this.inventoryLoadRequirements.add(optional.get());
@@ -367,6 +373,7 @@ public void loadButtons() {
buttonManager.registerPermissible(new PlayerNamePermissibleLoader(buttonManager));
buttonManager.registerPermissible(new CurrencyPermissibleLoader(buttonManager));
buttonManager.registerPermissible(new CuboidPermissibleLoader(buttonManager));
+ buttonManager.registerPermissible(new CheckInventoryLoader(this.plugin));
if (this.plugin.isEnable(Plugins.JOBS)) {
buttonManager.registerPermissible(new JobPermissibleLoader(buttonManager));
}
@@ -397,13 +404,17 @@ public void loadButtons() {
buttonManager.registerAction(new ActionBarLoader());
buttonManager.registerAction(new RefreshLoader());
buttonManager.registerAction(new RefreshInventoryLoader());
+ buttonManager.registerAction(new ResetPaginationLoader(this.paginationManager));
buttonManager.registerAction(new DiscordLoader());
buttonManager.registerAction(new DiscordComponentV2Loader());
buttonManager.registerAction(new TeleportLoader(this.plugin));
buttonManager.registerAction(new CurrencyWithdrawLoader());
buttonManager.registerAction(new CurrencyDepositLoader());
+ buttonManager.registerAction(new TakeItemLoader(this.plugin));
buttonManager.registerAction(new ItemEditLoader(this.plugin));
buttonManager.registerAction(new ItemGiveLoader(this.plugin));
+ buttonManager.registerAction(new SetItemActionLoader(this.plugin));
+ buttonManager.registerAction(new RefreshSlotActionLoader());
if (this.plugin.isEnable(Plugins.LUCKPERMS)) {
buttonManager.registerAction(new LuckPermissionSetLoader());
}
diff --git a/src/main/java/fr/maxlego08/menu/ZMenuPlugin.java b/src/main/java/fr/maxlego08/menu/ZMenuPlugin.java
index e8516c43..98a2d2a0 100644
--- a/src/main/java/fr/maxlego08/menu/ZMenuPlugin.java
+++ b/src/main/java/fr/maxlego08/menu/ZMenuPlugin.java
@@ -3,6 +3,7 @@
import com.tcoded.folialib.FoliaLib;
import com.tcoded.folialib.impl.PlatformScheduler;
import fr.maxlego08.menu.api.*;
+import fr.maxlego08.menu.api.annotations.AutoListener;
import fr.maxlego08.menu.api.attribute.ApplySpigotAttribute;
import fr.maxlego08.menu.api.attribute.AttributApplier;
import fr.maxlego08.menu.api.command.CommandManager;
@@ -20,13 +21,16 @@
import fr.maxlego08.menu.api.storage.StorageManager;
import fr.maxlego08.menu.api.utils.EnumInventory;
import fr.maxlego08.menu.api.utils.MetaUpdater;
+import fr.maxlego08.menu.api.utils.ReflectionsCache;
import fr.maxlego08.menu.api.utils.toast.ToastHelper;
import fr.maxlego08.menu.api.website.WebsiteManager;
import fr.maxlego08.menu.command.VCommandManager;
import fr.maxlego08.menu.command.commands.CommandMenu;
+import fr.maxlego08.menu.common.MinecraftVersion;
+import fr.maxlego08.menu.common.VersionFilter;
+import fr.maxlego08.menu.common.network.NMSMenuPacketListener;
import fr.maxlego08.menu.common.utils.cache.YamlFileCache;
import fr.maxlego08.menu.common.utils.nms.NMSUtils;
-import fr.maxlego08.menu.common.utils.nms.NmsVersion;
import fr.maxlego08.menu.config.ConfigManager;
import fr.maxlego08.menu.dupe.DupeListener;
import fr.maxlego08.menu.dupe.NMSDupeManager;
@@ -49,10 +53,9 @@
import fr.maxlego08.menu.hooks.packetevents.PacketUtils;
import fr.maxlego08.menu.hooks.packetevents.loader.PacketEventTitleAnimationLoader;
import fr.maxlego08.menu.inventory.VInventoryManager;
+import fr.maxlego08.menu.inventory.inventories.AnvilInventoryDefault;
import fr.maxlego08.menu.inventory.inventories.InventoryDefault;
-import fr.maxlego08.menu.listener.AdapterListener;
import fr.maxlego08.menu.listener.ItemUpdaterListener;
-import fr.maxlego08.menu.listener.SwapKeyListener;
import fr.maxlego08.menu.loader.materials.ArmorLoader;
import fr.maxlego08.menu.loader.materials.Base64Loader;
import fr.maxlego08.menu.pattern.ZPatternManager;
@@ -60,11 +63,14 @@
import fr.maxlego08.menu.placeholder.MenuPlaceholders;
import fr.maxlego08.menu.players.ZDataManager;
import fr.maxlego08.menu.players.inventory.ZInventoriesPlayer;
+import fr.maxlego08.menu.registry.ZRuleLoaderRegistry;
import fr.maxlego08.menu.save.MessageLoader;
import fr.maxlego08.menu.storage.ZStorageManager;
import fr.maxlego08.menu.website.Token;
import fr.maxlego08.menu.website.ZWebsiteManager;
import fr.maxlego08.menu.zcore.ZPlugin;
+import fr.maxlego08.menu.zcore.logger.BukkitLogger;
+import fr.maxlego08.menu.zcore.logger.ComponentLogger;
import fr.maxlego08.menu.zcore.logger.Logger;
import fr.maxlego08.menu.zcore.utils.meta.ClassicMeta;
import fr.maxlego08.menu.zcore.utils.plugins.Metrics;
@@ -75,9 +81,12 @@
import org.bukkit.OfflinePlayer;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
+import org.bukkit.event.Listener;
+import org.bukkit.event.inventory.InventoryType;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.ServicePriority;
import org.bukkit.plugin.ServicesManager;
+import org.reflections.Reflections;
import java.io.File;
import java.util.*;
@@ -118,12 +127,16 @@ public class ZMenuPlugin extends ZPlugin implements MenuPlugin {
private DialogManager dialogManager;
private BedrockManager bedrockManager;
private CommandMenu commandMenu;
- private PlatformScheduler scheduler;
+ private final PlatformScheduler scheduler = this.foliaLib.getScheduler();
private DupeManager dupeManager;
private FontImage fontImage = new EmptyFont();
private MetaUpdater metaUpdater = new ClassicMeta();
private PacketManager packetManager;
+ public ZMenuPlugin() {
+ new BukkitLogger(this.getDescription().getFullName());
+ }
+
public static ZMenuPlugin getInstance() {
return instance;
}
@@ -141,6 +154,8 @@ public void onLoad() {
@Override
public void onEnable() {
+ NMSMenuPacketListener.init(this);
+
instance = this;
this.saveDefaultConfig();
@@ -150,9 +165,7 @@ public void onEnable() {
this.packetManager.onEnable();
}
- this.scheduler = this.foliaLib.getScheduler();
-
- this.dupeManager = NmsVersion.nmsVersion.isPdcVersion() ? new PDCDupeManager(this) : new NMSDupeManager();
+ this.dupeManager = MinecraftVersion.getCurrentVersion().isAtLeast(MinecraftVersion.parse("1.14")) ? new PDCDupeManager(this) : new NMSDupeManager();
this.enchantments.register();
this.preEnable();
@@ -163,6 +176,7 @@ public void onEnable() {
this.loadMeta();
+ ZRuleLoaderRegistry.getInstance().registerDefaultLoaders(this);
this.componentsManager.initializeDefaultComponents(this);
List files = this.getInventoriesFiles();
@@ -195,7 +209,7 @@ public void onEnable() {
servicesManager.register(Enchantments.class, this.enchantments, this, ServicePriority.Highest);
servicesManager.register(TitleAnimationManager.class, this.titleAnimationManager, this, ServicePriority.Highest);
- if (this.isPaperOrFolia() && NmsVersion.getCurrentVersion().isDialogsVersion()) {
+ if (this.isPaperOrFolia() && MinecraftVersion.getCurrentVersion().isAtLeast(MinecraftVersion.parse("1.21.7"))) {
if (Configuration.enableMiniMessageFormat) {
Logger.info("Paper server detected, loading Dialogs support");
ConfigManager configManager = new ConfigManager(this);
@@ -216,11 +230,11 @@ public void onEnable() {
}
this.registerInventory(EnumInventory.INVENTORY_DEFAULT, new InventoryDefault());
+ this.vinventoryManager.registerInventory(EnumInventory.INVENTORY_DEFAULT.getId(), InventoryType.ANVIL, new AnvilInventoryDefault());
this.registerCommand("zmenu", this.commandMenu = new CommandMenu(this), "zm");
/* Add Listener */
- this.addListener(new SwapKeyListener());
- this.addListener(new AdapterListener(this));
+ this.registerAutoListeners();
this.addListener(this.vinventoryManager);
this.addListener(this.inventoriesPlayer);
this.addListener(new ItemUpdaterListener(this.itemManager));
@@ -277,11 +291,40 @@ public void onEnable() {
// this.inventoryManager.registerInventoryListener(this.packetUtils);
if (this.isActive(Plugins.PACKETEVENTS))
- this.inventoryManager.registerInventoryListener(new PacketEventPlayerInventoryManager());
+ this.inventoryManager.registerInventoryListener(new PacketEventPlayerInventoryManager(this));
this.postEnable();
}
+ private void registerAutoListeners() {
+ Reflections reflection = ReflectionsCache.getInstance().getOrCreate(this, "fr.maxlego08.menu");
+
+ Set> candidates = reflection.getTypesAnnotatedWith(AutoListener.class);
+
+ int count = 0;
+ for (Class> clazz : candidates) {
+ if (!Listener.class.isAssignableFrom(clazz)) continue;
+ if (!VersionFilter.passes(clazz)) continue;
+ try {
+ Listener listener;
+ try {
+ listener = (Listener) clazz.getDeclaredConstructor(MenuPlugin.class).newInstance(this);
+ } catch (NoSuchMethodException e) {
+ listener = (Listener) clazz.getDeclaredConstructor().newInstance();
+ }
+ this.addListener(listener);
+ count++;
+ } catch (Exception e) {
+ if (Configuration.enableDebug) {
+ Logger.info("Failed to instantiate auto listener: " + clazz.getName());
+ e.printStackTrace();
+ }
+ }
+ }
+
+ Logger.info("Registered " + count + " auto listener(s).");
+ }
+
/**
* Registers all the hooks for the plugins that are present.
* This method is called at the end of {@link #onEnable()} and it will
@@ -292,59 +335,93 @@ private void registerHooks() {
if (this.isActive(Plugins.HEADDATABASE)) {
this.inventoryManager.registerMaterialLoader(new HeadDatabaseLoader());
+ Logger.info("Registered HeadDatabase material loader");
}
+
if (this.isActive(Plugins.ZHEAD)) {
this.inventoryManager.registerMaterialLoader(new ZHeadLoader(this));
+ Logger.info("Registered ZHead material loader");
}
+
if (this.isActive(Plugins.ORAXEN)) {
this.inventoryManager.registerMaterialLoader(new OraxenLoader());
+ this.fontImage = new OraxenFont();
+ Logger.info("Registered Oraxen material loader and font");
}
+
if (this.isActive(Plugins.CRAFTENGINE)) {
this.inventoryManager.registerMaterialLoader(new CraftEngineLoader());
+ Logger.info("Registered CraftEngine material loader");
}
+
if (this.isActive(Plugins.NEXO)) {
this.inventoryManager.registerMaterialLoader(new NexoLoader());
+ Logger.info("Registered Nexo material loader");
}
- if (this.isEnable(Plugins.MAGICCOSMETICS)) {
+
+ if (this.isActive(Plugins.MAGICCOSMETICS)) {
this.inventoryManager.registerMaterialLoader(new MagicCosmeticsLoader());
+ Logger.info("Registered MagicCosmetics material loader");
}
- if (this.isEnable(Plugins.HMCCOSMETICS)) {
+
+ if (this.isActive(Plugins.HMCCOSMETICS)) {
this.inventoryManager.registerMaterialLoader(new HmccosmeticsLoader());
+ Logger.info("Registered HMC Cosmetics material loader");
}
- if (this.isEnable(Plugins.ITEMSADDER)) {
+
+ if (this.isActive(Plugins.ITEMSADDER)) {
this.inventoryManager.registerMaterialLoader(new ItemsAdderLoader(this));
this.fontImage = new ItemsAdderFont();
+ Logger.info("Registered ItemsAdder material loader and font");
}
+
if (this.isActive(Plugins.SLIMEFUN)) {
this.inventoryManager.registerMaterialLoader(new SlimeFunLoader());
+ Logger.info("Registered SlimeFun material loader");
}
+
if (this.isActive(Plugins.NOVA)) {
this.inventoryManager.registerMaterialLoader(new NovaLoader());
+ Logger.info("Registered Nova material loader");
}
+
if (this.isActive(Plugins.ECO)) {
this.inventoryManager.registerMaterialLoader(new EcoLoader());
+ Logger.info("Registered Eco material loader");
}
+
if (this.isActive(Plugins.ZITEMS)) {
this.inventoryManager.registerMaterialLoader(new ZItemsLoader(this));
+ Logger.info("Registered zItems material loader");
}
+
if (this.isActive(Plugins.EXECUTABLE_ITEMS)) {
this.inventoryManager.registerMaterialLoader(new ExecutableItemsLoader());
+ Logger.info("Registered ExecutableItems material loader");
}
+
if (this.isActive(Plugins.EXECUTABLE_BLOCKS)) {
this.inventoryManager.registerMaterialLoader(new ExecutableBlocksLoader());
+ Logger.info("Registered ExecutableBlocks material loader");
}
+
if (this.isActive(Plugins.NEXTGENS)) {
this.inventoryManager.registerMaterialLoader(new NextGensGeneratorLoader());
+ Logger.info("Registered NextGens material loader");
}
+
if (this.isActive(Plugins.MYTHICMOBS)) {
this.inventoryManager.registerMaterialLoader(new MythicMobsItemsLoader());
this.addListener(new MythicManager(this));
+ Logger.info("Registered MythicMobs material loader and listener");
}
if (this.isActive(Plugins.BREWERYX)) {
this.inventoryManager.registerMaterialLoader(new BreweryXLoader());
+ Logger.info("Registered BreweryX material loader");
}
if (this.isActive(Plugins.MMOITEMS)) {
this.inventoryManager.registerMaterialLoader(new MMOItemsLoader());
+ Logger.info("Registered MMOItems material loader");
}
if (this.isActive(Plugins.PACKETEVENTS)) {
this.titleAnimationManager.registerLoader("packet-events", new PacketEventTitleAnimationLoader());
@@ -372,7 +449,7 @@ private List