Skip to content

Feature add slot animation - #272

Closed
1robie wants to merge 66 commits into
Maxlego08:developfrom
1robie:feature/slot-animations
Closed

1robie wants to merge 66 commits into
Maxlego08:developfrom
1robie:feature/slot-animations

Conversation

@1robie

@1robie 1robie commented Oct 22, 2026

Copy link
Copy Markdown
Collaborator

Add slot animation support + some exemples

1robie and others added 26 commits October 13, 2026 16:59
ANVIL inventories only have a packet engine on 1.21+. On older versions
they fall back to the chest engine and rename-requirements never run.
Log an error at load time and document the minimum version in the README.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
…nitial-value' and standardize 'after-action' syntax
…an up log upload success message (remove old check for spigot)
Slot animations
- Reveal/conceal animations for inventories (open, close, actions), per-button
  settings, idle animations, temporary items with keyframes, variants, seeds.
- Built-in reveal orders in api.animation.slot.order; each type is a
  SlotAnimationLoader registered through @AutoSlotAnimationLoader, addons use
  InventoryManager#registerSlotAnimation.
- The compiler is internal (Common fr.maxlego08.menu.animation.compile); the
  API keeps the entry points, settings and order implementations.

Registries
- Typed registries (RegistryType, KeyedRegistry, WritableRegistry,
  RegistryManager) with namespaced keys, owners, aliases, and static
  registries frozen once the server has loaded.
- Reloadable registries rebuilt into a snapshot and swapped atomically
  (ReloadContext, ReloadReport, ReloadValidator).

Inventories
- zMenu's own menus live in a reloadable registry keyed zmenu:<file>: a file
  that fails on reload keeps its previous version, load events fire once the
  new snapshot is live, YAML errors no longer load an empty menu.
- Key-based InventoryManager methods; the name-based ones are deprecated for
  removal and delegate to them.
Conflicts resolved:
- ZInventoryManager: inventories stay in the registry; develop's shared-name rule (zMenu first, then
  plugin name order), its collision warning and its same-name re-registration on delete are kept,
  over keys. deleteInventory only removes one of zMenu's own while it is still the live entry, so
  InventoryHotReload (load new, then delete old) keeps the new version.
- InventoryDefault: develop's WrappedTask refresh timers and cancelTimers(); the animation and idle
  tasks are stopped with them.
- Inventory: extends both Keyed and SectionSerializable.
- InventoryManager, Configuration, Button, ZMenuPlugin, VInventoryManager: both sides kept.
- InventoryLoader: develop removed save(); the animation validation helpers stay.
- Commands: develop's NameSuggestions, fed with the inventory keys.
- BedrockReplacementListener (from develop) uses the key-based lookup.
Menus write their open-animation and close-animation, buttons their animation
settings and idle-animation, and the animation action its file, stop, inline
animation, mode and freeze, in the form the loaders read back.

- Each built-in SlotAnimation writes its type (matrix its rows, custom its
  order); an animation built in code cannot be serialized.
- Groups write only what differs from the group they inherit from.
- Settings and idle animations that only name files are written back as
  file:, otherwise in full.
- RandomPitchSoundOption writes its pitch range.
- Round-trip test over every example menu, and fixtures for the animation
  action.
- Add Registries.ANIMATION; animation files and plugin-registered animations
  are provided to it, a broken file keeps its previous version
