Skip to content

fix: cancel denied magic-block break early to stop Jobs reward exploit (#534)#535

Merged
tastybento merged 2 commits into
developfrom
fix/jobs-magic-block-priority-534
Jul 10, 2026
Merged

fix: cancel denied magic-block break early to stop Jobs reward exploit (#534)#535
tastybento merged 2 commits into
developfrom
fix/jobs-magic-block-priority-534

Conversation

@tastybento

Copy link
Copy Markdown
Member

Problem

Fixes #534 — Jobs Reborn awards infinite rewards when a player mines the magic block on an island where the MAGIC_BLOCK flag denies them, despite general block-breaking being allowed.

Root cause

An event-priority race:

  • Jobs Reborn (JobsPaymentListener) pays out from its BlockBreakEvent handler at @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true).
  • AOneBlock (BlockListener.onBlockBreak) also ran at HIGHEST, ignoreCancelled = true, and only there did it call checkIsland(...MAGIC_BLOCK), whose deny path cancels the break.

ignoreCancelled = true means "skip me if the event is already cancelled." Within a single priority slot, Bukkit fires handlers in plugin-registration order, which is nondeterministic across setups. When Jobs' HIGHEST handler ran before AOneBlock's, the event wasn't cancelled yet, so Jobs paid the reward. AOneBlock then cancelled the break — and since the magic block respawns on a cancelled break, a player lacking the MAGIC_BLOCK flag could mine it endlessly for infinite Jobs money.

Fix

Add a dedicated early-deny handler that performs the MAGIC_BLOCK flag check at EventPriority.LOWEST:

@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onBlockBreakDeny(final BlockBreakEvent e) {
    if (!addon.inWorld(e.getBlock().getWorld())) return;
    Location l = e.getBlock().getLocation();
    addon.getIslands().getIslandAt(l).filter(i -> l.equals(i.getCenter()))
            .ifPresent(i -> checkIsland(e, e.getPlayer(), i.getCenter(), addon.MAGIC_BLOCK));
}

Cancelling at LOWEST is strictly before any later ignoreCancelled = true handler, so Jobs' HIGHEST handler is guaranteed to be skipped for a denied break — no reward is granted. Full magic-block processing stays at HIGHEST (other protection plugins still get their say for legitimate breaks), and allowed breaks are unaffected.

Caveat

This closes the exploit for plugins that respect cancellation (Jobs does, via ignoreCancelled = true). A plugin that pays out at LOWEST or ignores cancellation entirely couldn't be stopped this way, but Jobs specifically is now handled.

Tests

Added 5 regression tests to BlockListenerTest2:

  • asserts the handler is registered at LOWEST / ignoreCancelled = true (the crux of the fix)
  • denied break is cancelled early
  • allowed break is left untouched
  • not-in-world and non-center-block guard clauses skip the flag check

Full BlockListener* / BlockProtect suites: 65 tests, 0 failures.

Version

Bumped to 1.25.2 (bug-fix release).

🤖 Generated with Claude Code

tastybento and others added 2 commits July 10, 2026 07:37
#534)

Jobs Reborn awards block-break rewards from a BlockBreakEvent handler at
EventPriority.HIGHEST with ignoreCancelled=true. AOneBlock also only checked
the MAGIC_BLOCK protection flag (and cancelled the break) at HIGHEST. Within a
single priority slot, Bukkit fires handlers in plugin-registration order, which
is nondeterministic. When Jobs ran before AOneBlock, it paid out before the
break was cancelled; since the magic block respawns on a cancelled break, a
player lacking the MAGIC_BLOCK flag could mine it endlessly for infinite rewards.

Add a dedicated onBlockBreakDeny handler at EventPriority.LOWEST that runs the
MAGIC_BLOCK flag check (which cancels the event on denial). Cancelling at LOWEST
is strictly before any later ignoreCancelled=true handler, so reward plugins are
skipped for denied breaks. Full magic-block processing stays at HIGHEST, and
allowed breaks are unaffected.

Bump version to 1.25.2.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017nxjWg93etdoy6U6nhTXRX
…d S8924)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017nxjWg93etdoy6U6nhTXRX
@sonarqubecloud

Copy link
Copy Markdown

@tastybento tastybento merged commit d50a8af into develop Jul 10, 2026
3 checks passed
@tastybento tastybento deleted the fix/jobs-magic-block-priority-534 branch July 10, 2026 14:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Jobs Reborn incompatibility with magic block flag

1 participant