) 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 000000000..35ff8127d
--- /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 ce9596bff..7081e7401 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 6ac42804b..329581ace 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 5edc1a389..d2739d160 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 c6e796eb8..3cf202e59 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 cdd70f663..be1e9cfc0 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 000000000..fd43d903b
--- /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 df76458f0..90642df9b 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 9d27dc7e0..aadb88d61 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 d83dc1fff..174902cbd 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 000000000..45466b883
--- /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 6e60d2123..0d05108de 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 000000000..6f19ea79b
--- /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 000000000..54dd236ba
--- /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 000000000..1dd0ce633
--- /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 000000000..a199a75e6
--- /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 000000000..dc669b4bc
--- /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 b23494740..0150c1b47 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 00f753423..4a469a33a 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 0443b04c8..bd1cc7cdf 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 c6c61cfff..000000000
--- 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 000000000..0d49c8cef
--- /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 000000000..5714771fc
--- /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 000000000..9fdef0f31
--- /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 000000000..2016af751
--- /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 1540df234..8aad0a484 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 ef5e1002c..87ee568d1 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 e71833b06..d2ceb18dc 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 af4c00139..f2f4f5e59 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 98f968b57..bbf2e893e 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 e29bce7e3..15f811ae3 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 fe85d461b..6e70e0e77 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/CraftEngine/src/main/java/fr/maxlego08/menu/hooks/rules/CraftEngineRule.java b/Hooks/CraftEngine/src/main/java/fr/maxlego08/menu/hooks/rules/CraftEngineRule.java
new file mode 100644
index 000000000..c69e403e8
--- /dev/null
+++ b/Hooks/CraftEngine/src/main/java/fr/maxlego08/menu/hooks/rules/CraftEngineRule.java
@@ -0,0 +1,26 @@
+package fr.maxlego08.menu.hooks.rules;
+
+import fr.maxlego08.menu.api.rules.AbstractPluginItemRule;
+import net.momirealms.craftengine.bukkit.api.CraftEngineItems;
+import net.momirealms.craftengine.bukkit.item.BukkitItemDefinition;
+import org.bukkit.inventory.ItemStack;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+public class CraftEngineRule extends AbstractPluginItemRule {
+
+ public CraftEngineRule(@NotNull List itemIds, boolean ignoreCase) {
+ super(itemIds, ignoreCase);
+ }
+
+ @Override
+ protected @Nullable String resolveId(@NotNull ItemStack itemStack) {
+ BukkitItemDefinition bukkitItemDefinition = CraftEngineItems.byItemStack(itemStack);
+ if (bukkitItemDefinition != null) {
+ return bukkitItemDefinition.id().asString();
+ }
+ return null;
+ }
+}
diff --git a/Hooks/CraftEngine/src/main/java/fr/maxlego08/menu/hooks/rules/CraftEngineRuleLoader.java b/Hooks/CraftEngine/src/main/java/fr/maxlego08/menu/hooks/rules/CraftEngineRuleLoader.java
new file mode 100644
index 000000000..85c64d2d7
--- /dev/null
+++ b/Hooks/CraftEngine/src/main/java/fr/maxlego08/menu/hooks/rules/CraftEngineRuleLoader.java
@@ -0,0 +1,29 @@
+package fr.maxlego08.menu.hooks.rules;
+
+import fr.maxlego08.menu.api.annotations.AutoRuleLoader;
+import fr.maxlego08.menu.api.configuration.annotation.RequiresPlugin;
+import fr.maxlego08.menu.api.rules.Rule;
+import fr.maxlego08.menu.api.rules.loader.AbstractPluginRuleLoader;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+@AutoRuleLoader
+@RequiresPlugin("CraftEngine")
+public class CraftEngineRuleLoader extends AbstractPluginRuleLoader {
+ @Override
+ protected @NotNull Rule createRule(@NotNull List items, boolean ignoreCase) {
+ return new CraftEngineRule(items, ignoreCase);
+ }
+
+ @Override
+ @NotNull
+ public List<@NotNull String> getAliases() {
+ return List.of("craft-engine", "craft_engine", "ce");
+ }
+
+ @Override
+ public @NotNull String getType() {
+ return "craftengine";
+ }
+}
diff --git a/Hooks/Denizen/build.gradle.kts b/Hooks/Denizen/build.gradle.kts
new file mode 100644
index 000000000..c15911cad
--- /dev/null
+++ b/Hooks/Denizen/build.gradle.kts
@@ -0,0 +1,13 @@
+group = "Hooks:Eco"
+
+repositories {
+ maven {
+ name = "citizensnpcs"
+ url = uri("https://maven.citizensnpcs.co/repo")
+ }
+}
+
+dependencies {
+ compileOnly(projects.common)
+ compileOnly(libs.denizen)
+}
\ No newline at end of file
diff --git a/Hooks/Denizen/src/main/java/fr/maxlego08/menu/hooks/denizen/rules/DenizenRule.java b/Hooks/Denizen/src/main/java/fr/maxlego08/menu/hooks/denizen/rules/DenizenRule.java
new file mode 100644
index 000000000..65c4a29c4
--- /dev/null
+++ b/Hooks/Denizen/src/main/java/fr/maxlego08/menu/hooks/denizen/rules/DenizenRule.java
@@ -0,0 +1,21 @@
+package fr.maxlego08.menu.hooks.denizen.rules;
+
+import com.denizenscript.denizen.objects.ItemTag;
+import fr.maxlego08.menu.api.rules.AbstractPluginItemRule;
+import org.bukkit.inventory.ItemStack;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+public class DenizenRule extends AbstractPluginItemRule {
+
+ public DenizenRule(@NotNull List itemIds, boolean ignoreCase) {
+ super(itemIds, ignoreCase);
+ }
+
+ @Override
+ protected @Nullable String resolveId(@NotNull ItemStack itemStack) {
+ return new ItemTag(itemStack).getScriptName();
+ }
+}
diff --git a/Hooks/Denizen/src/main/java/fr/maxlego08/menu/hooks/denizen/rules/DenizenRuleLoader.java b/Hooks/Denizen/src/main/java/fr/maxlego08/menu/hooks/denizen/rules/DenizenRuleLoader.java
new file mode 100644
index 000000000..dd928b390
--- /dev/null
+++ b/Hooks/Denizen/src/main/java/fr/maxlego08/menu/hooks/denizen/rules/DenizenRuleLoader.java
@@ -0,0 +1,23 @@
+package fr.maxlego08.menu.hooks.denizen.rules;
+
+import fr.maxlego08.menu.api.annotations.AutoRuleLoader;
+import fr.maxlego08.menu.api.configuration.annotation.RequiresPlugin;
+import fr.maxlego08.menu.api.rules.Rule;
+import fr.maxlego08.menu.api.rules.loader.AbstractPluginRuleLoader;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+@AutoRuleLoader
+@RequiresPlugin("Denizen")
+public class DenizenRuleLoader extends AbstractPluginRuleLoader {
+ @Override
+ protected @NotNull Rule createRule(@NotNull List items, boolean ignoreCase) {
+ return new DenizenRule(items, ignoreCase);
+ }
+
+ @Override
+ public @NotNull String getType() {
+ return "denizen";
+ }
+}
diff --git a/Hooks/Eco/build.gradle.kts b/Hooks/Eco/build.gradle.kts
index ce261eb67..155af9822 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/Eco/src/main/java/fr/maxlego08/menu/hooks/rules/EcoRule.java b/Hooks/Eco/src/main/java/fr/maxlego08/menu/hooks/rules/EcoRule.java
new file mode 100644
index 000000000..10096a08c
--- /dev/null
+++ b/Hooks/Eco/src/main/java/fr/maxlego08/menu/hooks/rules/EcoRule.java
@@ -0,0 +1,26 @@
+package fr.maxlego08.menu.hooks.rules;
+
+import com.willfp.eco.core.items.CustomItem;
+import com.willfp.eco.core.items.Items;
+import fr.maxlego08.menu.api.rules.AbstractPluginItemRule;
+import org.bukkit.inventory.ItemStack;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+public class EcoRule extends AbstractPluginItemRule {
+
+ public EcoRule(@NotNull List itemIds, boolean ignoreCase) {
+ super(itemIds, ignoreCase);
+ }
+
+ @Override
+ protected @Nullable String resolveId(@NotNull ItemStack itemStack) {
+ CustomItem customItem = Items.getCustomItem(itemStack);
+ if (customItem != null) {
+ return customItem.getKey().toString();
+ }
+ return null;
+ }
+}
diff --git a/Hooks/Eco/src/main/java/fr/maxlego08/menu/hooks/rules/EcoRuleLoader.java b/Hooks/Eco/src/main/java/fr/maxlego08/menu/hooks/rules/EcoRuleLoader.java
new file mode 100644
index 000000000..b13e257de
--- /dev/null
+++ b/Hooks/Eco/src/main/java/fr/maxlego08/menu/hooks/rules/EcoRuleLoader.java
@@ -0,0 +1,23 @@
+package fr.maxlego08.menu.hooks.rules;
+
+import fr.maxlego08.menu.api.annotations.AutoRuleLoader;
+import fr.maxlego08.menu.api.configuration.annotation.RequiresPlugin;
+import fr.maxlego08.menu.api.rules.Rule;
+import fr.maxlego08.menu.api.rules.loader.AbstractPluginRuleLoader;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+@AutoRuleLoader
+@RequiresPlugin("eco")
+public class EcoRuleLoader extends AbstractPluginRuleLoader {
+ @Override
+ protected @NotNull Rule createRule(@NotNull List items, boolean ignoreCase) {
+ return new EcoRule(items, ignoreCase);
+ }
+
+ @Override
+ public @NotNull String getType() {
+ return "eco";
+ }
+}
diff --git a/Hooks/ExecutableBlocks/build.gradle.kts b/Hooks/ExecutableBlocks/build.gradle.kts
index 463dc1c2b..2347a6ceb 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/ExecutableBlocks/src/main/java/fr/maxlego08/menu/hooks/executableblocks/rules/ExecutableBlocksRule.java b/Hooks/ExecutableBlocks/src/main/java/fr/maxlego08/menu/hooks/executableblocks/rules/ExecutableBlocksRule.java
new file mode 100644
index 000000000..a493ee1a6
--- /dev/null
+++ b/Hooks/ExecutableBlocks/src/main/java/fr/maxlego08/menu/hooks/executableblocks/rules/ExecutableBlocksRule.java
@@ -0,0 +1,24 @@
+package fr.maxlego08.menu.hooks.executableblocks.rules;
+
+import com.ssomar.score.api.executableblocks.ExecutableBlocksAPI;
+import com.ssomar.score.api.executableblocks.config.ExecutableBlockInterface;
+import fr.maxlego08.menu.api.rules.AbstractPluginItemRule;
+import org.bukkit.inventory.ItemStack;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+import java.util.Optional;
+
+public class ExecutableBlocksRule extends AbstractPluginItemRule {
+
+ public ExecutableBlocksRule(@NotNull List itemIds, boolean ignoreCase) {
+ super(itemIds, ignoreCase);
+ }
+
+ @Override
+ protected @Nullable String resolveId(@NotNull ItemStack itemStack) {
+ Optional executableBlock = ExecutableBlocksAPI.getExecutableBlocksManager().getExecutableBlock(itemStack);
+ return executableBlock.map(ExecutableBlockInterface::getId).orElse(null);
+ }
+}
diff --git a/Hooks/ExecutableBlocks/src/main/java/fr/maxlego08/menu/hooks/executableblocks/rules/ExecutableBlocksRuleLoader.java b/Hooks/ExecutableBlocks/src/main/java/fr/maxlego08/menu/hooks/executableblocks/rules/ExecutableBlocksRuleLoader.java
new file mode 100644
index 000000000..ce80cd3fc
--- /dev/null
+++ b/Hooks/ExecutableBlocks/src/main/java/fr/maxlego08/menu/hooks/executableblocks/rules/ExecutableBlocksRuleLoader.java
@@ -0,0 +1,29 @@
+package fr.maxlego08.menu.hooks.executableblocks.rules;
+
+import fr.maxlego08.menu.api.annotations.AutoRuleLoader;
+import fr.maxlego08.menu.api.configuration.annotation.RequiresPlugin;
+import fr.maxlego08.menu.api.rules.Rule;
+import fr.maxlego08.menu.api.rules.loader.AbstractPluginRuleLoader;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NonNull;
+
+import java.util.List;
+
+@AutoRuleLoader
+@RequiresPlugin("ExecutableBlocks")
+public class ExecutableBlocksRuleLoader extends AbstractPluginRuleLoader {
+ @Override
+ protected @NotNull Rule createRule(@NotNull List items, boolean ignoreCase) {
+ return new ExecutableBlocksRule(items, ignoreCase);
+ }
+
+ @Override
+ public @NonNull List getAliases() {
+ return List.of("executable-blocks", "executable_blocks", "eb");
+ }
+
+ @Override
+ public @NotNull String getType() {
+ return "executableblocks";
+ }
+}
diff --git a/Hooks/ExecutableItems/build.gradle.kts b/Hooks/ExecutableItems/build.gradle.kts
index 9ce1a81ca..8f0ded405 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/ExecutableItems/src/main/java/fr/maxlego08/menu/hooks/executableitems/rules/ExecutableItemsRule.java b/Hooks/ExecutableItems/src/main/java/fr/maxlego08/menu/hooks/executableitems/rules/ExecutableItemsRule.java
new file mode 100644
index 000000000..d4363b7c5
--- /dev/null
+++ b/Hooks/ExecutableItems/src/main/java/fr/maxlego08/menu/hooks/executableitems/rules/ExecutableItemsRule.java
@@ -0,0 +1,24 @@
+package fr.maxlego08.menu.hooks.executableitems.rules;
+
+import com.ssomar.score.api.executableitems.ExecutableItemsAPI;
+import com.ssomar.score.api.executableitems.config.ExecutableItemInterface;
+import fr.maxlego08.menu.api.rules.AbstractPluginItemRule;
+import org.bukkit.inventory.ItemStack;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+import java.util.Optional;
+
+public class ExecutableItemsRule extends AbstractPluginItemRule {
+
+ protected ExecutableItemsRule(@NotNull List itemIds, boolean ignoreCase) {
+ super(itemIds, ignoreCase);
+ }
+
+ @Override
+ protected @Nullable String resolveId(@NotNull ItemStack itemStack) {
+ Optional executableItem = ExecutableItemsAPI.getExecutableItemsManager().getExecutableItem(itemStack);
+ return executableItem.map(ExecutableItemInterface::getId).orElse(null);
+ }
+}
diff --git a/Hooks/ExecutableItems/src/main/java/fr/maxlego08/menu/hooks/executableitems/rules/ExecutableItemsRuleLoader.java b/Hooks/ExecutableItems/src/main/java/fr/maxlego08/menu/hooks/executableitems/rules/ExecutableItemsRuleLoader.java
new file mode 100644
index 000000000..0f0a1015c
--- /dev/null
+++ b/Hooks/ExecutableItems/src/main/java/fr/maxlego08/menu/hooks/executableitems/rules/ExecutableItemsRuleLoader.java
@@ -0,0 +1,29 @@
+package fr.maxlego08.menu.hooks.executableitems.rules;
+
+import fr.maxlego08.menu.api.annotations.AutoRuleLoader;
+import fr.maxlego08.menu.api.configuration.annotation.RequiresPlugin;
+import fr.maxlego08.menu.api.rules.Rule;
+import fr.maxlego08.menu.api.rules.loader.AbstractPluginRuleLoader;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NonNull;
+
+import java.util.List;
+
+@AutoRuleLoader
+@RequiresPlugin("ExecutableItems")
+public class ExecutableItemsRuleLoader extends AbstractPluginRuleLoader {
+ @Override
+ protected @NotNull Rule createRule(@NotNull List items, boolean ignoreCase) {
+ return new ExecutableItemsRule(items, ignoreCase);
+ }
+
+ @Override
+ public @NonNull List getAliases() {
+ return List.of("executable-items", "executable_items", "ei");
+ }
+
+ @Override
+ public @NotNull String getType() {
+ return "executableitems";
+ }
+}
diff --git a/Hooks/HeadDataBase/build.gradle.kts b/Hooks/HeadDataBase/build.gradle.kts
index a2fef0d5d..1337c49d4 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/HeadDataBase/src/main/java/fr/maxlego08/menu/hooks/headdatabase/rules/HeadDatabaseRule.java b/Hooks/HeadDataBase/src/main/java/fr/maxlego08/menu/hooks/headdatabase/rules/HeadDatabaseRule.java
new file mode 100644
index 000000000..b0797766e
--- /dev/null
+++ b/Hooks/HeadDataBase/src/main/java/fr/maxlego08/menu/hooks/headdatabase/rules/HeadDatabaseRule.java
@@ -0,0 +1,23 @@
+package fr.maxlego08.menu.hooks.headdatabase.rules;
+
+import fr.maxlego08.menu.api.rules.AbstractPluginItemRule;
+import me.arcaniax.hdb.api.HeadDatabaseAPI;
+import org.bukkit.inventory.ItemStack;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+public class HeadDatabaseRule extends AbstractPluginItemRule {
+ private final HeadDatabaseAPI headDatabaseAPI;
+
+ protected HeadDatabaseRule(@NotNull List itemIds, boolean ignoreCase) {
+ super(itemIds, ignoreCase);
+ this.headDatabaseAPI = new HeadDatabaseAPI();
+ }
+
+ @Override
+ protected @Nullable String resolveId(@NotNull ItemStack itemStack) {
+ return headDatabaseAPI.getItemID(itemStack);
+ }
+}
diff --git a/Hooks/HeadDataBase/src/main/java/fr/maxlego08/menu/hooks/headdatabase/rules/HeadDatabaseRuleLoader.java b/Hooks/HeadDataBase/src/main/java/fr/maxlego08/menu/hooks/headdatabase/rules/HeadDatabaseRuleLoader.java
new file mode 100644
index 000000000..db0f69801
--- /dev/null
+++ b/Hooks/HeadDataBase/src/main/java/fr/maxlego08/menu/hooks/headdatabase/rules/HeadDatabaseRuleLoader.java
@@ -0,0 +1,29 @@
+package fr.maxlego08.menu.hooks.headdatabase.rules;
+
+import fr.maxlego08.menu.api.annotations.AutoRuleLoader;
+import fr.maxlego08.menu.api.configuration.annotation.RequiresPlugin;
+import fr.maxlego08.menu.api.rules.Rule;
+import fr.maxlego08.menu.api.rules.loader.AbstractPluginRuleLoader;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NonNull;
+
+import java.util.List;
+
+@AutoRuleLoader
+@RequiresPlugin("HeadDatabase")
+public class HeadDatabaseRuleLoader extends AbstractPluginRuleLoader {
+ @Override
+ protected @NotNull Rule createRule(@NotNull List items, boolean ignoreCase) {
+ return new HeadDatabaseRule(items, ignoreCase);
+ }
+
+ @Override
+ public @NonNull List getAliases() {
+ return List.of("head-database", "head_database", "hdb");
+ }
+
+ @Override
+ public @NotNull String getType() {
+ return "headdatabase";
+ }
+}
diff --git a/Hooks/Hmccosmetics/build.gradle.kts b/Hooks/Hmccosmetics/build.gradle.kts
index f949571e5..a09cde85a 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 47400fbf9..a5366b4f0 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 e99887fed..53ef9a7df 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/ItemsAdder/src/main/java/fr/maxlego08/menu/hooks/itemsadder/rules/ItemsAdderRule.java b/Hooks/ItemsAdder/src/main/java/fr/maxlego08/menu/hooks/itemsadder/rules/ItemsAdderRule.java
new file mode 100644
index 000000000..1996e8de7
--- /dev/null
+++ b/Hooks/ItemsAdder/src/main/java/fr/maxlego08/menu/hooks/itemsadder/rules/ItemsAdderRule.java
@@ -0,0 +1,22 @@
+package fr.maxlego08.menu.hooks.itemsadder.rules;
+
+import dev.lone.itemsadder.api.CustomStack;
+import fr.maxlego08.menu.api.rules.AbstractPluginItemRule;
+import org.bukkit.inventory.ItemStack;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+public class ItemsAdderRule extends AbstractPluginItemRule {
+ public ItemsAdderRule(@NotNull List itemIds, boolean ignoreCase) {
+ super(itemIds, ignoreCase);
+ }
+
+ @Override
+ @Nullable
+ protected String resolveId(@NotNull ItemStack itemStack) {
+ CustomStack customStack = CustomStack.byItemStack(itemStack);
+ return customStack != null ? customStack.getNamespacedID() : null;
+ }
+}
diff --git a/Hooks/ItemsAdder/src/main/java/fr/maxlego08/menu/hooks/itemsadder/rules/ItemsAdderRuleLoader.java b/Hooks/ItemsAdder/src/main/java/fr/maxlego08/menu/hooks/itemsadder/rules/ItemsAdderRuleLoader.java
new file mode 100644
index 000000000..3d31d349c
--- /dev/null
+++ b/Hooks/ItemsAdder/src/main/java/fr/maxlego08/menu/hooks/itemsadder/rules/ItemsAdderRuleLoader.java
@@ -0,0 +1,25 @@
+package fr.maxlego08.menu.hooks.itemsadder.rules;
+
+import fr.maxlego08.menu.api.annotations.AutoRuleLoader;
+import fr.maxlego08.menu.api.configuration.annotation.RequiresPlugin;
+import fr.maxlego08.menu.api.rules.Rule;
+import fr.maxlego08.menu.api.rules.loader.AbstractPluginRuleLoader;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NonNull;
+
+import java.util.List;
+
+@RequiresPlugin("ItemsAdder")
+@AutoRuleLoader
+public class ItemsAdderRuleLoader extends AbstractPluginRuleLoader {
+
+ @Override
+ public @NonNull String getType() {
+ return "itemsadder";
+ }
+
+ @Override
+ protected @NonNull Rule createRule(@NotNull List items, boolean ignoreCase) {
+ return new ItemsAdderRule(items, ignoreCase);
+ }
+}
\ No newline at end of file
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 62b9b1ddc..dcea907d1 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 86ef5d066..f172dad58 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 5c0dd921f..195d03db7 100644
--- a/Hooks/MMOItems/build.gradle.kts
+++ b/Hooks/MMOItems/build.gradle.kts
@@ -8,5 +8,6 @@ repositories {
dependencies {
compileOnly(projects.common)
- compileOnly("net.Indyuce:MMOItems-API:6.9.5-SNAPSHOT")
+ compileOnly(libs.mmoitems)
+ compileOnly(libs.mythicLib)
}
\ 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 cde9cdb64..b5be3f8ee 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/MMOItems/src/main/java/fr/maxlego08/menu/hooks/mmoitems/rules/MMOItemsRule.java b/Hooks/MMOItems/src/main/java/fr/maxlego08/menu/hooks/mmoitems/rules/MMOItemsRule.java
new file mode 100644
index 000000000..4f2e6cc5e
--- /dev/null
+++ b/Hooks/MMOItems/src/main/java/fr/maxlego08/menu/hooks/mmoitems/rules/MMOItemsRule.java
@@ -0,0 +1,29 @@
+package fr.maxlego08.menu.hooks.mmoitems.rules;
+
+import fr.maxlego08.menu.api.rules.AbstractPluginItemRule;
+import io.lumine.mythic.lib.api.item.NBTItem;
+import org.bukkit.inventory.ItemStack;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+public class MMOItemsRule extends AbstractPluginItemRule {
+
+ public MMOItemsRule(@NotNull List itemIds, boolean ignoreCase) {
+ super(itemIds, ignoreCase);
+ }
+
+ @Override
+ protected @Nullable String resolveId(@NotNull ItemStack itemStack) {
+ NBTItem nbtItem = NBTItem.get(itemStack);
+ if (nbtItem.hasType()) {
+ String itemType = nbtItem.getType();
+ String id = nbtItem.getString("MMOITEMS_ITEM_ID");
+ if (id != null && !id.isEmpty()) {
+ return itemType + ":" + id;
+ }
+ }
+ return null;
+ }
+}
diff --git a/Hooks/MMOItems/src/main/java/fr/maxlego08/menu/hooks/mmoitems/rules/MMOItemsRuleLoader.java b/Hooks/MMOItems/src/main/java/fr/maxlego08/menu/hooks/mmoitems/rules/MMOItemsRuleLoader.java
new file mode 100644
index 000000000..0ddde14ec
--- /dev/null
+++ b/Hooks/MMOItems/src/main/java/fr/maxlego08/menu/hooks/mmoitems/rules/MMOItemsRuleLoader.java
@@ -0,0 +1,29 @@
+package fr.maxlego08.menu.hooks.mmoitems.rules;
+
+import fr.maxlego08.menu.api.annotations.AutoRuleLoader;
+import fr.maxlego08.menu.api.configuration.annotation.RequiresPlugin;
+import fr.maxlego08.menu.api.rules.Rule;
+import fr.maxlego08.menu.api.rules.loader.AbstractPluginRuleLoader;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NonNull;
+
+import java.util.List;
+
+@AutoRuleLoader
+@RequiresPlugin("MMOItems")
+public class MMOItemsRuleLoader extends AbstractPluginRuleLoader {
+ @Override
+ protected @NotNull Rule createRule(@NotNull List items, boolean ignoreCase) {
+ return new MMOItemsRule(items, ignoreCase);
+ }
+
+ @Override
+ public @NonNull List getAliases() {
+ return List.of("mmo-items", "mmo_items");
+ }
+
+ @Override
+ public @NotNull String getType() {
+ return "mmoitems";
+ }
+}
diff --git a/Hooks/MagicCosmetics/build.gradle.kts b/Hooks/MagicCosmetics/build.gradle.kts
index cfab7017b..362fb619e 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 183569b9b..75c77ba81 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 b9773ed3d..999cbd6a7 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 c5c7a4d0a..90e2e211d 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/Nexo/src/main/java/fr/maxlego08/menu/hooks/rules/NexoRule.java b/Hooks/Nexo/src/main/java/fr/maxlego08/menu/hooks/rules/NexoRule.java
new file mode 100644
index 000000000..5f538ab45
--- /dev/null
+++ b/Hooks/Nexo/src/main/java/fr/maxlego08/menu/hooks/rules/NexoRule.java
@@ -0,0 +1,21 @@
+package fr.maxlego08.menu.hooks.rules;
+
+import com.nexomc.nexo.api.NexoItems;
+import fr.maxlego08.menu.api.rules.AbstractPluginItemRule;
+import org.bukkit.inventory.ItemStack;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+public class NexoRule extends AbstractPluginItemRule {
+
+ public NexoRule(@NotNull List itemIds, boolean ignoreCase) {
+ super(itemIds, ignoreCase);
+ }
+
+ @Override
+ protected @Nullable String resolveId(@NotNull ItemStack itemStack) {
+ return NexoItems.idFromItem(itemStack);
+ }
+}
diff --git a/Hooks/Nexo/src/main/java/fr/maxlego08/menu/hooks/rules/NexoRuleLoader.java b/Hooks/Nexo/src/main/java/fr/maxlego08/menu/hooks/rules/NexoRuleLoader.java
new file mode 100644
index 000000000..bde24e3b9
--- /dev/null
+++ b/Hooks/Nexo/src/main/java/fr/maxlego08/menu/hooks/rules/NexoRuleLoader.java
@@ -0,0 +1,23 @@
+package fr.maxlego08.menu.hooks.rules;
+
+import fr.maxlego08.menu.api.annotations.AutoRuleLoader;
+import fr.maxlego08.menu.api.configuration.annotation.RequiresPlugin;
+import fr.maxlego08.menu.api.rules.Rule;
+import fr.maxlego08.menu.api.rules.loader.AbstractPluginRuleLoader;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+@AutoRuleLoader
+@RequiresPlugin("Nexo")
+public class NexoRuleLoader extends AbstractPluginRuleLoader {
+ @Override
+ protected @NotNull Rule createRule(@NotNull List items, boolean ignoreCase) {
+ return new NexoRule(items, ignoreCase);
+ }
+
+ @Override
+ public @NotNull String getType() {
+ return "nexo";
+ }
+}
diff --git a/Hooks/NextGens/src/main/java/fr/maxlego08/menu/hooks/rules/NextGensRule.java b/Hooks/NextGens/src/main/java/fr/maxlego08/menu/hooks/rules/NextGensRule.java
new file mode 100644
index 000000000..9ca99bd59
--- /dev/null
+++ b/Hooks/NextGens/src/main/java/fr/maxlego08/menu/hooks/rules/NextGensRule.java
@@ -0,0 +1,23 @@
+package fr.maxlego08.menu.hooks.rules;
+
+import com.muhammaddaffa.nextgens.NextGens;
+import com.muhammaddaffa.nextgens.generators.Generator;
+import fr.maxlego08.menu.api.rules.AbstractPluginItemRule;
+import org.bukkit.inventory.ItemStack;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+public class NextGensRule extends AbstractPluginItemRule {
+
+ public NextGensRule(@NotNull List itemIds, boolean ignoreCase) {
+ super(itemIds, ignoreCase);
+ }
+
+ @Override
+ protected @Nullable String resolveId(@NotNull ItemStack itemStack) {
+ Generator generator = NextGens.getApi().getGenerator(itemStack);
+ return generator != null ? generator.id() : null;
+ }
+}
diff --git a/Hooks/NextGens/src/main/java/fr/maxlego08/menu/hooks/rules/NextGensRuleLoader.java b/Hooks/NextGens/src/main/java/fr/maxlego08/menu/hooks/rules/NextGensRuleLoader.java
new file mode 100644
index 000000000..c8eab74e3
--- /dev/null
+++ b/Hooks/NextGens/src/main/java/fr/maxlego08/menu/hooks/rules/NextGensRuleLoader.java
@@ -0,0 +1,23 @@
+package fr.maxlego08.menu.hooks.rules;
+
+import fr.maxlego08.menu.api.annotations.AutoRuleLoader;
+import fr.maxlego08.menu.api.configuration.annotation.RequiresPlugin;
+import fr.maxlego08.menu.api.rules.Rule;
+import fr.maxlego08.menu.api.rules.loader.AbstractPluginRuleLoader;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+@AutoRuleLoader
+@RequiresPlugin("NextGens")
+public class NextGensRuleLoader extends AbstractPluginRuleLoader {
+ @Override
+ protected @NotNull Rule createRule(@NotNull List items, boolean ignoreCase) {
+ return new NextGensRule(items, ignoreCase);
+ }
+
+ @Override
+ public @NotNull String getType() {
+ return "nextgens";
+ }
+}
diff --git a/Hooks/Nova/build.gradle.kts b/Hooks/Nova/build.gradle.kts
index 800b58a88..e54b4cbac 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/Nova/src/main/java/fr/maxlego08/menu/hooks/rules/NovaRule.java b/Hooks/Nova/src/main/java/fr/maxlego08/menu/hooks/rules/NovaRule.java
new file mode 100644
index 000000000..0837ecef1
--- /dev/null
+++ b/Hooks/Nova/src/main/java/fr/maxlego08/menu/hooks/rules/NovaRule.java
@@ -0,0 +1,23 @@
+package fr.maxlego08.menu.hooks.rules;
+
+import fr.maxlego08.menu.api.rules.AbstractPluginItemRule;
+import org.bukkit.inventory.ItemStack;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import xyz.xenondevs.nova.api.Nova;
+import xyz.xenondevs.nova.api.item.NovaItem;
+
+import java.util.List;
+
+public class NovaRule extends AbstractPluginItemRule {
+
+ public NovaRule(@NotNull List itemIds, boolean ignoreCase) {
+ super(itemIds, ignoreCase);
+ }
+
+ @Override
+ protected @Nullable String resolveId(@NotNull ItemStack itemStack) {
+ NovaItem novaItem = Nova.getNova().getItemRegistry().getOrNull(itemStack);
+ return novaItem != null ? novaItem.getId().toString() : null;
+ }
+}
diff --git a/Hooks/Nova/src/main/java/fr/maxlego08/menu/hooks/rules/NovaRuleLoader.java b/Hooks/Nova/src/main/java/fr/maxlego08/menu/hooks/rules/NovaRuleLoader.java
new file mode 100644
index 000000000..b892a90cb
--- /dev/null
+++ b/Hooks/Nova/src/main/java/fr/maxlego08/menu/hooks/rules/NovaRuleLoader.java
@@ -0,0 +1,23 @@
+package fr.maxlego08.menu.hooks.rules;
+
+import fr.maxlego08.menu.api.annotations.AutoRuleLoader;
+import fr.maxlego08.menu.api.configuration.annotation.RequiresPlugin;
+import fr.maxlego08.menu.api.rules.Rule;
+import fr.maxlego08.menu.api.rules.loader.AbstractPluginRuleLoader;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+@AutoRuleLoader
+@RequiresPlugin("Nova")
+public class NovaRuleLoader extends AbstractPluginRuleLoader {
+ @Override
+ protected @NotNull Rule createRule(@NotNull List items, boolean ignoreCase) {
+ return new NovaRule(items, ignoreCase);
+ }
+
+ @Override
+ public @NotNull String getType() {
+ return "nova";
+ }
+}
diff --git a/Hooks/Oraxen/build.gradle.kts b/Hooks/Oraxen/build.gradle.kts
index 3a9fcaf82..b2875aa75 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/Oraxen/src/main/java/fr/maxlego08/menu/hooks/rules/OraxenRule.java b/Hooks/Oraxen/src/main/java/fr/maxlego08/menu/hooks/rules/OraxenRule.java
new file mode 100644
index 000000000..c040a87d1
--- /dev/null
+++ b/Hooks/Oraxen/src/main/java/fr/maxlego08/menu/hooks/rules/OraxenRule.java
@@ -0,0 +1,22 @@
+package fr.maxlego08.menu.hooks.rules;
+
+import fr.maxlego08.menu.api.rules.AbstractPluginItemRule;
+import io.th0rgal.oraxen.api.OraxenItems;
+import org.bukkit.inventory.ItemStack;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+public class OraxenRule extends AbstractPluginItemRule {
+
+ public OraxenRule(@NotNull List itemIds, boolean ignoreCase) {
+ super(itemIds, ignoreCase);
+ }
+
+ @Override
+ @Nullable
+ protected String resolveId(@NotNull ItemStack itemStack) {
+ return OraxenItems.getIdByItem(itemStack);
+ }
+}
diff --git a/Hooks/Oraxen/src/main/java/fr/maxlego08/menu/hooks/rules/OraxenRuleLoader.java b/Hooks/Oraxen/src/main/java/fr/maxlego08/menu/hooks/rules/OraxenRuleLoader.java
new file mode 100644
index 000000000..70fd0e5a6
--- /dev/null
+++ b/Hooks/Oraxen/src/main/java/fr/maxlego08/menu/hooks/rules/OraxenRuleLoader.java
@@ -0,0 +1,25 @@
+package fr.maxlego08.menu.hooks.rules;
+
+import fr.maxlego08.menu.api.annotations.AutoRuleLoader;
+import fr.maxlego08.menu.api.configuration.annotation.RequiresPlugin;
+import fr.maxlego08.menu.api.rules.Rule;
+import fr.maxlego08.menu.api.rules.loader.AbstractPluginRuleLoader;
+import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NonNull;
+
+import java.util.List;
+
+@RequiresPlugin("Oraxen")
+@AutoRuleLoader
+public class OraxenRuleLoader extends AbstractPluginRuleLoader {
+
+ @Override
+ public String getType() {
+ return "oraxen";
+ }
+
+ @Override
+ protected @NonNull Rule createRule(@NotNull List items, boolean ignoreCase) {
+ return new OraxenRule(items, ignoreCase);
+ }
+}
\ No newline at end of file
diff --git a/Hooks/PacketEvents/build.gradle.kts b/Hooks/PacketEvents/build.gradle.kts
index 064786d95..b6240730f 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 91b49d765..f551dba29 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