- Animations are keyed (zmenu:<file> or plugin:name); CustomAnimation takes a Key
- The animation action resolves a Key loaded once from file:
- Skip button idle animation files when loading inventory animations
@1robie
1robie marked this pull request as draft October 22, 2026 14:32
Which animations a player has already seen now lives in AnimationHistory,
reached with AnimationManager#getHistory(), instead of eight methods on
InventoryManager. ZAnimationHistory holds the session and database memory
that ZInventoryManager used to keep.
1robie added 29 commits October 22, 2026 21:27
The hand-written codec produced standard padded Base64 and skipped
whitespace when decoding; java.util.Base64's encoder and MIME decoder give
the same results, checked on 20000 random inputs, so stored items still
read back.
Drops the old firework reader and its unused colour list helper, the old
download call, the Persist save/load pair, and commented log and listener
lines. The commented messages of /zm reload command and the disabled
anti-dupe Discord notification are left for their own fixes.
LoreSimilar had no @AutoItemStackSimilar, so 'lore' was never registered
and every lookup fell back to a full item comparison.
They were commented out when the command moved to paper-dispatch, so the
command gave no feedback at all.
ZMenuItemStack#setTypeMapAccessor lost its last callers in 78b075b,
when the take_item action and the item permissible moved to
loadItemStack. It kept a third enchantment parser that had drifted from
the loader's (comma only, Enchantment.getByName), so MenuItemStackLoader
is now the only one.
Dialog inputs escape % as U+F000 so PlaceholderAPI leaves them alone.
Placeholder.Api restored it, Placeholder.Local did not, so without
PlaceholderAPI only ActionHelper and MenuPlugin#parse (which added their
own replace) gave the % back, and PapiUtils left the escape character in
the text. Local now restores it too and the duplicate replaces are gone.
PapiUtils kept its cache in instance fields, so every ZUtils subclass,
including each ZMenuItemStack, parsed the same placeholder for the same
player on its own. The cache is now shared, still keyed by text and
player and rebuilt when cache-placeholderapi changes.
PlatformType, @PaperOnly and @SpigotOnly are deprecated for removal since
zMenu only runs on Paper. VersionFilter keeps refusing @SpigotOnly
classes without asking PlatformType, the Paper client version provider
is always available, and ZMenuPlugin answers the deprecated
isPaper/isPaperOrFolia/isSpigot with their only possible values.
NoneButton, ClickAction, TrimHelper, ZPersistentDataType,
ZDamageReductionRecord, ZToolRule, ResolvablePlayerProfile,
ItemCreateException, StringConsumer, ReturnConsumer,
ItemComponentLoaderInterface and EnumInventory.INVENTORY_MARKETPLACE have
no user in zMenu; each is deprecated for removal and names its
replacement where there is one. ZDataManager uses Function instead of
ReturnConsumer.
BaseInventory#getSpigotInventory returned the same inventory as
getInventory; it is now a deprecated default and zMenu calls
getInventory. InventoryEngine#setMaxPage and the MenuItemStack cache
setters are deprecated since zMenu computes those values itself.
InventoryEngine#cancel loses its wrong @contract(pure = true).
fromDamage reads damage values that potions lost in 1.9 and looks up
type names that no longer exist; toDamageValue and getNameId always
return 0; the brewer is never set or read. All are deprecated for
removal.
57 'TODO Auto-generated constructor stub' lines in the API exceptions and
MenuEvent marked nothing left to do.
RegistryType.Kind.OPEN registries are never frozen; RegistryOwnerListener
removes a plugin's entries from them when it disables, so a plugin
reloaded at runtime can register again. WritableRegistry gains
unregister, unregisterAll(owner) and an all-or-nothing register with
aliases. RegistryOwners resolves the owner of entries handed to the old
register methods (the plugin that provides their class) and turns a
clash into a warning. ZMenuKeys.parse turns any name into a key, reading
spaces, '-' and every character a key cannot hold as underscores, so
names registered before the registries keep working; tryParse only
returns null for a blank name. Menus waiting for an element match its
name the same way.
PermissibleLoader is Keyed (its type read like a YAML name) and lives in
the open Registries.PERMISSIBLE registry. Registries notify listeners of
each new key and alias, so menus waiting for a requirement type load
whichever way it is registered. registerPermissible and getPermissibles
are deprecated; a type registered twice is now refused with a warning
instead of silently replacing the first one.
ActionLoader is Keyed by its first name, with the others as aliases, and
lives in the open Registries.ACTION registry; names are read like YAML
types, so any case or space/dash/underscore spelling resolves. zMenu
registers its built-ins straight into the registry, registerAction is
deprecated, and the serialization test reads the registry instead of the
old private map.
ButtonLoader is Keyed by its name, with its aliases as keys, and lives in
the open Registries.BUTTON registry owned by ButtonLoader#getPlugin. The
O(n) name/alias clash scan and the linear lookup are gone. The
ButtonManager register/unregister methods, getLoaders(Plugin) and
ButtonLoaderRegisterEvent#register are deprecated; a clash is logged
instead of throwing ButtonAlreadyRegisterException, which is deprecated.
RuleLoader is Keyed by its type, with its aliases as keys, and lives in
the open Registries.RULE registry. ZRuleLoaderRegistry is no longer a
lazily created singleton on the deprecated Registry base: it is a static
helper that registers the built-ins and reads a rule through the
registry. The unreleased ButtonManager#registerRuleLoader is removed and
the published RuleLoaderRegistry is deprecated.
ItemStackSimilar is Keyed by its name and lives in the open
Registries.ITEM_VERIFICATION registry. ItemStackService keeps
getVerification(String) for names read from files and drops the
unreleased registerVerification/getVerifications; the deprecated
InventoryManager methods use the registry.
MaterialLoader is Keyed by its prefix and lives in the open
Registries.MATERIAL_LOADER registry, replacing the list scanned on every
item build. The InventoryManager register and lookup methods are
deprecated; zMenu reads the registry when it resolves a prefixed material.
ItemComponentLoader is Keyed: minecraft:<name> for Minecraft components,
with <name> as an alias, and <plugin>:<name> for a plugin's. They live
in the open Registries.ITEM_COMPONENT registry; ZComponentsManager reads
it and takes the registry manager in its constructor, so tests still use
an isolated one. registerComponent is deprecated and logs a clash; the
exception it used to throw is deprecated.
CommandArgumentValidator is Keyed by its type and lives in the open
Registries.COMMAND_ARGUMENT_VALIDATOR registry. The block validator was
created with the type "material", so it shadowed nothing and "block"
never resolved; MaterialArgumentValidator now has material() and
block() with their own types, and block only accepts blocks. The
CommandManager register, unregister and list methods are deprecated.
MechanicFactory is Keyed by its id and lives in the open
Registries.MECHANIC registry. A custom item records the factory's own id,
so a mechanic written with another spelling still matches its listeners.
ItemManager#registerMechanicFactory is deprecated.
Options are registered as classes, so they get keyed wrapper records,
ButtonOptionType and InventoryOptionType (<plugin>:<class name>), held
in the open BUTTON_OPTION and INVENTORY_OPTION registries. Buttons,
inventories, Bedrock forms, dialogs and inventory serialization read
the registries; the InventoryManager option methods are deprecated and
still register the same class only once.
The inventory type, Bedrock type, dialog type and dialog action
registries only ever registered and read entries, so they keep their own
EnumMap or HashMap instead of extending the deprecated Registry<T,R>.
RegistryNameTest checks that names a key cannot hold as they are
(symbols, accents, spaces in a namespace, a second ':') still register
and are found by the same name, through the old register methods and
the registries, for buttons, actions, requirements, material loaders,
item comparisons, command argument types, mechanics and rules.
The slot animation loader built sounds with the internal ZSoundOption and
RandomPitchSoundOption and read file references through Common's
YamlFileCache, which a plugin compiling against the API cannot reach.
SoundService creates fixed and random-pitch sounds and reads them in the
animation format; readYamlFile exposes the file cache. The loader, the
animation action and its loader now only use the API. The unreleased
InventoryManager#createSoundOption is removed.
zMenu keeps the animation engine, its API, the history, the built-in
reveal orders, /zm resetanimation and the animations folder with its
default files. Reading open-animation, close-animation, the button
animation and idle-animation, the animation action and the files of the
animations folder now belongs to zMenuPlus, like player-inventory, along
with the example menus and their tests. ContainerInventory gets
setSlotAnimation/setCloseAnimation in the API so an inventory option can
set them. The animation docs are kept out of git.
features.custom-items in config.yml disables the items folder, the
itemjoin and on-click mechanics, the item update on join and
/zm giveitem. Features are read once at startup; /zm reload warns when
one changed. When disabled, getItemManager() returns DisabledItemManager,
which knows no item and ignores addon registrations.
@1robie 1robie closed this Oct 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant