Перейти к содержимому
Mineforgian

Allium

A modern, secure Essentials solution

Загрузки
105
Подписчики
1
Обновлён
7 июля 2026 г.
Лицензия
GPL-3.0-only

Опубликован 5 апреля 2026 г.

Allium

Discord GitHub Issues Wiki CASTLED CODEX

Allium is a modern Essentials-style Paper plugin built for servers that want one cohesive core instead of a pile of loosely connected utility plugins.

It combines everyday player commands, staff tooling, moderation systems, economy utilities, advanced chat handling, creative-mode restrictions, Discord integration, and custom world systems into a single package that is designed to feel practical on a real server.

If you run a survival server, a semi-vanilla community, or a staff-heavy admin environment and keep finding yourself thinking “this should already be built in”, Allium is aimed directly at that problem.

Why Allium

  • One plugin for the core systems most servers actually need
  • Strong admin and moderation tooling, not just player conveniences
  • Modern integrations with Vault, PlaceholderAPI, LuckPerms, DiscordSRV, PacketEvents, Oraxen, and Floodgate
  • Built around real server-owner workflows: hiding commands, creative auditing, chat cleanup, ticket/escalation style tooling, timed fly, vouchers, utility items, and more

Feature Highlights

Core player utilities

  • Homes, bed homes, warps, spawn, /back, offline location tracking, and full teleport request flow
  • Private messages, reply, mail, social spy, notes, and /whois
  • Economy support with balances, payments, cheques, and XP vouchers
  • Utility commands like /heal, /feed, /god, /fly, /nv, /speed, /trash, /more, /itemdb, /skull

Advanced item and reward systems

  • Flexible /give and /i handling
  • Dialog-based /rename, /lore, and nickname editing
  • Voucher items with redeem commands and weighted permission grants
  • Cheques and XP bottles as redeemable item-backed value
  • Spawner core items and spawner-crafting support

Staff and admin tooling

  • Freeze, handcuffs, vanish, creative controls, invsee, ender chest access, and detailed player inspection
  • /delmsg chat moderation with resend support and Discord mirror cleanup
  • Command/plugin hiding via hide.yml
  • Group-based hidden command inheritance with LuckPerms-aware parent support
  • Escalation-ready admin workflows and offline state tracking

Chat system

  • Configurable channel system with built-in global and staff chat
  • Discord-linked channel routing
  • Word/phrase filter with token, phrase, substring, and regex modes
  • Spam blocker with repeated-message detection and normalization
  • Hover/click formatting, placeholder support, and moderation overlays

Server protection and creative controls

  • Creative Manager with per-action permissions for place, break, use, interact, drop, pickup, spawn, and inventory behavior
  • Creative blacklists for blocks and entities
  • Command hiding and tab completion filtering
  • Anti-alt / security-oriented listener support

World and custom content systems

  • Integrated custom ore generation for Oraxen ores
  • Pregeneration command with ore placement support
  • Oraxen custom smelting hooks
  • Note block / custom block protection helpers
  • Creeper explosion regeneration and related world safety logic

Integrations

Allium is designed to work well with common modern server stacks.

  • Vault
  • LuckPerms
  • PlaceholderAPI
  • DiscordSRV
  • PacketEvents
  • Oraxen
  • Floodgate
  • mcMMO

Most integrations are soft dependencies, so you can run a smaller setup and still use the rest of the plugin.

Good Fit For

  • Survival and SMP servers that want a stronger core plugin
  • Servers replacing a pile of Essentials-style utilities with one system
  • Staff teams that need moderation, visibility control, and audit-friendly tools
  • Servers using DiscordSRV, PlaceholderAPI, LuckPerms, and custom content plugins

Quick Examples

  • Give staff their own live in-game + Discord-linked staff chat
  • Hide /plugins, /version, and sensitive tab-completes from normal players
  • Let players use temporary fly time without permanent fly permission
  • Turn XP, money, or perks into redeemable items
  • Run /delmsg and clean up moderated chat quickly
  • Generate custom silver/galena ores directly in world generation

