Список изменений
[4.0] — 2026-03-12 — Legendary Ability Audit & Fixes
🐛 Bug Fixes — Legendary Abilities
-
🛡️ ReinforcedElytra never activated (Critical) —
performSneak()called!checkCooldown(player)meaning the ability only "activated" while on cooldown and did nothing when ready. Fixed by removing the negation:if (checkCooldown(player)) return; -
💬 DeathNote spammed chat 20×/sec (Major) —
showProgress()calledplayer.sendMessage()every tick. With the passive task running at 1-tick period, this sent 20 messages per second to chat, making the chat completely unusable while holding the item. Fixed by replacingsendMessage()withsendActionBar()and rendering a proper progress bar (colored block chars + target name). -
💊 FountainOfYouth healed all online players (Major) — The heal loop iterated over
Bukkit.getOnlinePlayers()instead of the arena player list. This meant the item healed players in other arenas, spectators, and any player on the server within range regardless of game state. Fixed by iterating overarena.getPlayers()with a team-fire check. -
💀 HadesHelm applied Wither without checking if helm was equipped (Major) —
performDamaged()added Wither to any attacker when the player took damage, even if they had already unequipped the helm during combat. Fixed by addingAbilityManager.isAbilityItem(player.getInventory().getHelmet(), "hades_helm")guard at the top of the method. -
👢 HermesBoots cancelled fall damage without checking if boots were worn (Major) — Same class of bug as HadesHelm:
performDamaged()suppressed all fall damage even after the player swapped out the boots. Fixed by guarding withisAbilityItem(player.getInventory().getBoots(), "hermes_boots"). -
🔨 MidasSword used deprecated
AttributeModifierconstructor (Major) — The oldAttributeModifier(UUID, String, double, Operation, EquipmentSlot)constructor is removed in Paper 1.21+. Replaced with the currentAttributeModifier(NamespacedKey, double, Operation, EquipmentSlotGroup)API; modifier key stored as aNamespacedKeyfield to allow stable removal on each upgrade. -
🌿 EmeraldBlade used deprecated
AttributeModifierconstructor (Major) — Same issue as MidasSword.updateItemData()callednew AttributeModifier(UUID.randomUUID(), "emerald_blade_damage", …). This also meant a fresh random UUID was generated on every deposit, so the old modifier was never removed, stacking damage indefinitely. Fixed with a stableNamespacedKeyfield (emerald_blade_damage) and the new constructor. -
🩸 CrimsonChainsword leaked
revvedUp/bleedingTargetsmaps on disconnect/death (Minor) — Neither map was cleaned up when a player left or died, causing unbounded memory growth over long sessions. AddedperformQuit()andperformDeath()overrides that remove the player's entries from both maps.

