Paper 26.1.2 fixed a bug where the player attack cooldown ticker was not
resetting at the correct point during melee hits. mcMMO relied on the old
(incorrect) order, reading the cooldown during the damage event, which
always returned near-zero after Paper's fix. Attack strength scale is
now back-derived from the raw event damage divided by the player's
GENERIC_ATTACK_DAMAGE attribute value and clamped to [0.0, 1.0].
AttributeMapper now survives test environments where Bukkit registries
are absent (catch Throwable in the registry reflection path).
Fixes#5287.
Nether_Wart_Block and Warped_Wart_Block both have woodcutting XP in
experience.yml AND are in the treeFellerDestructibleWhiteList. The
drop routing in dropTreeFellerLootFromBlocks used an if/else-if
structure, so blocks with woodcutting XP always took the first branch
and never reached the else-if where the KnockOnWood orb logic lived.
Fix: extract the orb spawning block into a standalone if-check that
runs after the drop routing, so it fires for any isNonWoodPartOfTree
block regardless of whether it also has woodcutting XP.
Fixes#5288
Warriorrrr's commit (fb6aebcaa) corrected the default potions.yml shipped
with the plugin (splash: 2500->3600, lingering: 3000->900), but existing
server installs still had the old incorrect values.
This adds a one-time UpgradeManager migration (FIX_TRICKY_TRIALS_SPLASH_POTION_DURATIONS)
that auto-patches existing potions.yml on first server startup after updating.
The migration only corrects exact-match bad values; user-customized durations
are intentionally left untouched. Absent potion keys are silently skipped.
- Add UpgradeType.FIX_TRICKY_TRIALS_SPLASH_POTION_DURATIONS
- Implement PotionConfig.fixTrickyTrialsPotionDurations() + patchTrickyTrialsDurations()
- Gate migration in PotionConfig.loadPotions() via shouldUpgrade()
- Add 13 unit tests covering all migration paths in PotionConfigTest
The old regex required a trailing [-_] after the version digits, which worked
for getBukkitVersion() strings (e.g. '1.21.4-R0.1-SNAPSHOT') but silently
failed on Spigot's Bukkit.getVersion() format ('git-Spigot-12345-abcdef
(MC: 1.21.4)') since '1.21.4)' has no trailing dash or underscore. Version
resolved to 0.0.0, causing Tricky Trials potions (isAtLeast 1.21.0 check)
to be incorrectly skipped on every Spigot server.
MinecraftGameVersionFactory now uses two patterns:
- Primary: extracts from the '(MC: X.Y.Z)' segment that CraftBukkit always
embeds in Bukkit.getVersion() — handles Spigot, old Paper, and Paper 26+
- Fallback: original regex for strings without '(MC: ...)' such as
getBukkitVersion()-style strings
Tests updated with @Nested classes covering both paths, including explicit
Spigot format cases and Paper 26+ versioning (26.1.2-60-b4682bf format).
Woodcutting (Harvest Lumber, Clean Cuts) and Excavation treasure drops
previously spawned items directly via world.dropItem(), bypassing
BlockDropItemEvent entirely. This made them invisible to Telekinesis-style
enchant plugins (ExcellentEnchants, EcoEnchants, etc.).
Woodcutting fix: processBonusDropCheck() now calls BlockUtils.markDropsAsBonus()
for normal breaks, routing bonus drops through the existing BlockDropItemEvent
metadata pipeline. Tree Feller retains the direct-spawn path since it sets
blocks to AIR without firing BlockDropItemEvent.
Excavation fix: treasure rolls are now performed inside onBlockDropItemEvent()
via ExcavationManager.rollAndCollectTreasureDrops(). The returned ItemStacks
are spawned and injected into event.getItems(), exposing them to the full
Bukkit event pipeline. GigaDrillBreaker's 3x roll count is preserved. The
old processExcavationBonusesOnBlock(treasure, location) path is kept as a
deprecated fallback for external API callers.