Installation Overview

  1. Install Allium on a Paper server.
  2. Add Vault and LuckPerms if you want economy/chat/group integration.
  3. Add PlaceholderAPI if you want placeholder-driven formatting.
  4. Add DiscordSRV if you want Discord-linked channels and staff relay.
  5. Add PacketEvents if you want the best chat resend/deletion behavior.
  6. Review config.yml, lang.yml, hide.yml, and the chat/ module files.

Documentation

For usage instructions, see the official Allium documentation.

Current Direction

Allium is actively growing beyond a traditional Essentials replacement. The current focus is on:

  • better chat moderation and channel systems
  • stronger admin workflows
  • smoother Discord integration
  • deeper custom content/world integration
  • keeping one coherent core instead of fragmenting into many separate plugins

Ченджлог

0.2.6aРелиз26.1.1, 26.1.2, 26.2 · 7 июля 2026 г.

Allium v0.2.6a

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

Highlights

  • Paper Brigadier compatibilityCommandManager now correctly handles commands registered via Paper's LifecycleEvents.COMMANDS (e.g., AbyssalLib's CommandBus, custom Brigadier dispatcher commands). These commands appear as VanillaCommandWrapper in the command map, whose testPermissionSilent() can false-negative. Allium now allows these commands through and defers permission evaluation to the server's native Brigadier dispatch.
  • Derived permission scoped to Allium-owning plugins only — The legacy heuristic that produced synthetic permissions like <pluginName>.<commandName> is now only applied to commands owned by Allium itself. For all other plugins — whether PluginCommand, VanillaCommandWrapper, or custom wrappers — Allium trusts the command's native permission system.

Technical Details

Problem

Commands registered through Paper's modern LifecycleEvents.COMMANDS API (used by AbyssalLib's CommandBus, among others) do not go through Bukkit's plugin.yml command registration. Instead, they register LiteralArgumentBuilder<CommandSourceStack> nodes directly into Mojang's Brigadier CommandDispatcher.

Paper wraps these dispatcher-only nodes in VanillaCommandWrapper (org.bukkit.craftbukkit.command.VanillaCommandWrapper) so they appear in SimpleCommandMap.knownCommands for Bukkit API compatibility. However, VanillaCommandWrapper.testPermissionSilent() does not reliably evaluate the underlying Brigadier node's requires() predicates, often returning false even when the player holds the correct permission.

This caused Allium's CommandManager to block all such commands and display the Allium "no-permission" message, even when the command's native permission system would have allowed execution.

Attempted Fixes (Rejected)

  1. Class name matching (className.contains("Brigadier") || className.contains("Wrapper")) — fragile, case-sensitive, and misses VanillaCommandWrapper in the general case since the wrapper extends Command/PluginCommand via different paths depending on the Paper version.
  2. PluginIdentifiableCommand instanceof check — Paper's MinecraftCommandMap$CommandWrapper may implement PluginIdentifiableCommand with a null plugin, making the check useless.
  3. PluginCommand instanceof check — some Paper wrapper variants extend PluginCommand directly, so negating PluginCommand doesn't reliably capture dispatcher-only commands.

Actual Fix

The fix uses a class-name-exact check for VanillaCommandWrapper as the first gate in hasPermissionForCommand():

if (className.contains("VanillaCommandWrapper")) {
    return true;
}

This immediately allows all Brigadier-dispatcher-registered commands and defers permission evaluation to the server's native dispatch (which correctly evaluates the CommandNode.canUse() predicates at execution time).

For PluginCommand instances, the revised logic is:

  1. Explicit permission setcommand.getPermission() is non-null → testPermissionSilent already checked it, allow.
  2. Derived permission — only computed for commands whose PluginIdentifiableCommand.getPlugin() returns "Allium". The derived string is allium.<baseCommand>.
  3. All other commands (PluginCommand from other plugins, vanilla commands with matching Bukkit wrappers) — trust testPermissionSilent.

getPluginForCommand Fallback Fix

The fallback in getPluginForCommand previously returned commandName.toLowerCase() when no plugin could be identified, causing the derived permission to be <commandName>.<commandName> (e.g., relique.relique). This is now null, which propagates through getDerivedPluginCommandPermission as null — treated as "no permission required".

Support and Feedback

