Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
55d39d3
feat: slot animations, registries and registry-backed inventory reloads
1robie Oct 22, 2026
b8ca02e
Merge branch 'develop' into feature/slot-animations
1robie Oct 22, 2026
b7e3499
feat: serialize slot animations
1robie Oct 22, 2026
2832f45
feat: store named animations in a reloadable registry
1robie Oct 22, 2026
e4815dc
feat: update inventory registry to use ZMenuKeys namespace
1robie Oct 22, 2026
dcb04e0
feat: remove legacy ClassicMeta formatter and update MiniMessage hand…
1robie Oct 22, 2026
6282089
feat: move animation history out of InventoryManager
1robie Oct 22, 2026
4a856f0
feat: deprecate InventoryManager methods that do not belong to it
1robie Oct 22, 2026
40f8fdb
feat: move the menu page of a player to PaginationManager
1robie Oct 22, 2026
f8a5027
feat: add ItemStackService for item loading, conversion and comparison
1robie Oct 22, 2026
2ba124a
feat: deprecate the varargs openInventory overload
1robie Oct 22, 2026
e2318ec
chore: remove the pre-1.14 NMS dupe manager and its modules
1robie Oct 22, 2026
48030fd
chore: remove code paths for versions older than 1.20.6
1robie Oct 22, 2026
2c6ce5c
chore: remove unused internal classes
1robie Oct 22, 2026
97214d3
chore: drop the unused NBT-API dependency
1robie Oct 22, 2026
e0d4bf0
chore: use java.util.Base64 for serialized items
1robie Oct 22, 2026
729bb26
chore: remove commented-out code
1robie Oct 22, 2026
afd6ea2
fix: register the lore item verification
1robie Oct 22, 2026
c109a20
fix: restore the messages of /zm reload command
1robie Oct 22, 2026
3d55bae
fix: remove the abandoned map-based item reader
1robie Oct 22, 2026
5a2b273
fix: restore escaped percent signs in every placeholder path
1robie Oct 22, 2026
5f5a5b4
perf: share one PlaceholderAPI result cache
1robie Oct 22, 2026
255a9df
feat: deprecate the Spigot platform detection
1robie Oct 22, 2026
1fec346
feat: deprecate API types zMenu never uses
1robie Oct 22, 2026
58f6c96
feat: deprecate redundant inventory and item members
1robie Oct 22, 2026
629e94f
feat: deprecate the pre-1.9 Potion methods
1robie Oct 22, 2026
6f61443
chore: remove generated constructor stub comments
1robie Oct 22, 2026
a1b267c
fix: discord webhook avatar
1robie Oct 22, 2026
15186f7
feat: add open registries with per-plugin cleanup
1robie Oct 22, 2026
7ab6c73
feat: move requirement types to the PERMISSIBLE registry
1robie Oct 22, 2026
ccf7ec3
feat: move action types to the ACTION registry
1robie Oct 22, 2026
2b69cc7
feat: move button types to the BUTTON registry
1robie Oct 22, 2026
554b495
feat: move item rule types to the RULE registry
1robie Oct 22, 2026
ded9192
feat: move item comparisons to the ITEM_VERIFICATION registry
1robie Oct 23, 2026
68b7304
feat: move material loaders to the MATERIAL_LOADER registry
1robie Oct 23, 2026
30c1809
feat: move item components to the ITEM_COMPONENT registry
1robie Oct 23, 2026
c0e59b8
feat: move command argument types to their registry
1robie Oct 23, 2026
2fa796e
feat: move custom item mechanics to the MECHANIC registry
1robie Oct 23, 2026
6e8c58d
feat: move button and inventory options to registries
1robie Oct 23, 2026
334c985
refactor: drop the deprecated Registry base from internal registries
1robie Oct 23, 2026
f0aaa75
feat: add SoundService and MenuPlugin#readYamlFile
1robie Oct 23, 2026
adda90d
feat: move slot animation reading to zMenuPlus
1robie Oct 23, 2026
2ba3fc7
feat: replace fallback plugin name with ZMenuKeys.PLUGIN_NAME
1robie Oct 23, 2026
71ccc06
feat: add a features section to turn off custom items
1robie Oct 23, 2026
40f0949
Merge branch 'feature/slot-animations' into develop
1robie Oct 23, 2026
3ae21d5
fix: clamp item stack amount to the range of 1 to 99
1robie Oct 25, 2026
40b2aee
Merge remote-tracking branch 'upstream/develop' into develop
1robie Oct 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
java-version: '25'
publish: true
project-to-publish: "API:publish"
discord-avatar-url: "https://groupez.dev/storage/images/253.png"
discord-avatar-url: "https://groupez.dev/storage/images/resources/icons/253.webp"
artifact-glob: "target/*.jar"
changelog-exclude-pattern: '^[a-f0-9]+\s+(build|chore)\(deps\)'
secrets:
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,5 @@ build-and-deploy.sh
GEMINI.md

