Dirty Effect Hack¶
Quick Start: Spice it up with twists.
What the warning means¶
Potion effects in JManhunt are owned by one shared ledger: each
modifier writes its own named entries through the pfx tags and
the engine merges every entry onto the player's live effects (see
Shared Effects). The engine remembers
the merged winners it last applied per player.
When another modifier edits a ledger-managed effect directly (an
effect command, another plugin, or a datapack) and the live
effect comes out stronger than the ledger holds (higher
amplifier, or longer remaining than the winner plus a small
tolerance), the engine's next refresh logs this once per player
per match:
Dirty Effect Hack detected for <name>: <effect> is stronger than
the ledger holds. Another modifier is editing effects directly;
switch it to the pfx tags:
https://jruk8.github.io/JManhunt/mods/dirty-effect-hack/
The engine then re-applies the merged winners, so the direct edit loses under vanilla merge rules whenever the ledger dose wins.
Missing effects never warn: milk, totems of removal, and rival clears are legitimate, and the next ledger mutation re-applies the merged view.
Why direct edits break¶
A modifier that fires a blind write only knows its own doses. Two
such modifiers overwrite each other, and any pfx user recomputes
from the ledger and silently wipes both. Through the ledger every
modifier keeps its own entry and all of them merge per effect,
with infinite entries always winning.
How to fix a flagged modifier¶
Replace the direct edit with ledger tags under one id per modifier
(the modifier's own name, via <id>, is a good id):
# Before: clobbers every other effect change.
- <run:effect give <p> minecraft:blindness 30 0>
# After: merges with every other entry.
- <pfx.set:<p>,<id>,[[blindness,0,30]]>
Use pfx.get to read the modifier's own entry ([] when unset),
pfx.duration to read the live seconds left for one effect under
one id (-1 runs forever, null when absent), and pfx.clear to
drop entries the modifier no longer needs. Modifiers that write
infinite doses should clear their own id in an ON_CLEANUP block
so the hold ends with the match even if the engine teardown is
what finally strips it.