Issues: https://github.com/castledking/Allium/issues Wiki: https://github.com/castledking/Allium/wiki Discord: https://discord.com/invite/pCKdCX6nYr Website: https://castled.codes/

0.2.5aРелиз26.1.1, 26.1.2, 26.2 · 6 июля 2026 г.

Allium v0.2.5a

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

Highlights

  • Translation probe config corruption fixedapplyBundledDefaults no longer calls config.save(), preventing the old JAR's defaults from being written to disk on every restart. A new seedMissingProbeConfig() method writes the translation-probe section to disk only when the file actually lacks it (using contains(path, true) to ignore in-memory defaults).
  • Hardcoded probe check fallbackloadChecks() now cascades: disk config → bundled resource → createDefaultChecks() with 16 hardcoded checks (meteor + 14 IPN + 2 libIPN). This ensures the probe always has checks even when both the disk config and old JAR resource lack the section.
  • Probe enabled fallbackisEnabled() now falls back to root enabled, so the probe registers even when the translation-probe section is entirely absent from the config file.
  • Stealthier probeCloseWindow is sent immediately (no 2-tick delay, sign GUI never renders), and the sign position is Y - 30 below the player (out of view). Zero visual flicker.
  • /allium modguard reload — New command unregisters the probe, reloads the config from disk, and re-registers. Requires allium.admin.

Bug Fixes

Bug Root Cause Fix
Config file overwritten on every restart applyBundledDefaults called config.save() with copyDefaults(true), writing old JAR defaults back to disk Removed config.save() and copyDefaults(true) from applyBundledDefaults
translation-probe section never persisted to disk seedMissingProbeConfig used config.contains("translation-probe") which returned true from defaults set by applyBundledDefaults — even though the file lacked the section Changed to config.contains("translation-probe", true) to ignore defaults and check only the file
Probe has no checks after config corruption loadChecks() had no fallback when both disk config and bundled resource lacked the checks section Added createDefaultChecks() with 16 hardcoded checks as final fallback
Probe doesn't fire when translation-probe section is missing registerTranslationProbe() and isEnabled() returned false for config.getBoolean("translation-probe.enabled", false) when the section was absent Changed fallback to config.getBoolean("translation-probe.enabled", config.getBoolean("enabled", false))
Probe delay too slow (3s) and timeout too long (4s) Config defaults for delay-ticks (60) and timeout-ticks (80) were unnecessarily conservative Changed to 10 ticks (0.5s) and 30 ticks (1.5s)
Sign GUI visible to player on join CloseWindow was sent after a 2-tick delay, giving the client time to render the sign CloseWindow sent immediately in the same packet batch; sign placed 30 blocks below player
No reload command — required full restart for config changes No implementation Added /allium modguard reload which calls ModGuardManager.reload()

Files Changed (4)

File Change
managers/security/ModGuardManager.java applyBundledDefaults no longer saves to disk; added seedMissingProbeConfig() with contains(path, true) guard; added reload() static method; added /allium modguard reload dispatcher
managers/security/ModGuardTranslationProbe.java Added createDefaultChecks() (16 hardcoded checks); loadChecks() now cascades config → bundled → hardcoded; isEnabled() falls back to root enabled; CloseWindow immediate; sign Y -30; delay-ticks 10, timeout-ticks 30
modguard/config.yml Cleaned up: removed debug, regex-matching, case-sensitive, banned-mods, allowed-mods; added translation-probe section with all 16 checks with require-corroboration-for-kick: false
commands/Core.java Added handleModGuardCommand() for /allium modguard reload

Technical Details

Config Persistence Chain

The old code had two bugs forming a corruption loop:

  1. applyBundledDefaults called config.save() with the old JAR's bundled config (no translation-probe section), overwriting user changes on every restart
  2. Even after removing config.save(), seedMissingProbeConfig checked config.contains("translation-probe") — but applyBundledDefaults had already set the NEW bundled resource as defaults, which DO contain the section. So contains() returned true from defaults and seedMissingProbeConfig returned early without persisting

Fix: seedMissingProbeConfig now uses config.contains("translation-probe", true) to skip default-only matches. It also writes the full 16-check section to disk when absent, so subsequent restarts load it directly from the file.