TODO.md
docs/triage-issues.md
/docs/*
!/docs/live-sync-plan.md
11 changes: 10 additions & 1 deletion API/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
plugins {
alias(libs.plugins.groupez.publish)
`java-test-fixtures`
}

dependencies{
compileOnly(libs.adventure.api)
compileOnly(libs.adventure.text.minimessage)

testImplementation(libs.paper.api)
testFixturesCompileOnly(libs.paper.api)
}

// The test fixtures are shared with the tests of other modules, they are not published.
(components["java"] as AdhocComponentWithVariants).apply {
withVariantsFromConfiguration(configurations["testFixturesApiElements"]) { skip() }
withVariantsFromConfiguration(configurations["testFixturesRuntimeElements"]) { skip() }
}

rootProject.extra.properties["sha"]?.let { sha ->
Expand All @@ -15,7 +25,6 @@ tasks {
shadowJar {
relocate("com.tcoded.folialib", "fr.maxlego08.menu.hooks.folialib")
relocate("fr.traqueur.currencies", "fr.maxlego08.menu.hooks.currencies")
relocate("de.tr7zw.changeme.nbtapi", "fr.maxlego08.menu.hooks.nbtapi")
relocate("com.cryptomorin.xseries", "fr.maxlego08.menu.hooks.xseries")
relocate("fr.maxlego08.sarah", "fr.maxlego08.menu.hooks.sarah")
relocate("net.objecthunter.exp4j", "fr.maxlego08.menu.hooks.exp4j")
Expand Down
35 changes: 23 additions & 12 deletions API/src/main/java/fr/maxlego08/menu/api/ButtonManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import fr.maxlego08.menu.api.requirement.Action;
import fr.maxlego08.menu.api.requirement.Permissible;
import fr.maxlego08.menu.api.requirement.Requirement;
import fr.maxlego08.menu.api.rules.loader.RuleLoader;
import fr.maxlego08.menu.api.utils.Loader;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.plugin.Plugin;
Expand Down Expand Up @@ -37,21 +36,30 @@ public interface ButtonManager {
* Registers a new {@link ButtonLoader} responsible for button creation.
*
* @param button The {@link ButtonLoader} instance to register.
* @deprecated register it in {@link fr.maxlego08.menu.api.registry.Registries#BUTTON}:
* {@code registries.writable(Registries.BUTTON).register(plugin, loader, loader.aliases())}, which
* throws on a name already taken instead of logging it.
*/
@Deprecated(since = "1.1.2.1", forRemoval = true)
void register(@NotNull ButtonLoader button);

/**
* Unregisters an existing {@link ButtonLoader}, ceasing its button creation responsibilities.
*
* @param button The {@link ButtonLoader} instance to unregister.
* @deprecated use {@code registries.writable(Registries.BUTTON).unregister(loader.key())}.
*/
@Deprecated(since = "1.1.2.1", forRemoval = true)
void unregister(@NotNull ButtonLoader button);

/**
* Unregisters all {@link ButtonLoader} instances linked to a specific plugin.
*
* @param plugin The plugin whose loaders should be unregistered.
* @deprecated a plugin's button types are removed when it disables; to remove them earlier use
* {@code registries.writable(Registries.BUTTON).unregisterAll(plugin)}.
*/
@Deprecated(since = "1.1.2.1", forRemoval = true)
void unregisters(@NotNull Plugin plugin);

/**
Expand All @@ -67,8 +75,11 @@ public interface ButtonManager {
*
* @param plugin The plugin whose loaders are to be retrieved.
* @return A collection of {@link ButtonLoader} instances or an empty collection if none are found.
* @deprecated read {@link fr.maxlego08.menu.api.registry.Registries#BUTTON} and its
* {@link fr.maxlego08.menu.api.registry.KeyedRegistry#owner(net.kyori.adventure.key.Key) owners}.
*/
@NotNull
@Deprecated(since = "1.1.2.1", forRemoval = true)
Collection<ButtonLoader> getLoaders(@NotNull Plugin plugin);

/**
Expand All @@ -84,15 +95,21 @@ public interface ButtonManager {
* Registers a new {@link PermissibleLoader} responsible for permissible creation.
*
* @param permissibleLoader The {@link PermissibleLoader} instance to register.
* @deprecated register it in {@link fr.maxlego08.menu.api.registry.Registries#PERMISSIBLE}:
* {@code registries.writable(Registries.PERMISSIBLE).register(plugin, loader)}, which throws on a
* name already taken instead of logging it.
*/
@Deprecated(since = "1.1.2.1", forRemoval = true)
void registerPermissible(@NotNull PermissibleLoader permissibleLoader);

