Fix Herbalism double drops not working on beetroots
At BlockDropItemEvent time the broken block already reads as AIR, so deciding the beetroot drop tolerance from the live block type never matched BEETROOTS and the two legitimate beetroot drop materials tripped the tile-entity dupe heuristic. Read the type from the event's captured pre-break BlockState instead. (commit: 5a1a61c)
Fix error when a pet owned by a non-player deals damage
Tameable owners resolved in the damage handler are AnimalTamers and not necessarily players; the unchecked OfflinePlayer cast crashed the handler for plugin-provided owners. The tame handler fixed the same bug class earlier; this brings the damage path in line. (commit: 808bc55)
Fix error when non-players click or drag in furnace and brewing inventories
InventoryClickEvent and InventoryDragEvent report the viewer as a HumanEntity, and plugins can open container inventories for human-shaped entities that are not players. The click and drag handlers cast the viewer to Player unchecked and crashed on such viewers; they now ignore non-player viewers. (commit: cc7442b)
Fix localized skill commands rewriting arguments that repeat the skill name
The alias rewrite replaced every occurrence of the alias text in the command message, so arguments that repeated the alias (player names, search terms) were rewritten along with the command token. Only the leading command token is rewritten now. (commit: 7f3f5b4)
Fix error when a plugin-fired fish catch carries a non-item entity
CAUGHT_FISH normally carries an Item, but the event does not enforce the caught entity's type; the HIGH-priority handler cast it unchecked and crashed on plugin-fired events with other entity types. (commit: 4d2b088)
Fix splash saturation potions losing particle and icon visibility
The saturation splash workaround re-added the effect with the short PotionEffect constructor, which resets particle and icon visibility to the defaults; custom potions brewed to hide their particles started showing them after the splash. (commit: 81f5c55)
Clean up listener debug reporting and stale comments
Extract the duplicated PvP combat debug report in EntityListener into a shared helper, correct the entity explode handler name, and fix two comments that no longer matched the code (traveling-block cleanup timer cadence, piston retract direction). (commit: 1cad900)
Move buff-stripping inventory handlers off MONITOR priority
The inventory click and open handlers strip ability buffs from item stacks, which mutates item state; the MONITOR contract forbids that. They now run at HIGHEST like the other mutating handlers moved during the listener priority cleanup. (commit: 8fa27d3)
Fix error when adding levels to a child skill through the API
Child skills have no level entry of their own, so the read-then-modify in PlayerProfile#addLevels crashed on the missing entry before the child guard in modifySkill could run. Added levels now split evenly across the child's parent skills, matching how child skill XP and the offline ExperienceAPI level variants already behave. The addlevels command rejects child skills up front, so only API callers were affected. (commit: 7ea3d91)
Fix error reading XP requirements for offline players with the cumulative curve
With 'Experience_Formula.Cumulative_Curve' enabled, PlayerProfile resolved the power level through UserManager, which has no entry for offline-loaded profiles (offline /inspect, ExperienceAPI offline lookups) and crashed. The profile's own level sum now stands in when no online player is found; permission-aware filtering is impossible offline anyway. Also corrects the stale getLastLogin javadoc. (commit: e76d62c)
Compute the modified XP once in beginUnsharedXpGain instead of running the permission-heavy perk modifier twice per gain (which also sent the XP perk debug report to debug-mode players twice), and reuse the local player reference in logout instead of re-reading a field that is never null. (commit: 49ff833)
Fix error when another plugin reads raw XP for a child skill
Child skills store no XP entry of their own, so the raw XP read crashed on the missing entry. Zero is returned instead, matching getSkillXpLevel. In-repo callers filter child skills first; only plugins calling the profile API directly were affected. (commit: 43a5f94)
Fix player data changes made during an in-flight save being lost
The dirty flag was overwritten unconditionally once the database returned, so a change that landed while the async save was writing its copy was marked clean and skipped by later saves until the next unrelated change. The flag is now cleared before the copy is taken and only restored on failure, so concurrent changes re-mark the profile dirty and the next save picks them up. Answers the old TODO about synchronizing the copy: value races during the copy self-heal through the dirty flag, so no lock is needed. (commit: b249b4d)
Stop console spam when other plugins check skill names through the API
Unmatched skill name lookups logged an 'Invalid mcMMO skill' warning on every call, so plugins validating names through ExperienceAPI flooded the console. The message is now debug output shown only with Verbose_Logging. (commit: 2b85a6f)
Make the -s flag on XP commands silence the sender confirmation too
/addxp, /addlevels, and /mmoedit echoed 'has been modified' back to the sender even with -s, flooding the log for plugins that award XP by dispatching these commands from console. (commit: bb6a395)
Route McMMOPlayer addXp and addLevels through level up processing
Both wrote raw values into the profile, so plugins using them left skills over their XP threshold with no level ups, events, or XP bar updates. addXp now runs the normal XP gain path with the amount unmodified, and addLevels fires the level change events like the addlevels command. Internal callers that revert cancelled events or apply vampirism gains keep raw writes via the profile. (commit: df4cdce)