Probe Check Fallback Chain

loadChecks() now follows this order:

  1. config().getConfigurationSection("translation-probe.checks") — reads from the in-memory config (loaded from disk or defaults)
  2. loadBundledChecks() — reads from the JAR resource (modguard/config.yml) and copies checks into the in-memory config
  3. createDefaultChecks() — 16 hardcoded checks: meteor + 14 IPN (key.inventoryprofiles.*) + 2 libIPN

This ensures the probe always has checks regardless of which JAR version is deployed or whether the config file contains the section.

Support and Feedback

Issues: https://github.com/castledking/Allium/issues Wiki: https://github.com/castledking/Allium/wiki Discord: https://discord.com/invite/pCKdCX6nYr Website: https://castled.codes/

0.2.4aРелиз26.1.1, 26.1.2, 26.2 · 30 июня 2026 г.

Allium v0.2.4a

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

Highlights

  • Vault softdepend crash fixed — Allium no longer crashes at startup when Vault is absent. All Vault-typed fields and method signatures were changed to Object, with casts at call sites. VaultEconomyProvider is only created when Vault's Economy class is actually loadable. The FormatChatListener is skipped entirely when Vault Chat isn't available.
  • PacketEvents softdepend crash fixed — Allium no longer crashes at startup when PacketEvents is absent. The Glow command and GlowListener are guarded behind isPacketEventsAvailable(), and the glowCommand field was relaxed from Glow to Object to prevent class loading.
  • CrowBar 128-block radius limit removed — Added shouldBeVisibleIgnoreDistance to PartyManager so players beyond 128 blocks remain visible on the locator bar, with only same-world and forced-visibility checks applied.
  • NPC locator bar flash fixedPartyManager.updatePlayerVisibility now checks viewer.canSee(target) before calling showPlayer, preventing NPC info packets from being resent every 5 ticks when the NPC is already visible.

Bug Fixes

Bug Root Cause Fix
Plugin fails to enable without Vault Vault types in field/method signatures cause NoClassDefFoundError during class loading; new VaultEconomyProvider runs before Vault availability check Changed Vault-typed fields/methods to Object; guarded VaultEconomyProvider creation; skipped FormatChatListener when vaultChat == null
Plugin fails to enable without PacketEvents Glow class references PacketEvents types in method signatures; new Glow(this) at unconditional line 1524 forces class loading Guarded Glow/GlowListener creation behind isPacketEventsAvailable(); changed glowCommand field to Object
Players beyond 128 blocks hidden on CrowBar shouldBeVisible applies distance filtering which limits range to 128 blocks Added shouldBeVisibleIgnoreDistance that skips distance check while keeping same-world and visibility overrides
NPCs flash on locator bar every 5 ticks updatePlayerVisibility calls showPlayer unconditionally every interval Guarded showPlayer behind viewer.canSee(target)

Files Changed (8)

File Change
PluginStart.java Changed Vault fields/methods to Object; guarded VaultEconomyProvider and FormatChatListener creation; guarded Glow/GlowListener behind isPacketEventsAvailable()
commands/Glow.java No structural change (guarded at call site)
DB/PermissionCache.java getVaultPermission returns Object
listeners/security/CommandManager.java vaultPermission field / setupVaultPermission now Object
listeners/security/MaintenanceManager.java perms field / constructor param now Object
managers/core/PartyManager.java Added shouldBeVisibleIgnoreDistance; canSee guard in updatePlayerVisibility
packetevents/CrowBarDataSender.java Uses shouldBeVisibleIgnoreDistance instead of shouldBeVisible
listeners/security/ConnectionManager.java vaultChat null guard in reloadChatFormatter

Technical Details

Vault Class Loading Fix

Paper 1.21+'s PluginClassLoader eagerly resolves type references during class definition. Having Vault types in field declarations or method return types causes NoClassDefFoundError even when the code path never executes. Fix: all Vault-typed fields and return types are now Object, with casts at every call site.

PacketEvents Class Loading Fix

Same mechanism as Vault — PacketEvents types in Glow's method signatures crash class loading. Glow is now only instantiated when isPacketEventsAvailable() returns true, so the class is never loaded on servers without PacketEvents.