/**
* Retrieves a mapping of permissible keys to their associated {@link PermissibleLoader} instances.
*
* @return A map linking permissible keys to their corresponding {@link PermissibleLoader} instances.
* @return A copy of the registered types, by their lowercased name.
* @deprecated read {@link fr.maxlego08.menu.api.registry.Registries#PERMISSIBLE}.
*/
@NotNull
@Deprecated(since = "1.1.2.1", forRemoval = true)
Map<String, PermissibleLoader> getPermissibles();

/**
Expand All @@ -108,19 +125,13 @@ public interface ButtonManager {
* Registers a new {@link ActionLoader} responsible for action creation.
*
* @param actionLoader The {@link ActionLoader} instance to register.
* @deprecated register it in {@link fr.maxlego08.menu.api.registry.Registries#ACTION}:
* {@code registries.writable(Registries.ACTION).register(plugin, loader, loader.aliases())}, which
* throws on a name already taken instead of logging it.
*/
@Deprecated(since = "1.1.2.1", forRemoval = true)
void registerAction(@NotNull ActionLoader actionLoader);

/**
* Registers a {@link RuleLoader} so its rule type (and aliases) can be used in item rules,
* for example in an {@code item_drag} button or an {@code item-rule} requirement.
* <p>
* Unlike {@code @AutoRuleLoader}, which only scans the zMenu package, this lets external plugins add rule types.
*
* @param ruleLoader The {@link RuleLoader} instance to register.
*/
void registerRuleLoader(@NotNull RuleLoader ruleLoader);

/**
* Retrieves an {@link Optional} {@link ActionLoader} based on a specific action key.
*
Expand Down
10 changes: 6 additions & 4 deletions API/src/main/java/fr/maxlego08/menu/api/ComponentsManager.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package fr.maxlego08.menu.api;

import fr.maxlego08.menu.api.exceptions.ItemComponentAlreadyRegisterException;
import fr.maxlego08.menu.api.loader.ItemComponentLoader;
import org.jetbrains.annotations.NotNull;

Expand All @@ -12,11 +11,14 @@ public interface ComponentsManager {
void initializeDefaultComponents(MenuPlugin plugin);

/**
* Register a new ItemComponentLoader.
* Register a new ItemComponentLoader. A name already taken is logged and the loader is not registered.
* @param loader The loader to register
* @throws ItemComponentAlreadyRegisterException if a loader with the same name is already registered
* @deprecated register it in {@link fr.maxlego08.menu.api.registry.Registries#ITEM_COMPONENT}:
* {@code registries.writable(Registries.ITEM_COMPONENT).register(plugin, loader, loader.aliases())},
* which throws on a name already taken.
**/
void registerComponent(@NotNull ItemComponentLoader loader) throws ItemComponentAlreadyRegisterException;
@Deprecated(since = "1.1.2.1", forRemoval = true)
void registerComponent(@NotNull ItemComponentLoader loader);

/**
* Get an ItemComponentLoader by its name.
Expand Down
19 changes: 18 additions & 1 deletion API/src/main/java/fr/maxlego08/menu/api/Inventory.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import fr.maxlego08.menu.api.utils.OpenWithItem;
import fr.maxlego08.menu.api.utils.Placeholders;
import fr.maxlego08.menu.api.utils.SectionSerializable;
import net.kyori.adventure.key.Key;
import net.kyori.adventure.key.Keyed;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryType;
Expand All @@ -31,7 +33,19 @@
* Documentation: <a href="https://docs.zmenu.dev/api/create-inventory">Inventory documentation</a>
* <p>This class encapsulates information about an inventory, including its size, buttons, patterns, and associated requirements.</p>
*/
public interface Inventory extends SectionSerializable {
public interface Inventory extends Keyed, SectionSerializable {

/**
* Returns the key of the inventory: the name of its plugin and its file name, lowercased, with
* every character a key cannot hold replaced by "_".
*
* @return the key
* @see ZMenuKeys#fileKey(String, String)
*/
@Override
default @NotNull Key key() {
return ZMenuKeys.fileKey(this.getPlugin().getName(), this.getFileName());
}

/**
* Returns the size of the inventory.
Expand Down Expand Up @@ -91,6 +105,9 @@ public interface Inventory extends SectionSerializable {
/**
* Returns the name of the file associated with the inventory.
*
* <p>Use it to display or store the inventory, not to identify it: the case is kept, so it can
* differ from {@link #key()}. Compare and look up inventories with {@link #key()}.</p>
*
* @return The file name. This name is the name of the configuration file.
*/
String getFileName();
Expand Down
Loading
Loading