Skip to content

Confirm chunk claims before spending level credit - #17

Merged
tastybento merged 2 commits into
developfrom
feat/claim-confirmation
Aug 8, 2026
Merged

Confirm chunk claims before spending level credit#17
tastybento merged 2 commits into
developfrom
feat/claim-confirmation

Conversation

@tastybento

Copy link
Copy Markdown
Member

Hitting the border spent the island's levels on the first swing, so a stray click near the frontier could cost a chunk's worth of credit with no way to undo it. Claiming now takes two deliberate gestures.

  1. Hit the border — the target chunk is outlined in yellow and you are quoted the price:
    "Claim this chunk for 1 level(s)? That leaves you 3 level(s) of credit. Sneak and hit the border again within 15s to confirm."
  2. Sneak and hit the same chunk again — the credit is spent and the existing celebration fires.

A hit that could not claim anyway (no credit, beyond the protection range, not adjacent) skips the preview entirely and gives exactly the same feedback as before, so players are only ever asked to confirm a purchase that would actually go through.

Design notes

Why sneaking rather than just hitting twice. A plain second hit protects nothing — normal mining cadence lands a second swing about 250ms after the first, so the confirmation would fire on its own. Sneaking is a distinct gesture that a swing stream does not produce by itself.

The arming delay is a separate guard. One physical swing can raise both LEFT_CLICK_AIR and LEFT_CLICK_BLOCK on the same tick; without a minimum gap that single swing would preview and pay. CONFIRM_ARM_MS (250ms) covers this, and testDoubleFireOfOneSwingDoesNotClaim pins it.

The outline persists for the whole window. BorderDisplay already runs a redraw task every 12 ticks, so the preview rides that loop and expires by itself — no new scheduler, and the visual lasts as long as the offer does.

Quotes are bound to island, chunk and time. Aiming at a different chunk re-prices instead of confirming, an expired window re-prices, and quitting drops the pending claim.

Quote spam is throttled through the existing 2s feedback cooldown, so holding attack at the border announces the price once rather than every blow. That throttle never stamped its timestamp on the first message; fixed here as well. The quit handler also clears lastFeedback, which previously leaked an entry per departed player.

Configuration

Key Default
chunkblock.claim.require-confirmation true Set false for the old one-hit claim
chunkblock.claim.confirmation-timeout 15 Seconds a quote stays confirmable, minimum 1

New locale key chunkblock.chunks.claim-confirm in en-US.yml. Other locales will show the raw key until synced. claim-hint is unchanged — it is still accurate as step one.

This defaults to on, which changes behaviour for existing servers on update. That is the right default for the problem, but it is a mid-season gameplay change and deserves a line in the release notes.

Testing

623 tests green, 19 in ChunkClaimListenerTest of which 8 are new: preview spends nothing, a non-sneaking second hit does not claim, one swing's double fire does not claim, the window expires and re-prices, confirming while aimed at a different chunk claims neither, the quote is not re-announced per swing, quitting drops the pending claim, and the whole thing can be switched off.

Also tried on a live Paper 26.2 server with BentoBox 3.22.0 and Level 2.28.1 alongside AOneBlock.

Scope

Part of #6 — this is the confirmation half. The rank-based "who may claim" island setting from that issue is not included, so #6 should stay open. Today claiming is still hard-coded to the island owner at ChunkClaimListener.java:71, and a teammate who hits the border gets no feedback at all.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Taa2snoHkvtcZ6e5rAHDQS

tastybento and others added 2 commits August 8, 2026 12:06
Hitting the border spent the island's levels on the first swing, so a stray
click near the frontier could cost a chunk's worth of credit with no way back.
Claiming is now two deliberate gestures: the first hit outlines the target
chunk and quotes its price, and only a second hit made while sneaking pays for
it. A hit that could not claim anyway (no credit, beyond the protection range,
not adjacent) skips the preview and gives the same feedback as before, so
players are only asked to confirm a purchase that would actually go through.

Sneaking, rather than simply hitting twice, is what separates the confirming
gesture from an ordinary swing: mining cadence puts a second hit ~250ms after
the first, which would confirm on its own. A short arming delay sits underneath
that because one physical swing can raise both LEFT_CLICK_AIR and
LEFT_CLICK_BLOCK on the same tick, and without it that single swing would
preview and pay at once.

The outline lives in BorderDisplay and rides the existing redraw task, so it
persists for the whole confirmation window and expires by itself rather than
needing a scheduler of its own. Quotes are bound to island, chunk and time:
aiming elsewhere re-prices, an expired window re-prices, and logging out drops
the pending claim. Repeat swings at the same chunk reuse the existing feedback
throttle so the quote is announced once, not once per blow; that throttle never
stamped its timestamp on the first message, which is fixed here too.

Configurable via chunkblock.claim.require-confirmation (default true) and
chunkblock.claim.confirmation-timeout (15s), so servers preferring the old
one-hit claim can switch it off.

Part of #6 (the confirmation step only; rank-based claim permission is still to come).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Taa2snoHkvtcZ6e5rAHDQS
The preview outline computed its particle coordinates with int arithmetic
before widening to the double parameters, which Sonar reports as a reliability
bug. Hold the chunk origin as a double so the whole expression is double, and
fold the half-block offset into the base height rather than recomputing it per
row.

Also in the tests: use the Component overload of PlayerQuitEvent instead of the
String one, which is deprecated for removal, and hoist an inline mock into a
local.

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

sonarqubecloud Bot commented Aug 8, 2026

Copy link
Copy Markdown

@tastybento
tastybento merged commit fa12f9e into develop Aug 8, 2026
3 checks passed
@tastybento
tastybento deleted the feat/claim-confirmation branch August 8, 2026 19:49
@tastybento tastybento mentioned this pull request Aug 8, 2026
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.

1 participant