Support and Feedback

Issues: https://github.com/castledking/Allium/issues Wiki: https://github.com/castledking/Allium/wiki Discord: https://discord.com/invite/pCKdCX6nYr Website: https://castled.codes/

0.2.3aРелиз26.1.1, 26.1.2, 26.2 · 29 июня 2026 г.

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

Highlights

  • CanvasMC 26.2 support — Migrated from Paper API to Canvas API (io.canvasmc.canvas:canvas-api). Canvas is a Folia fork targeting Minecraft 26.2 (build 835). All scheduling now goes through the new SchedulerAdapter in the codes.castled.allium.scheduler package, which properly handles Canvas's regionized threading model.
  • New SchedulerAdapter — Complete rewrite of the scheduling layer. The old util/SchedulerAdapter.java (587 lines of reflection-heavy Folia detection) is replaced by a clean 426-line scheduler/SchedulerAdapter.java with a dedicated TaskHandle abstraction. The old class is kept as a deprecated thin wrapper delegating to the new one, ensuring backward compatibility.
  • Tab completion API — New AlliumTabCompletionsEvent + AlliumTabCompletionsListener that populate tab completions with all online non-vanished players when PartyManager is enabled. Other plugins can fire this event to get Allium-aware player name suggestions.
  • Vault initialization guard — Fixed a race condition where registerVaultDependentListeners() could be called multiple times if Vault initialized successfully and then the retry timer fired again. Added a registered boolean flag to ensure one-time registration.
  • FAWE removed — FastAsyncWorldEdit dependency and repositories dropped from pom.xml. No longer a soft dependency.

Minecraft Version Support

Version Status
26.2 (Canvas build 835) Primary target
26.2 (Folia) Supported
1.21.x (Paper/Spigot) Supported via fallback

API / Dependency Changes

  • pom.xml: io.papermc.paper:paper-api replaced with io.canvasmc.canvas:canvas-api
  • pom.xml: <paper.version> bumped from 26.2.build.37-alpha to 26.2.build.835-alpha
  • pom.xml: Added canvasmc-releases and canvasmc-snapshots repositories
  • pom.xml: Removed FastAsyncWorldEdit-Core dependency
  • pom.xml: Removed IntellectualSites repositories
  • plugin.yml: Removed FastAsyncWorldEdit and WorldEdit from softdepend

New Files

File Description
scheduler/SchedulerAdapter.java Full Folia/Canvas scheduling adapter with global, async, entity, and location scheduling
scheduler/TaskHandle.java Lightweight abstraction over BukkitTask and Folia ScheduledTask
events/AlliumTabCompletionsEvent.java Custom event for populating player name tab completions
listeners/AlliumTabCompletionsListener.java Handles the event — returns all online non-vanished players when PartyManager is enabled

SchedulerAdapter API

The new codes.castled.allium.scheduler.SchedulerAdapter provides:

// Global (main thread equivalent)
SchedulerAdapter.runGlobal(plugin, runnable)
SchedulerAdapter.runLaterGlobal(plugin, runnable, delayTicks)
SchedulerAdapter.runRepeatingGlobal(plugin, runnable, delayTicks, periodTicks)

// Async
SchedulerAdapter.runAsyncNow(plugin, runnable)
SchedulerAdapter.runAsyncLater(plugin, runnable, delayTicks)
SchedulerAdapter.runAsyncRepeating(plugin, runnable, delayTicks, periodTicks)

// Entity (Folia entity scheduler, Bukkit fallback)
SchedulerAdapter.runEntity(plugin, entity, runnable, retired)
SchedulerAdapter.runLaterEntity(plugin, entity, runnable, delayTicks)
SchedulerAdapter.runEntityRepeating(plugin, entity, runnable, retired, delayTicks, periodTicks)

// Location (Folia region scheduler, Bukkit fallback)
SchedulerAdapter.runAtLocation(plugin, location, runnable)
SchedulerAdapter.runAtLocationLater(plugin, location, runnable, delayTicks)
SchedulerAdapter.runAtLocationRepeating(plugin, location, runnable, delayTicks, periodTicks)

