▶️ ЗАБЕРИ СВОИ 8 ПОДАРКОВ 🎁 ПРИ СОЗДАНИИ СВОЕГО МАЙНКРАФТ СЕРВЕРА
Allium

Allium

A modern, secure Essentials solution

Оцените первым
135
1
Все версииAllium v0.2.7a

Allium v0.2.7a

Release19.07.2026

Список изменений

Allium v0.2.7a

Wiki: https://github.com/castledking/Allium/wiki

Highlights

  • New pluggable command permission resolution pipeline — The ad-hoc permission heuristics in CommandManager have been replaced by a dedicated codes.castled.allium.permissions.command package. A chain of framework-specific adapters (Paper BasicCommand, Brigadier, NightCore, Bukkit, LuckPerms, registered-permission conventions) resolves whether a player may run a command, and reports how the decision was made. Unit-tested with JUnit 5.
  • Vault Chat abstract-class support — When the Vault Chat class is an abstract class rather than an interface, the provider is now assigned directly instead of being skipped, so chat formatting works with permission plugins that expose Chat through an abstract base.
  • Deleted chat messages no longer reappear — Fixed duplicate per-player message tracking that broke content matching in deleteMessage, causing deleted messages to resurface on resend.
  • Nickname formatting fixes%allium_nickname% is now recognized as a player placeholder in chat formats, and channel messages use the formatted nickname (falling back to the real name when no nickname is stored).
  • Oraxen → Nexo migration — Built-in custom items (Tree Axe, Spawner Changer) now reference nexo: item models instead of oraxen:.

Technical Details

Command Permission Resolver (permissions/command)

CommandManager previously resolved permissions through a single hasPermissionForCommand() method that had accumulated special cases (VanillaCommandWrapper class-name checks, Paper-internals safety nets, Allium-derived permissions). That logic is now factored into an adapter pipeline:

DefaultCommandPermissionResolver
  ├── (extension point: CommandAPI, ACF, cloud, …)
  ├── PaperBasicCommandPermissionAdapter   — reflects the wrapped Paper BasicCommand, calls canUse()/permission()
  ├── BrigadierCommandPermissionAdapter    — finds the CommandNode field, walks requires() predicates; VanillaCommandWrapper without an inspectable node → allow (defer to native dispatch)
  ├── NightCoreCommandPermissionAdapter    — reads NightCore's public command tree reflectively (no hard dependency), tests root and sub-command nodes
  ├── BukkitCommandPermissionAdapter       — explicit command.getPermission() → testPermissionSilent()
  ├── LuckPermsCommandPermissionAdapter    — queries CachedPermissionData against candidate permission strings (reflective, no hard dependency)
  └── RegisteredCommandPermissionAdapter   — checks candidate permissions registered with Bukkit's PluginManager (wildcards only count as a grant, never as a denial)

Key contracts:

  • CommandPermissionAdapter.resolve() returns Optional.empty() when the adapter does not understand the command (next adapter is tried), or a PermissionResult with ResolutionType.UNKNOWN when it owns the command but cannot safely inspect its permission rule.
  • PermissionResult is a record carrying allowed, the ResolutionType that decided, the matchedPermission (evidence), and the resolved Command. A null command means the command is unknown → Allium's unknown-command message.
  • PermissionCandidates generates conventional permission strings (<plugin>.<module>.command.<action> etc.) from the owning plugin, command labels/aliases, and arguments. A GUI "open" action is only inferred when the owning module actually registers …command.open, so /ah-style commands work without every no-argument command looking like "open".
  • DefaultCommandPermissionResolver caches the registered-permission snapshot for 2 s and accepts additional adapters via its constructor — the extension point for CommandAPI, ACF, cloud, or other frameworks.

CommandManager behavior changes:

  • Command resolution (including namespaced plugin:command fallback) now happens inside the resolver; resolveCommandForPermissionCheck, hasPermissionForCommand, and getDerivedPluginCommandPermission were removed (~130 lines of heuristics).
  • With debug-mode: true, every resolution is logged: Permission resolution for /<cmd>: allowed=…, type=…, matched=… — making "why was this command blocked/allowed" answerable from the log.
  • The legacy aliases are retained as a final fallback: /fly passes with allium.fly or allium.tfly, /ping with allium.ping.
  • The direct net.milkbowl.vault.permission.Permission import was dropped; Vault permission setup remains reflective.

Tests: CommandPermissionAdaptersTest (445 lines) and PermissionCandidatesTest (126 lines) cover the adapter pipeline and candidate generation. JUnit Jupiter 5.12.2 and Surefire 3.5.2 were added to the build for this.

Vault Chat Proxy Fix

createChatProxy bailed out with null when the Vault Chat class was an abstract class instead of an interface (chatInterface.isInterface() false), which silently disabled Allium's chat formatter. It now returns the provider directly in that case — a JDK dynamic proxy is only possible for interfaces, but the concrete provider is already usable as-is.

Additionally, the "Vault Chat not available" message was upgraded from INFO to WARN and now explains the common cause: permission plugins like LuckPerms need chat: true in their config to provide chat services — Vault alone does not provide chat formatting.

Chat Message Deletion Fix

FormatChatListener used to build its own ChatMessageManager.ChatMessage and track it for every online player, in parallel with PacketChatTrackerImpl (packet capture). The listener-built entries were rendered from a different format template, so their plain text did not match the components stored by AlliumChannelManager. Content matching in deleteMessage then failed for those entries, they stayed undeleted, and the "deleted" message reappeared on resend. The listener-side tracking was removed; PacketChatTrackerImpl is now the single owner of per-player chat history.

Also in FormatChatListener, hover components are now wrapped explicitly with HoverEvent.showText(...) instead of passing the component directly to hoverEvent().

Nickname Handling

  • %allium_nickname% in chat format templates is now substituted with the player component (same treatment as <player>/<display_name>), in both FormatChatListener and AlliumChannelManager.
  • AlliumChannelManager no longer returns the raw stored nickname: an empty/null stored nickname falls back to player.getName(), and a present one is passed through getFormattedNickname(player, stored) so nickname formatting (colors, prefix rules) applies in channel messages.

/back Cache Invalidation (TP)

Teleporting a player now removes their entry from locationCache, so the next /back re-evaluates from lastLocation/the database instead of a stale cached location.

Adventure Component Builders

ComponentBuilder.build() calls were replaced with asComponent() in Help, Notes, and Warp (deprecation cleanup; behavior unchanged).

Oraxen → Nexo

TreeAxeItem, SpawnerChangerItem, and customitems.yml now reference nexo:tree_axe / nexo:spawner_changer item models instead of the oraxen: namespace.

Build

  • Version bumped 0.2.6a0.2.7a.
  • Added org.junit.jupiter:junit-jupiter:5.12.2 (test scope) and maven-surefire-plugin:3.5.2.

Файлы

Allium.jar(4.40 MiB)
Основной
Скачать

Метаданные

Канал релиза

Release

Номер версии

0.2.7a

Загрузчики

Bukkit
Folia
Paper
Purpur
Spigot

Версии игры

1.20–26.2

Загрузок

2

Дата публикации

19.07.2026

Загрузил

ID версии

Главная