// Utility
SchedulerAdapter.cancelTasks(plugin)
SchedulerAdapter.isFolia()

All methods return codes.castled.allium.scheduler.TaskHandle which wraps both BukkitTask and Folia's ScheduledTask.

Deprecated API

codes.castled.allium.util.SchedulerAdapter is now a deprecated wrapper. All methods delegate to the new codes.castled.allium.scheduler.SchedulerAdapter. Existing code continues to work but should be migrated:

Old (util) New (scheduler)
run(task) runGlobal(plugin, task)
runLater(task, delay) runLaterGlobal(plugin, task, delay)
runTimer(task, delay, period) runRepeatingGlobal(plugin, task, delay, period)
runAsync(task) runAsyncNow(plugin, task)
runLaterAsync(task, delay) runAsyncLater(plugin, task, delay)
runAtEntity(entity, task) runEntity(plugin, entity, task, null)
runAtEntityLater(entity, task, delay) runLaterEntity(plugin, entity, task, delay)

Files Changed (31)

File Change
pom.xml Canvas API, build 835, removed FAWE, added Canvas repos
plugin.yml Removed FAWE/WorldEdit softdepend
scheduler/SchedulerAdapter.java New — full scheduling adapter
scheduler/TaskHandle.java New — task handle abstraction
events/AlliumTabCompletionsEvent.java New — tab completion event
listeners/AlliumTabCompletionsListener.java New — tab completion handler
util/SchedulerAdapter.java Rewritten as deprecated wrapper (~500 lines removed)
PluginStart.java Vault init guard, SchedulerAdapter migration for channel/Discord retry
Core.java Bukkit.getScheduler() calls replaced with SchedulerAdapter
PregenCommand.java SchedulerAdapter for async completion callback
StaffChatCommand.java SchedulerAdapter for channel switch
InventoryManager.java SchedulerAdapter for autosave
FormatChatListener.java SchedulerAdapter for phase renderer
StaffChatListener.java SchedulerAdapter for message redirect
WolfBehaviorListener.java SchedulerAdapter for delayed task
CommandManager.java SchedulerAdapter migration
ConnectionManager.java SchedulerAdapter migration, significant refactor
FreecamDetector.java SchedulerAdapter migration
HandcuffsListener.java SchedulerAdapter migration
IPNDetector.java SchedulerAdapter migration
ModDetectionListener.java SchedulerAdapter migration
VanishListener.java SchedulerAdapter migration
FaweActivityListener.java SchedulerAdapter migration, FAWE removal
OreGenerationListener.java SchedulerAdapter migration
AlliumChannelManager.java SchedulerAdapter migration
DiscordSrvMessageBridge.java SchedulerAdapter migration
GradientNameManager.java SchedulerAdapter migration
ModGuardManager.java SchedulerAdapter migration
ModGuardTranslationProbe.java SchedulerAdapter migration
OreGenerationManager.java SchedulerAdapter migration
CrowBarDataSender.java SchedulerAdapter migration

Technical Details

Scheduler Detection

Folia/Canvas detection uses Bukkit.getServer().getClass().getMethods() to find getGlobalRegionScheduler — more reliable than string-matching server name/version. The detection result is cached in a static final boolean at class load time.

TaskHandle

Wraps either a BukkitTask (Paper/Spigot path) or a raw Folia ScheduledTask object (accessed via reflection for cancel). Thread-safe cancellation via AtomicBoolean. The isScheduled() method returns best-effort status.

Vault Initialization Fix

Previously, if initializeVault() succeeded on attempt N but the timer tick was already queued, registerVaultDependentListeners() could fire twice. The fix adds a registered[] boolean flag checked before each registration call, ensuring idempotency.

Support and Feedback

Issues: https://github.com/castledking/Allium/issues Wiki: https://github.com/castledking/Allium/wiki Discord: https://discord.com/invite/pCKdCX6nYr Website: https://castled.codes/

0.2.2aРелиз26.1, 26.1.1, 26.1.2 · 21 июня 2026 г.

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

Highlights

  • Glow command — New /glow command for per-player colored glow outlines using PacketEvents virtual team packets. Supports all 16 vanilla colors, rainbow cycling, and per-color permissions. No scoreboard pollution — teams are sent directly to viewers and never registered on any Bukkit scoreboard.
  • Join/Quit message permissions — Permission-based join/quit message formats via allium.join_message.<id> and allium.quit_message.<id>. Set custom formats with LuckPerms metadata.
  • Chat system rewriteChatMessageManager, FormatChatListener, and PacketChatTrackerImpl significantly reworked for better PacketEvents integration and staff moderation features.
  • Flight restoration refactorFlightRestoration rewritten for improved Folia compatibility and reliability.
  • Command managementCommandManager now caches the server's known commands map with a 2-second TTL, eliminating repeated reflection calls. Help command caches available commands per-player with a 3-second TTL.
  • TP companion teleportation — Pet/entity teleport-on-TP moved from TP listener to dedicated TeleportBackListener for cleaner separation.
  • Inventory snapshot optimizationInventoryManager.saveSnapshot() simplified to run directly on the calling thread instead of through SchedulerAdapter.run().

New Commands

Command Description Permission
/glow <color> [player] Set glow color (e.g. /glow red, /glow dark_aqua) allium.glow + allium.glow.<color>
/glow rainbow [player] Enable rainbow cycling glow allium.glow.rainbow
/glow off [player] Remove glow effect allium.glow / allium.glow.others

New Permissions

Permission Description Default
allium.glow Base glow permission (grants all 16 color sub-permissions) op
allium.glow.<color> Per-color (e.g. allium.glow.red, allium.glow.blue) via parent
allium.glow.rainbow Rainbow glow mode op
allium.glow.others Target other players op
allium.join_message.<id> Custom join message format (value from LP metadata)
allium.quit_message.<id> Custom quit message format (value from LP metadata)
allium.join_message.* Wildcard — grants all join message formats staff
allium.quit_message.* Wildcard — grants all quit message formats staff

New Config

join-and-quit-messages:
  join:
    enabled: true
    format: "&e%name% &7has joined the server"
  quit:
    enabled: true
    format: "&e%name% &7has left the server"
  broadcast-scope: server  # server, world, or global

Setting Custom Join/Quit Messages with LuckPerms

Set a permission with a metadata value on a player:

/lp user <player> meta set allium.join_message.vip.a "rift in the universe has spawned %player%"
/lp user <player> meta set allium.quit_message.vip.a "%player% has left through a rift"

Supported placeholders: %name% (display name, respects /nick), %player% (real name), %prefix% (Vault prefix), %suffix% (Vault suffix).

The first matching permission (alphabetical by suffix) is used. If no permission metadata is found, the default config format is used.

Technical Details

Glow

  • Uses PacketEvents WrapperPlayServerTeams with TeamMode.CREATE (includes both team info and player entries in one packet)
  • TeamMode.UPDATE for rainbow color changes, TeamMode.REMOVE for cleanup
  • Packets sent to all online players including the target (the client needs to receive the team packet to render the colored outline)
  • No Bukkit.getScoreboardManager() usage — completely virtual
  • Folia-safe: no region-scheduled tasks needed

Join/Quit Messages

  • Handled via standard PlayerJoinEvent / PlayerQuitEvent (main thread on both Bukkit and Folia)
  • Permission metadata read through Vault Chat's getPlayerInfoString()
  • Falls back to default config format if no permission match found
  • Vanish check: vanished players don't show join/quit messages

Chat System

  • ChatMessageManager rewritten with improved message storage and retrieval
  • PacketChatTrackerImpl updated for better PacketEvents 2.11.1 compatibility
  • FormatChatListener significantly expanded with new formatting options

SchedulerAdapter

  • All scheduled tasks route through SchedulerAdapter which auto-detects Folia
  • Folia path: uses EntityScheduler for entity-specific tasks, GlobalRegionScheduler for global tasks
  • Bukkit path: uses standard BukkitScheduler
  • No raw Bukkit.getScheduler() calls in new code

Files Changed (22)

File Change
PluginStart.java Glow command + listener registration, glow field
Glow.java New — /glow command with PacketEvents team packets
GlowListener.java New — cleanup on player quit
JoinQuitMessages.java New — permission-based join/quit messages
ChatMessageManager.java Rewritten — message storage, tracking, moderation
FormatChatListener.java Major rewrite — chat formatting, hover, click events
PacketChatTrackerImpl.java Major rewrite — PacketEvents 2.11.1 integration
FlightRestoration.java Major rewrite — Folia-safe flight state management
CommandManager.java Known commands caching, getCachedKnownCommands() API
Help.java Available commands caching, uses CommandManager cache
`TeleportBackListener.java** Extracted from TP — pet/entity companion teleport
TP.java Removed inline teleport listener, now delegates
InventoryManager.java Simplified snapshot saving, removed SchedulerAdapter wrapper
AlliumPlaceholder.java Import cleanup
GeneralPlaceholder.java Import cleanup
TFlyManager.java Import cleanup, formatting
SpawnerChangerManager.java Minor cleanup
config.yml New join-and-quit-messages section
lang.yml New glow.* message keys
plugin.yml New glow command, permission definitions
pom.xml Paper version 1.21.8

Support and Feedback

Issues: https://github.com/castledking/Allium/issues Wiki: https://github.com/castledking/Allium/wiki Discord: https://discord.com/invite/pCKdCX6nYr Website: https://castled.codes/

0.2.1aРелиз26.1, 26.1.1, 26.1.2 · 1 июня 2026 г.

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

Highlights

  • CrowBar same-world payloads — CrowBar player data is now built per recipient and only includes players in the recipient's current world.
  • CrowBar quit refresh — Sends an immediate snapshot when a player quits so CrowBar clients can remove stale dots and name tags without waiting for expiry.
  • CrowBar join/world snapshots — Sends delayed targeted snapshots after joins and world changes so reconnecting CrowBar clients get nearby player positions before movement updates.
  • NPC filtering — Citizens NPCs are excluded from CrowBar player-data payloads.

Support and Feedback

Issues: https://github.com/castledking/Allium/issues Wiki: https://github.com/castledking/Allium/wiki Discord: https://discord.com/invite/pCKdCX6nYr Website: https://castled.codes/

0.2.0aРелиз26.1, 26.1.1, 26.1.2 · 1 июня 2026 г.

Allium v0.2.0a

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

Highlights

  • CrowBarDataSender NPC Filter — Prevents NPCs from Citizens from having their data sent to CrowBar

Support and Feedback

Issues: https://github.com/castledking/Allium/issues Wiki: https://github.com/castledking/Allium/wiki Discord: https://discord.com/invite/pCKdCX6nYr Website: https://castled.codes/

0.1.9aРелиз26.1, 26.1.1, 26.1.2 · 31 мая 2026 г.

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

Highlights

  • Citizens NPC body visibility fixed — Allium no longer strips unlisted PLAYER_INFO_UPDATE entries for unknown player UUIDs. Citizens uses those packets to send player-NPC profile/skin data while keeping NPCs out of the tab list; removing them made the client fail to render NPC bodies. NPCs are also exempted from PartyManager body visibility hiding.
  • CrowBarDataSender UUID fix — Fixed a bug where the loop variable uuid (a String) was being used instead of player.getUniqueId(), causing all CrowBar clients to receive the same UUID for every player entry.

What's Fixed

  • Citizens NPC bodies no longer invisible — The confirmed fix is in the PacketEvents tab-list interceptor: unknown/unlisted player-info entries now pass through unchanged instead of being removed. This preserves Citizens' spawn/profile handshake for player-type NPCs. Allium also detects Citizens NPC metadata live and skips hidePlayer() visibility management for those NPC entities.
  • CrowBarDataSender player UUID — Each player object now correctly calls player.getUniqueId().toString(). Previously, a stray uuid variable from an unrelated context was serialized for every entry, meaning all players appeared as the same entity on the CrowBar locator bar.

Internal

  • .release/discord-updater-webhook.ymlmessage_id updated for the current Discord release post.
  • .release/src/spigot-release.js — Modrinth download link corrected.

Requirements

  • Minecraft 1.21.11
  • Fabric Loader 0.18.4 or newer
  • Fabric API 0.141.4 or newer
  • Java 21

Комментарии

Загружаем…