Add block donation feature - #412

Merged
tastybento merged 38 commits into
masterfrom
feature/block-donation
Apr 12, 2026
Merged

Add block donation feature#412
tastybento merged 38 commits into
masterfrom
feature/block-donation

Conversation

@tastybento

@tastybentotastybento commented Apr 11, 2026

Copy link
Copy Markdown
Member

Summary

  • New /island donate command and chest-style GUI letting players permanently donate blocks to raise their island level
  • /island donate hand [amount] for quick donation from the held item
  • New ISLAND_BLOCK_DONATION flag (default: owner; configurable to member) gates who can donate
  • Donated points feed into the level calculation and persist across recalcs; legacy island data stays compatible via null-safe fields
  • Detail panel gains a DONATED tab; admin level report includes a donated-blocks section; donation audit log records donor + timestamp
  • Destructive-action warnings on the confirm button and GUI info text

Test plan

  • mvn verify passes
  • /island donate opens the GUI; dragging a block in and confirming raises level and consumes the items
  • /island donate hand 5 donates 5 from the held stack
  • ISLAND_BLOCK_DONATION flag toggles between owner-only and member access
  • Donated blocks survive a /island level recalculation
  • Detail panel DONATED tab shows the donation history
  • Admin level report includes the donated blocks section
  • Legacy islands (no donation data) load without NPEs

🤖 Generated with Claude Code

CopilotAIand others added 30 commits March 2, 2026 01:19
…alidate cache on update
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>
Fix top ten ordering: replace LinkedHashMap with ConcurrentHashMap for thread safety
- Remove _hanging stripping in ValuePanel.getIcon() so hanging signs
display as hanging signs instead of regular signs
- Split Tag fallback: ALL_HANGING_SIGNS -> OAK_HANGING_SIGN
- Fix DetailsPanel wall hanging sign conversion to produce _HANGING_SIGN
- Change twisting vines plant icon from VINE to TWISTING_VINES
- Change weeping vines plant icon from VINE to WEEPING_VINES
- Change cave vines plant icon from VINE to GLOW_BERRIES
- Add CAVE_VINES to ValuePanel switch so it appears in /ob value menu
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>
…-sign-icon
Fix incorrect icons for hanging signs, vines, and cave vines in panels
…guage-translation
Add Russian (ru) locale with MiniMessage formatting
- Add missing island.detail.description
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
- Fix spawner button name (Спавнери)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add missing island.level keys (in-progress, time-out)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add missing island.level keys (in-progress, time-out)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add missing island.level keys (in-progress, time-out)
- Add full level section (commands, gui, conversations)
- Remove old island.value and island.top.remove structures
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.level.sethandicap section
- Add admin.levelstatus.description
- Add admin.stats section
- Add island.detail.description
- Add missing island.level keys (in-progress, time-out, in-queue)
- Add missing island.level-details keys (names-island, syntax, hint)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.top.description, admin.stats section
- Add island.detail.description
- Add missing island.level keys (estimated-wait, in-queue, in-progress, time-out)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.level.sethandicap section
- Add admin.levelstatus.islands-in-queue and description
- Add admin.stats section
- Add island.detail.description
- Add missing island.level keys (estimated-wait, in-queue, in-progress, time-out)
- Add island.level-details section (all keys)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.level.sethandicap section
- Add admin.levelstatus section
- Add admin.top.remove, admin.stats section
- Add island.detail.description
- Add missing island.level keys (estimated-wait, in-queue, in-progress, time-out)
- Add island.level-details section (all keys)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…n plugins
Require BentoBox API 3.14.0 (addon.yml) and align the pom dependency with
the bentobox.version property so both stay in sync. All 17 locale files are
converted from legacy & color codes to MiniMessage tags now that the User
API supports them natively. Maven plugins are bumped to their latest stable
releases; the compiler plugin is forked to work around a plexus-compiler
in-process bug ("this.hashes is null") that otherwise breaks test-compile.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Players can permanently donate blocks to raise island level.
- /island donate: opens chest-style GUI to drag blocks in
- /island donate hand [amount]: quick donate from held item
- ISLAND_BLOCK_DONATION flag (default: owner, configurable to member)
- Donated points added to level calculation, persist across recalcs
- DONATED tab in island detail panel
- Donation audit log with timestamps and donor tracking
- Admin level report extended with donated blocks section
- Destructive action warnings on confirm button and GUI info
- Backwards compatible: null-safe fields for legacy island data
Adds the new donation feature strings (island.donate, ISLAND_BLOCK_DONATION
flag, donated tab button) to all non-English locales using English text as
placeholder for translators. Notes in CLAUDE.md that on-disk panel templates
are not overwritten on upgrade so release notes must call out panel changes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The donation panel built items via Bukkit's deprecated setDisplayName/
setLore APIs and split the translated text on '|'. Two adjacent
MiniMessage spans of the same color collapse to a single legacy run
(e.g. "§cWarning…|destroyed…"), so splitting dropped the §c from the
second line and it rendered in default purple italic. Lore also got
Minecraft's default italic because the legacy String API does not
suppress it the way Adventure Components do.
Switch to displayName(Component)/lore(List<Component>), parse each
segment with Util.parseMiniMessageOrLegacy, suppress default italic,
and carry the active §color/§format codes across '|' splits so styles
do not get dropped on subsequent segments.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a new “block donation” mechanic for the Level addon: players can donate blocks (via GUI or from hand) to permanently add points that are included in island level calculations, with an audit trail and new UI tabs/strings.

Changes:

  • Added /island donate command + Donation GUI to convert donated blocks into permanent level points gated by a new ISLAND_BLOCK_DONATION flag.
  • Persisted donated blocks/points + donation audit log in island level data, and included donated points in level calculations and reports.
  • Updated detail panel UI + many locale files, and bumped BentoBox/API versions.

Reviewed changes

Copilot reviewed 33 out of 33 changed files in this pull request and generated 6 comments.

Show a summary per file
FileDescription
src/test/java/world/bentobox/level/LevelTest.javaUpdates command registration expectations due to new command.
src/test/java/world/bentobox/level/LevelsManagerTest.javaAdds a regression test to ensure Top Ten results are sorted descending.
src/main/resources/panels/detail_panel.ymlAdds a new DONATED tab button to the island detail panel.
src/main/resources/locales/zh-CN.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/vi.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/uk.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/tr.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/ru.ymlAdds a new Russian locale including donation + flag strings.
src/main/resources/locales/pt.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/pl.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/nl.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/lv.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/ko.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/id.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/hu.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/fr.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/es.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/en-US.ymlConverts to MiniMessage-style formatting and adds donation + flag strings.
src/main/resources/locales/de.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/cs.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/addon.ymlBumps addon api-version to align with updated BentoBox dependency.
src/main/java/world/bentobox/level/panels/ValuePanel.javaAdjusts icon mapping for newer materials (vines/signs).
src/main/java/world/bentobox/level/panels/DonationPanel.javaImplements the chest-style donation GUI and inventory event handling.
src/main/java/world/bentobox/level/panels/DetailsPanel.javaAdds DONATED tab support and adjusts icon conversion for newer items.
src/main/java/world/bentobox/level/objects/TopTenData.javaSwitches Top Ten backing map to ConcurrentHashMap.
src/main/java/world/bentobox/level/objects/IslandLevels.javaPersists donated blocks/points and a donation audit log (null-safe).
src/main/java/world/bentobox/level/LevelsManager.javaAdds donation persistence APIs + cache invalidation for top-ten caching.
src/main/java/world/bentobox/level/Level.javaRegisters donation flag and the new donate command.
src/main/java/world/bentobox/level/commands/IslandDonateCommand.javaAdds /island donate and /island donate hand [amount] command handling.
src/main/java/world/bentobox/level/calculators/Results.javaAdds donatedPoints to results.
src/main/java/world/bentobox/level/calculators/IslandLevelCalculator.javaIncludes donated points in calculation and admin report output.
pom.xmlUpdates Bentobox + build/plugin versions.
CLAUDE.mdDocuments panel template upgrade caveat and local dependency source lookup guidance.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadsrc/main/java/world/bentobox/level/panels/DonationPanel.java
Comment threadsrc/main/java/world/bentobox/level/panels/DonationPanel.java Outdated
Comment threadsrc/main/java/world/bentobox/level/panels/DonationPanel.java Outdated
Comment threadsrc/main/java/world/bentobox/level/LevelsManager.java Outdated
Comment threadsrc/main/java/world/bentobox/level/LevelsManager.java Outdated
Comment threadsrc/main/resources/locales/en-US.yml Outdated
Require a re-run confirmation before /island donate hand destroys items,
fix tab completion to offer "hand" and the held stack size, route "help"
through the standard help handler, and format [points] placeholders via
the player's locale so large totals render with thousands separators.
Sync the new confirm-prompt key plus spacing and typo fixes across every
locale file.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@tastybento

Copy link
Copy Markdown
MemberAuthor

@copilot apply changes based on the comments in this thread

…ity, locale spacing
Agent-Logs-Url: https://github.com/BentoBoxWorld/Level/sessions/0764e162-6b48-4cf7-b3e9-f344016416bd
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>

CopilotAI commented Apr 11, 2026

Copy link
Copy Markdown
Contributor

@copilot apply changes based on the comments in this thread

Applied all changes from the review in commit f27f8f7:

  • processDonation(): valueless items are now returned to the player (with overflow drop) instead of being silently consumed
  • Shift-click handler: replaced direct mutation of event.getCurrentItem() with inventory.setItem() / event.setCurrentItem() to avoid client/server inventory desync
  • Donation-slot validator: now rejects blocks with no configured value (not just non-blocks), and handles inventory overflow by dropping items at the player's location
  • donateBlocks(): uses getLevelsData(island) instead of computeIfAbsent() to avoid overwriting persisted DB records
  • addToTopTen() call removed: donations only affect future recalculations; the stored level is updated by setIslandResults() after a full recalc
  • en-US.yml: restored space before [+/-] in admin.level.sethandicap.parameters

@tastybento

Copy link
Copy Markdown
MemberAuthor

@copilot apply changes based on the comments in this thread

CopilotAI commented Apr 11, 2026

Copy link
Copy Markdown
Contributor

@copilot apply changes based on the comments in this thread

All six changes from the review thread were already applied in commit f27f8f7:

  1. processDonation() — valueless items returned to player instead of consumed
  2. Shift-click handler — uses event.setCurrentItem() / inventory.setItem() with clones instead of mutating event.getCurrentItem()
  3. Donation-slot validator — checks isBlock() AND getValue() > 0, drops overflow at player location
  4. donateBlocks() — uses getLevelsData(island) instead of computeIfAbsent()
  5. addToTopTen() call removed with explanatory comment
  6. en-US.yml — space restored in admin.level.sethandicap.parameters

tastybentoand others added 3 commits April 11, 2026 16:28
Bumps BentoBox to 3.14.1-SNAPSHOT for the new Flag.Builder.minimumRank
API and uses it on BLOCK_DONATION so VISITOR/COOP/TRUSTED ranks can
never be selected as the donation rank — only MEMBER and above.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Extract [points] placeholder into a POINTS_PLACEHOLDER constant so
the literal is declared once instead of four times (S1192)
- Switch the GUI creation to the Component-based Bukkit.createInventory
overload so we are no longer calling the deprecated String variant
(S1874), and reuse removeDefaultItalic so the title matches the
styling rules used for item names
- Split onInventoryClick into small focused helpers
(handlePlayerInventoryClick, handleCancel, handleConfirm,
handleDonationSlotClick, isValidDonationItem,
distributeIntoDonationSlots). Drops cognitive complexity well below
the 15 threshold and fixes the brain-method warning (S3776, S6541)
- Rewrite the shift-click distribution loop as a while loop guarded by
amount > 0 and the two-branch splitWithStyleCarryover loop as an
if/else-if/else chain, so neither uses more than one break/continue
(S135)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Require Member rank minimum on block donation flag

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 35 out of 35 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +556 to +563
public void donateBlocks(@NonNull Island island, @NonNull UUID donorUUID, @NonNull String material, int count, long points) {
IslandLevels ld = getLevelsData(island);
ld.addDonation(donorUUID.toString(), material, count, points);
handler.saveObjectAsync(ld);
// Do not update TopTen here: donations affect future recalculations, and the
// stored island level is only updated when setIslandResults(...) persists the
// recalculated level data.
}

CopilotAIApr 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

donateBlocks(...) only updates the donation fields and saves the object, but it never triggers a level recalculation or updates the stored level/pointsToNextLevel fields. Since getIslandLevel(...) reads IslandLevels#getLevel(), donations won’t actually affect island level/top-ten output until some later /island level recalculation happens. Consider queueing a recalculation here (or in the donate command/panel after a successful donation), or explicitly updating the persisted level fields so the “donation raises level” behavior is immediate and consistent.

Copilot uses AI. Check for mistakes.
Comment on lines +145 to +156
public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
String lastArg = !args.isEmpty() ? args.get(args.size() - 1) : "";
if (args.size() <= 2) {
return Optional.of(Util.tabLimit(List.of("hand"), lastArg));
}
if (args.size() == 3 && "hand".equalsIgnoreCase(args.get(1)) && user.isPlayer()) {
int held = user.getPlayer().getInventory().getItemInMainHand().getAmount();
if (held > 0) {
return Optional.of(Util.tabLimit(List.of(String.valueOf(held)), lastArg));
}
}
return Optional.of(List.of());

CopilotAIApr 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tab-complete argument indexing/branching looks off for /island donate hand [amount]. With the current logic, args.size() <= 2 always suggests only hand (even after typing hand), and the amount suggestion branch (args.size() == 3 && args.get(1)) is never reached for typical arg arrays like ["hand"] or ["hand","5"]. Adjust the conditions to match the actual args passed to subcommands so hand is suggested for the first arg and an amount is suggested for the second.

Copilot uses AI. Check for mistakes.
Comment on lines +314 to +320
if (inSlot != null && !inSlot.getType().isAir() && !isValidDonationItem(inSlot)) {
inventory.setItem(slot, null);
Map<Integer, ItemStack> overflow = player.getInventory().addItem(inSlot);
overflow.values().forEach(item -> player.getWorld().dropItemNaturally(player.getLocation(), item));
user.sendMessage("island.donate.hand.not-block");
}
updatePreview();

CopilotAIApr 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When a player places an invalid item into the donation GUI, the code sends island.donate.hand.not-block. That message is specific to the /island donate hand flow (“You must be holding…”), so it’s misleading in the GUI context (and also for blocks that are placeable but have no configured value). Consider adding/using a GUI-specific translation key (e.g. “Only valuable blocks can be donated”) to make the error message accurate.

Copilot uses AI. Check for mistakes.
Comment threadCLAUDE.md Outdated
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@tastybento

Copy link
Copy Markdown
MemberAuthor

@copilot apply changes based on the comments in this thread

…ng, GUI-specific error message
Agent-Logs-Url: https://github.com/BentoBoxWorld/Level/sessions/753156c2-d054-4c6f-820a-48c0ffedbbbe
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>

CopilotAI commented Apr 11, 2026

Copy link
Copy Markdown
Contributor

@copilot apply changes based on the comments in this thread

Applied all 3 changes in commit 099fc44:

  1. Level recalculation after donation — Added recalculateAfterDonation() to LevelsManager, called from both the GUI and hand donation flows so island level/top-ten update immediately
  2. Tab-complete arg indexing — Fixed to suggest hand for args.size() <= 1 and amount for args.size() == 2 && args.get(0) == "hand"
  3. GUI-specific error message — New island.donate.invalid-item key ("Only blocks with a configured level value can be donated") replaces reuse of the hand-flow message

@sonarqubecloud

Copy link
Copy Markdown

@tastybento
tastybento merged commit b755519 into masterApr 12, 2026
3 checks passed
@tastybento
tastybento deleted the feature/block-donation branch April 12, 2026 00:19
Sign up for freeto 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.

3 participants

@tastybento
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Add block donation feature - #412

Merged
tastybento merged 38 commits into
masterfrom
feature/block-donation
Apr 12, 2026
Merged

Add block donation feature#412
tastybento merged 38 commits into
masterfrom
feature/block-donation

Conversation

@tastybento

@tastybentotastybento commented Apr 11, 2026

Copy link
Copy Markdown
Member

Summary

  • New /island donate command and chest-style GUI letting players permanently donate blocks to raise their island level
  • /island donate hand [amount] for quick donation from the held item
  • New ISLAND_BLOCK_DONATION flag (default: owner; configurable to member) gates who can donate
  • Donated points feed into the level calculation and persist across recalcs; legacy island data stays compatible via null-safe fields
  • Detail panel gains a DONATED tab; admin level report includes a donated-blocks section; donation audit log records donor + timestamp
  • Destructive-action warnings on the confirm button and GUI info text

Test plan

  • mvn verify passes
  • /island donate opens the GUI; dragging a block in and confirming raises level and consumes the items
  • /island donate hand 5 donates 5 from the held stack
  • ISLAND_BLOCK_DONATION flag toggles between owner-only and member access
  • Donated blocks survive a /island level recalculation
  • Detail panel DONATED tab shows the donation history
  • Admin level report includes the donated blocks section
  • Legacy islands (no donation data) load without NPEs

🤖 Generated with Claude Code

CopilotAIand others added 30 commits March 2, 2026 01:19
…alidate cache on update
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>
Fix top ten ordering: replace LinkedHashMap with ConcurrentHashMap for thread safety
- Remove _hanging stripping in ValuePanel.getIcon() so hanging signs
display as hanging signs instead of regular signs
- Split Tag fallback: ALL_HANGING_SIGNS -> OAK_HANGING_SIGN
- Fix DetailsPanel wall hanging sign conversion to produce _HANGING_SIGN
- Change twisting vines plant icon from VINE to TWISTING_VINES
- Change weeping vines plant icon from VINE to WEEPING_VINES
- Change cave vines plant icon from VINE to GLOW_BERRIES
- Add CAVE_VINES to ValuePanel switch so it appears in /ob value menu
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>
…-sign-icon
Fix incorrect icons for hanging signs, vines, and cave vines in panels
…guage-translation
Add Russian (ru) locale with MiniMessage formatting
- Add missing island.detail.description
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
- Fix spawner button name (Спавнери)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add missing island.level keys (in-progress, time-out)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add missing island.level keys (in-progress, time-out)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add missing island.level keys (in-progress, time-out)
- Add full level section (commands, gui, conversations)
- Remove old island.value and island.top.remove structures
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.level.sethandicap section
- Add admin.levelstatus.description
- Add admin.stats section
- Add island.detail.description
- Add missing island.level keys (in-progress, time-out, in-queue)
- Add missing island.level-details keys (names-island, syntax, hint)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.top.description, admin.stats section
- Add island.detail.description
- Add missing island.level keys (estimated-wait, in-queue, in-progress, time-out)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.level.sethandicap section
- Add admin.levelstatus.islands-in-queue and description
- Add admin.stats section
- Add island.detail.description
- Add missing island.level keys (estimated-wait, in-queue, in-progress, time-out)
- Add island.level-details section (all keys)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.level.sethandicap section
- Add admin.levelstatus section
- Add admin.top.remove, admin.stats section
- Add island.detail.description
- Add missing island.level keys (estimated-wait, in-queue, in-progress, time-out)
- Add island.level-details section (all keys)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…n plugins
Require BentoBox API 3.14.0 (addon.yml) and align the pom dependency with
the bentobox.version property so both stay in sync. All 17 locale files are
converted from legacy & color codes to MiniMessage tags now that the User
API supports them natively. Maven plugins are bumped to their latest stable
releases; the compiler plugin is forked to work around a plexus-compiler
in-process bug ("this.hashes is null") that otherwise breaks test-compile.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Players can permanently donate blocks to raise island level.
- /island donate: opens chest-style GUI to drag blocks in
- /island donate hand [amount]: quick donate from held item
- ISLAND_BLOCK_DONATION flag (default: owner, configurable to member)
- Donated points added to level calculation, persist across recalcs
- DONATED tab in island detail panel
- Donation audit log with timestamps and donor tracking
- Admin level report extended with donated blocks section
- Destructive action warnings on confirm button and GUI info
- Backwards compatible: null-safe fields for legacy island data
Adds the new donation feature strings (island.donate, ISLAND_BLOCK_DONATION
flag, donated tab button) to all non-English locales using English text as
placeholder for translators. Notes in CLAUDE.md that on-disk panel templates
are not overwritten on upgrade so release notes must call out panel changes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The donation panel built items via Bukkit's deprecated setDisplayName/
setLore APIs and split the translated text on '|'. Two adjacent
MiniMessage spans of the same color collapse to a single legacy run
(e.g. "§cWarning…|destroyed…"), so splitting dropped the §c from the
second line and it rendered in default purple italic. Lore also got
Minecraft's default italic because the legacy String API does not
suppress it the way Adventure Components do.
Switch to displayName(Component)/lore(List<Component>), parse each
segment with Util.parseMiniMessageOrLegacy, suppress default italic,
and carry the active §color/§format codes across '|' splits so styles
do not get dropped on subsequent segments.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a new “block donation” mechanic for the Level addon: players can donate blocks (via GUI or from hand) to permanently add points that are included in island level calculations, with an audit trail and new UI tabs/strings.

Changes:

  • Added /island donate command + Donation GUI to convert donated blocks into permanent level points gated by a new ISLAND_BLOCK_DONATION flag.
  • Persisted donated blocks/points + donation audit log in island level data, and included donated points in level calculations and reports.
  • Updated detail panel UI + many locale files, and bumped BentoBox/API versions.

Reviewed changes

Copilot reviewed 33 out of 33 changed files in this pull request and generated 6 comments.

Show a summary per file
FileDescription
src/test/java/world/bentobox/level/LevelTest.javaUpdates command registration expectations due to new command.
src/test/java/world/bentobox/level/LevelsManagerTest.javaAdds a regression test to ensure Top Ten results are sorted descending.
src/main/resources/panels/detail_panel.ymlAdds a new DONATED tab button to the island detail panel.
src/main/resources/locales/zh-CN.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/vi.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/uk.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/tr.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/ru.ymlAdds a new Russian locale including donation + flag strings.
src/main/resources/locales/pt.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/pl.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/nl.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/lv.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/ko.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/id.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/hu.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/fr.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/es.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/en-US.ymlConverts to MiniMessage-style formatting and adds donation + flag strings.
src/main/resources/locales/de.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/cs.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/addon.ymlBumps addon api-version to align with updated BentoBox dependency.
src/main/java/world/bentobox/level/panels/ValuePanel.javaAdjusts icon mapping for newer materials (vines/signs).
src/main/java/world/bentobox/level/panels/DonationPanel.javaImplements the chest-style donation GUI and inventory event handling.
src/main/java/world/bentobox/level/panels/DetailsPanel.javaAdds DONATED tab support and adjusts icon conversion for newer items.
src/main/java/world/bentobox/level/objects/TopTenData.javaSwitches Top Ten backing map to ConcurrentHashMap.
src/main/java/world/bentobox/level/objects/IslandLevels.javaPersists donated blocks/points and a donation audit log (null-safe).
src/main/java/world/bentobox/level/LevelsManager.javaAdds donation persistence APIs + cache invalidation for top-ten caching.
src/main/java/world/bentobox/level/Level.javaRegisters donation flag and the new donate command.
src/main/java/world/bentobox/level/commands/IslandDonateCommand.javaAdds /island donate and /island donate hand [amount] command handling.
src/main/java/world/bentobox/level/calculators/Results.javaAdds donatedPoints to results.
src/main/java/world/bentobox/level/calculators/IslandLevelCalculator.javaIncludes donated points in calculation and admin report output.
pom.xmlUpdates Bentobox + build/plugin versions.
CLAUDE.mdDocuments panel template upgrade caveat and local dependency source lookup guidance.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadsrc/main/java/world/bentobox/level/panels/DonationPanel.java
Comment threadsrc/main/java/world/bentobox/level/panels/DonationPanel.java Outdated
Comment threadsrc/main/java/world/bentobox/level/panels/DonationPanel.java Outdated
Comment threadsrc/main/java/world/bentobox/level/LevelsManager.java Outdated
Comment threadsrc/main/java/world/bentobox/level/LevelsManager.java Outdated
Comment threadsrc/main/resources/locales/en-US.yml Outdated
Require a re-run confirmation before /island donate hand destroys items,
fix tab completion to offer "hand" and the held stack size, route "help"
through the standard help handler, and format [points] placeholders via
the player's locale so large totals render with thousands separators.
Sync the new confirm-prompt key plus spacing and typo fixes across every
locale file.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@tastybento

Copy link
Copy Markdown
MemberAuthor

@copilot apply changes based on the comments in this thread

…ity, locale spacing
Agent-Logs-Url: https://github.com/BentoBoxWorld/Level/sessions/0764e162-6b48-4cf7-b3e9-f344016416bd
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>

CopilotAI commented Apr 11, 2026

Copy link
Copy Markdown
Contributor

@copilot apply changes based on the comments in this thread

Applied all changes from the review in commit f27f8f7:

  • processDonation(): valueless items are now returned to the player (with overflow drop) instead of being silently consumed
  • Shift-click handler: replaced direct mutation of event.getCurrentItem() with inventory.setItem() / event.setCurrentItem() to avoid client/server inventory desync
  • Donation-slot validator: now rejects blocks with no configured value (not just non-blocks), and handles inventory overflow by dropping items at the player's location
  • donateBlocks(): uses getLevelsData(island) instead of computeIfAbsent() to avoid overwriting persisted DB records
  • addToTopTen() call removed: donations only affect future recalculations; the stored level is updated by setIslandResults() after a full recalc
  • en-US.yml: restored space before [+/-] in admin.level.sethandicap.parameters

@tastybento

Copy link
Copy Markdown
MemberAuthor

@copilot apply changes based on the comments in this thread

CopilotAI commented Apr 11, 2026

Copy link
Copy Markdown
Contributor

@copilot apply changes based on the comments in this thread

All six changes from the review thread were already applied in commit f27f8f7:

  1. processDonation() — valueless items returned to player instead of consumed
  2. Shift-click handler — uses event.setCurrentItem() / inventory.setItem() with clones instead of mutating event.getCurrentItem()
  3. Donation-slot validator — checks isBlock() AND getValue() > 0, drops overflow at player location
  4. donateBlocks() — uses getLevelsData(island) instead of computeIfAbsent()
  5. addToTopTen() call removed with explanatory comment
  6. en-US.yml — space restored in admin.level.sethandicap.parameters

tastybentoand others added 3 commits April 11, 2026 16:28
Bumps BentoBox to 3.14.1-SNAPSHOT for the new Flag.Builder.minimumRank
API and uses it on BLOCK_DONATION so VISITOR/COOP/TRUSTED ranks can
never be selected as the donation rank — only MEMBER and above.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Extract [points] placeholder into a POINTS_PLACEHOLDER constant so
the literal is declared once instead of four times (S1192)
- Switch the GUI creation to the Component-based Bukkit.createInventory
overload so we are no longer calling the deprecated String variant
(S1874), and reuse removeDefaultItalic so the title matches the
styling rules used for item names
- Split onInventoryClick into small focused helpers
(handlePlayerInventoryClick, handleCancel, handleConfirm,
handleDonationSlotClick, isValidDonationItem,
distributeIntoDonationSlots). Drops cognitive complexity well below
the 15 threshold and fixes the brain-method warning (S3776, S6541)
- Rewrite the shift-click distribution loop as a while loop guarded by
amount > 0 and the two-branch splitWithStyleCarryover loop as an
if/else-if/else chain, so neither uses more than one break/continue
(S135)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Require Member rank minimum on block donation flag

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 35 out of 35 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +556 to +563
public void donateBlocks(@NonNull Island island, @NonNull UUID donorUUID, @NonNull String material, int count, long points) {
IslandLevels ld = getLevelsData(island);
ld.addDonation(donorUUID.toString(), material, count, points);
handler.saveObjectAsync(ld);
// Do not update TopTen here: donations affect future recalculations, and the
// stored island level is only updated when setIslandResults(...) persists the
// recalculated level data.
}

CopilotAIApr 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

donateBlocks(...) only updates the donation fields and saves the object, but it never triggers a level recalculation or updates the stored level/pointsToNextLevel fields. Since getIslandLevel(...) reads IslandLevels#getLevel(), donations won’t actually affect island level/top-ten output until some later /island level recalculation happens. Consider queueing a recalculation here (or in the donate command/panel after a successful donation), or explicitly updating the persisted level fields so the “donation raises level” behavior is immediate and consistent.

Copilot uses AI. Check for mistakes.
Comment on lines +145 to +156
public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
String lastArg = !args.isEmpty() ? args.get(args.size() - 1) : "";
if (args.size() <= 2) {
return Optional.of(Util.tabLimit(List.of("hand"), lastArg));
}
if (args.size() == 3 && "hand".equalsIgnoreCase(args.get(1)) && user.isPlayer()) {
int held = user.getPlayer().getInventory().getItemInMainHand().getAmount();
if (held > 0) {
return Optional.of(Util.tabLimit(List.of(String.valueOf(held)), lastArg));
}
}
return Optional.of(List.of());

CopilotAIApr 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tab-complete argument indexing/branching looks off for /island donate hand [amount]. With the current logic, args.size() <= 2 always suggests only hand (even after typing hand), and the amount suggestion branch (args.size() == 3 && args.get(1)) is never reached for typical arg arrays like ["hand"] or ["hand","5"]. Adjust the conditions to match the actual args passed to subcommands so hand is suggested for the first arg and an amount is suggested for the second.

Copilot uses AI. Check for mistakes.
Comment on lines +314 to +320
if (inSlot != null && !inSlot.getType().isAir() && !isValidDonationItem(inSlot)) {
inventory.setItem(slot, null);
Map<Integer, ItemStack> overflow = player.getInventory().addItem(inSlot);
overflow.values().forEach(item -> player.getWorld().dropItemNaturally(player.getLocation(), item));
user.sendMessage("island.donate.hand.not-block");
}
updatePreview();

CopilotAIApr 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When a player places an invalid item into the donation GUI, the code sends island.donate.hand.not-block. That message is specific to the /island donate hand flow (“You must be holding…”), so it’s misleading in the GUI context (and also for blocks that are placeable but have no configured value). Consider adding/using a GUI-specific translation key (e.g. “Only valuable blocks can be donated”) to make the error message accurate.

Copilot uses AI. Check for mistakes.
Comment threadCLAUDE.md Outdated
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@tastybento

Copy link
Copy Markdown
MemberAuthor

@copilot apply changes based on the comments in this thread

…ng, GUI-specific error message
Agent-Logs-Url: https://github.com/BentoBoxWorld/Level/sessions/753156c2-d054-4c6f-820a-48c0ffedbbbe
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>

CopilotAI commented Apr 11, 2026

Copy link
Copy Markdown
Contributor

@copilot apply changes based on the comments in this thread

Applied all 3 changes in commit 099fc44:

  1. Level recalculation after donation — Added recalculateAfterDonation() to LevelsManager, called from both the GUI and hand donation flows so island level/top-ten update immediately
  2. Tab-complete arg indexing — Fixed to suggest hand for args.size() <= 1 and amount for args.size() == 2 && args.get(0) == "hand"
  3. GUI-specific error message — New island.donate.invalid-item key ("Only blocks with a configured level value can be donated") replaces reuse of the hand-flow message

@sonarqubecloud

Copy link
Copy Markdown

@tastybento
tastybento merged commit b755519 into masterApr 12, 2026
3 checks passed
@tastybento
tastybento deleted the feature/block-donation branch April 12, 2026 00:19
Sign up for freeto 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.

3 participants

@tastybento
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add block donation feature - #412

Merged
tastybento merged 38 commits into
masterfrom
feature/block-donation
Apr 12, 2026
Merged

Add block donation feature#412
tastybento merged 38 commits into
masterfrom
feature/block-donation

Conversation

@tastybento

@tastybentotastybento commented Apr 11, 2026

Copy link
Copy Markdown
Member

Summary

  • New /island donate command and chest-style GUI letting players permanently donate blocks to raise their island level
  • /island donate hand [amount] for quick donation from the held item
  • New ISLAND_BLOCK_DONATION flag (default: owner; configurable to member) gates who can donate
  • Donated points feed into the level calculation and persist across recalcs; legacy island data stays compatible via null-safe fields
  • Detail panel gains a DONATED tab; admin level report includes a donated-blocks section; donation audit log records donor + timestamp
  • Destructive-action warnings on the confirm button and GUI info text

Test plan

  • mvn verify passes
  • /island donate opens the GUI; dragging a block in and confirming raises level and consumes the items
  • /island donate hand 5 donates 5 from the held stack
  • ISLAND_BLOCK_DONATION flag toggles between owner-only and member access
  • Donated blocks survive a /island level recalculation
  • Detail panel DONATED tab shows the donation history
  • Admin level report includes the donated blocks section
  • Legacy islands (no donation data) load without NPEs

🤖 Generated with Claude Code

CopilotAIand others added 30 commits March 2, 2026 01:19
…alidate cache on update
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>
Fix top ten ordering: replace LinkedHashMap with ConcurrentHashMap for thread safety
- Remove _hanging stripping in ValuePanel.getIcon() so hanging signs
display as hanging signs instead of regular signs
- Split Tag fallback: ALL_HANGING_SIGNS -> OAK_HANGING_SIGN
- Fix DetailsPanel wall hanging sign conversion to produce _HANGING_SIGN
- Change twisting vines plant icon from VINE to TWISTING_VINES
- Change weeping vines plant icon from VINE to WEEPING_VINES
- Change cave vines plant icon from VINE to GLOW_BERRIES
- Add CAVE_VINES to ValuePanel switch so it appears in /ob value menu
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>
…-sign-icon
Fix incorrect icons for hanging signs, vines, and cave vines in panels
…guage-translation
Add Russian (ru) locale with MiniMessage formatting
- Add missing island.detail.description
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
- Fix spawner button name (Спавнери)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add missing island.level keys (in-progress, time-out)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add missing island.level keys (in-progress, time-out)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add missing island.level keys (in-progress, time-out)
- Add full level section (commands, gui, conversations)
- Remove old island.value and island.top.remove structures
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.level.sethandicap section
- Add admin.levelstatus.description
- Add admin.stats section
- Add island.detail.description
- Add missing island.level keys (in-progress, time-out, in-queue)
- Add missing island.level-details keys (names-island, syntax, hint)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.top.description, admin.stats section
- Add island.detail.description
- Add missing island.level keys (estimated-wait, in-queue, in-progress, time-out)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.level.sethandicap section
- Add admin.levelstatus.islands-in-queue and description
- Add admin.stats section
- Add island.detail.description
- Add missing island.level keys (estimated-wait, in-queue, in-progress, time-out)
- Add island.level-details section (all keys)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.level.sethandicap section
- Add admin.levelstatus section
- Add admin.top.remove, admin.stats section
- Add island.detail.description
- Add missing island.level keys (estimated-wait, in-queue, in-progress, time-out)
- Add island.level-details section (all keys)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…n plugins
Require BentoBox API 3.14.0 (addon.yml) and align the pom dependency with
the bentobox.version property so both stay in sync. All 17 locale files are
converted from legacy & color codes to MiniMessage tags now that the User
API supports them natively. Maven plugins are bumped to their latest stable
releases; the compiler plugin is forked to work around a plexus-compiler
in-process bug ("this.hashes is null") that otherwise breaks test-compile.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Players can permanently donate blocks to raise island level.
- /island donate: opens chest-style GUI to drag blocks in
- /island donate hand [amount]: quick donate from held item
- ISLAND_BLOCK_DONATION flag (default: owner, configurable to member)
- Donated points added to level calculation, persist across recalcs
- DONATED tab in island detail panel
- Donation audit log with timestamps and donor tracking
- Admin level report extended with donated blocks section
- Destructive action warnings on confirm button and GUI info
- Backwards compatible: null-safe fields for legacy island data
Adds the new donation feature strings (island.donate, ISLAND_BLOCK_DONATION
flag, donated tab button) to all non-English locales using English text as
placeholder for translators. Notes in CLAUDE.md that on-disk panel templates
are not overwritten on upgrade so release notes must call out panel changes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The donation panel built items via Bukkit's deprecated setDisplayName/
setLore APIs and split the translated text on '|'. Two adjacent
MiniMessage spans of the same color collapse to a single legacy run
(e.g. "§cWarning…|destroyed…"), so splitting dropped the §c from the
second line and it rendered in default purple italic. Lore also got
Minecraft's default italic because the legacy String API does not
suppress it the way Adventure Components do.
Switch to displayName(Component)/lore(List<Component>), parse each
segment with Util.parseMiniMessageOrLegacy, suppress default italic,
and carry the active §color/§format codes across '|' splits so styles
do not get dropped on subsequent segments.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a new “block donation” mechanic for the Level addon: players can donate blocks (via GUI or from hand) to permanently add points that are included in island level calculations, with an audit trail and new UI tabs/strings.

Changes:

  • Added /island donate command + Donation GUI to convert donated blocks into permanent level points gated by a new ISLAND_BLOCK_DONATION flag.
  • Persisted donated blocks/points + donation audit log in island level data, and included donated points in level calculations and reports.
  • Updated detail panel UI + many locale files, and bumped BentoBox/API versions.

Reviewed changes

Copilot reviewed 33 out of 33 changed files in this pull request and generated 6 comments.

Show a summary per file
FileDescription
src/test/java/world/bentobox/level/LevelTest.javaUpdates command registration expectations due to new command.
src/test/java/world/bentobox/level/LevelsManagerTest.javaAdds a regression test to ensure Top Ten results are sorted descending.
src/main/resources/panels/detail_panel.ymlAdds a new DONATED tab button to the island detail panel.
src/main/resources/locales/zh-CN.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/vi.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/uk.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/tr.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/ru.ymlAdds a new Russian locale including donation + flag strings.
src/main/resources/locales/pt.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/pl.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/nl.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/lv.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/ko.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/id.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/hu.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/fr.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/es.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/en-US.ymlConverts to MiniMessage-style formatting and adds donation + flag strings.
src/main/resources/locales/de.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/cs.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/addon.ymlBumps addon api-version to align with updated BentoBox dependency.
src/main/java/world/bentobox/level/panels/ValuePanel.javaAdjusts icon mapping for newer materials (vines/signs).
src/main/java/world/bentobox/level/panels/DonationPanel.javaImplements the chest-style donation GUI and inventory event handling.
src/main/java/world/bentobox/level/panels/DetailsPanel.javaAdds DONATED tab support and adjusts icon conversion for newer items.
src/main/java/world/bentobox/level/objects/TopTenData.javaSwitches Top Ten backing map to ConcurrentHashMap.
src/main/java/world/bentobox/level/objects/IslandLevels.javaPersists donated blocks/points and a donation audit log (null-safe).
src/main/java/world/bentobox/level/LevelsManager.javaAdds donation persistence APIs + cache invalidation for top-ten caching.
src/main/java/world/bentobox/level/Level.javaRegisters donation flag and the new donate command.
src/main/java/world/bentobox/level/commands/IslandDonateCommand.javaAdds /island donate and /island donate hand [amount] command handling.
src/main/java/world/bentobox/level/calculators/Results.javaAdds donatedPoints to results.
src/main/java/world/bentobox/level/calculators/IslandLevelCalculator.javaIncludes donated points in calculation and admin report output.
pom.xmlUpdates Bentobox + build/plugin versions.
CLAUDE.mdDocuments panel template upgrade caveat and local dependency source lookup guidance.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadsrc/main/java/world/bentobox/level/panels/DonationPanel.java
Comment threadsrc/main/java/world/bentobox/level/panels/DonationPanel.java Outdated
Comment threadsrc/main/java/world/bentobox/level/panels/DonationPanel.java Outdated
Comment threadsrc/main/java/world/bentobox/level/LevelsManager.java Outdated
Comment threadsrc/main/java/world/bentobox/level/LevelsManager.java Outdated
Comment threadsrc/main/resources/locales/en-US.yml Outdated
Require a re-run confirmation before /island donate hand destroys items,
fix tab completion to offer "hand" and the held stack size, route "help"
through the standard help handler, and format [points] placeholders via
the player's locale so large totals render with thousands separators.
Sync the new confirm-prompt key plus spacing and typo fixes across every
locale file.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@tastybento

Copy link
Copy Markdown
MemberAuthor

@copilot apply changes based on the comments in this thread

…ity, locale spacing
Agent-Logs-Url: https://github.com/BentoBoxWorld/Level/sessions/0764e162-6b48-4cf7-b3e9-f344016416bd
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>

CopilotAI commented Apr 11, 2026

Copy link
Copy Markdown
Contributor

@copilot apply changes based on the comments in this thread

Applied all changes from the review in commit f27f8f7:

  • processDonation(): valueless items are now returned to the player (with overflow drop) instead of being silently consumed
  • Shift-click handler: replaced direct mutation of event.getCurrentItem() with inventory.setItem() / event.setCurrentItem() to avoid client/server inventory desync
  • Donation-slot validator: now rejects blocks with no configured value (not just non-blocks), and handles inventory overflow by dropping items at the player's location
  • donateBlocks(): uses getLevelsData(island) instead of computeIfAbsent() to avoid overwriting persisted DB records
  • addToTopTen() call removed: donations only affect future recalculations; the stored level is updated by setIslandResults() after a full recalc
  • en-US.yml: restored space before [+/-] in admin.level.sethandicap.parameters

@tastybento

Copy link
Copy Markdown
MemberAuthor

@copilot apply changes based on the comments in this thread

CopilotAI commented Apr 11, 2026

Copy link
Copy Markdown
Contributor

@copilot apply changes based on the comments in this thread

All six changes from the review thread were already applied in commit f27f8f7:

  1. processDonation() — valueless items returned to player instead of consumed
  2. Shift-click handler — uses event.setCurrentItem() / inventory.setItem() with clones instead of mutating event.getCurrentItem()
  3. Donation-slot validator — checks isBlock() AND getValue() > 0, drops overflow at player location
  4. donateBlocks() — uses getLevelsData(island) instead of computeIfAbsent()
  5. addToTopTen() call removed with explanatory comment
  6. en-US.yml — space restored in admin.level.sethandicap.parameters

tastybentoand others added 3 commits April 11, 2026 16:28
Bumps BentoBox to 3.14.1-SNAPSHOT for the new Flag.Builder.minimumRank
API and uses it on BLOCK_DONATION so VISITOR/COOP/TRUSTED ranks can
never be selected as the donation rank — only MEMBER and above.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Extract [points] placeholder into a POINTS_PLACEHOLDER constant so
the literal is declared once instead of four times (S1192)
- Switch the GUI creation to the Component-based Bukkit.createInventory
overload so we are no longer calling the deprecated String variant
(S1874), and reuse removeDefaultItalic so the title matches the
styling rules used for item names
- Split onInventoryClick into small focused helpers
(handlePlayerInventoryClick, handleCancel, handleConfirm,
handleDonationSlotClick, isValidDonationItem,
distributeIntoDonationSlots). Drops cognitive complexity well below
the 15 threshold and fixes the brain-method warning (S3776, S6541)
- Rewrite the shift-click distribution loop as a while loop guarded by
amount > 0 and the two-branch splitWithStyleCarryover loop as an
if/else-if/else chain, so neither uses more than one break/continue
(S135)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Require Member rank minimum on block donation flag

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 35 out of 35 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +556 to +563
public void donateBlocks(@NonNull Island island, @NonNull UUID donorUUID, @NonNull String material, int count, long points) {
IslandLevels ld = getLevelsData(island);
ld.addDonation(donorUUID.toString(), material, count, points);
handler.saveObjectAsync(ld);
// Do not update TopTen here: donations affect future recalculations, and the
// stored island level is only updated when setIslandResults(...) persists the
// recalculated level data.
}

CopilotAIApr 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

donateBlocks(...) only updates the donation fields and saves the object, but it never triggers a level recalculation or updates the stored level/pointsToNextLevel fields. Since getIslandLevel(...) reads IslandLevels#getLevel(), donations won’t actually affect island level/top-ten output until some later /island level recalculation happens. Consider queueing a recalculation here (or in the donate command/panel after a successful donation), or explicitly updating the persisted level fields so the “donation raises level” behavior is immediate and consistent.

Copilot uses AI. Check for mistakes.
Comment on lines +145 to +156
public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
String lastArg = !args.isEmpty() ? args.get(args.size() - 1) : "";
if (args.size() <= 2) {
return Optional.of(Util.tabLimit(List.of("hand"), lastArg));
}
if (args.size() == 3 && "hand".equalsIgnoreCase(args.get(1)) && user.isPlayer()) {
int held = user.getPlayer().getInventory().getItemInMainHand().getAmount();
if (held > 0) {
return Optional.of(Util.tabLimit(List.of(String.valueOf(held)), lastArg));
}
}
return Optional.of(List.of());

CopilotAIApr 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tab-complete argument indexing/branching looks off for /island donate hand [amount]. With the current logic, args.size() <= 2 always suggests only hand (even after typing hand), and the amount suggestion branch (args.size() == 3 && args.get(1)) is never reached for typical arg arrays like ["hand"] or ["hand","5"]. Adjust the conditions to match the actual args passed to subcommands so hand is suggested for the first arg and an amount is suggested for the second.

Copilot uses AI. Check for mistakes.
Comment on lines +314 to +320
if (inSlot != null && !inSlot.getType().isAir() && !isValidDonationItem(inSlot)) {
inventory.setItem(slot, null);
Map<Integer, ItemStack> overflow = player.getInventory().addItem(inSlot);
overflow.values().forEach(item -> player.getWorld().dropItemNaturally(player.getLocation(), item));
user.sendMessage("island.donate.hand.not-block");
}
updatePreview();

CopilotAIApr 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When a player places an invalid item into the donation GUI, the code sends island.donate.hand.not-block. That message is specific to the /island donate hand flow (“You must be holding…”), so it’s misleading in the GUI context (and also for blocks that are placeable but have no configured value). Consider adding/using a GUI-specific translation key (e.g. “Only valuable blocks can be donated”) to make the error message accurate.

Copilot uses AI. Check for mistakes.
Comment threadCLAUDE.md Outdated
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@tastybento

Copy link
Copy Markdown
MemberAuthor

@copilot apply changes based on the comments in this thread

…ng, GUI-specific error message
Agent-Logs-Url: https://github.com/BentoBoxWorld/Level/sessions/753156c2-d054-4c6f-820a-48c0ffedbbbe
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>

CopilotAI commented Apr 11, 2026

Copy link
Copy Markdown
Contributor

@copilot apply changes based on the comments in this thread

Applied all 3 changes in commit 099fc44:

  1. Level recalculation after donation — Added recalculateAfterDonation() to LevelsManager, called from both the GUI and hand donation flows so island level/top-ten update immediately
  2. Tab-complete arg indexing — Fixed to suggest hand for args.size() <= 1 and amount for args.size() == 2 && args.get(0) == "hand"
  3. GUI-specific error message — New island.donate.invalid-item key ("Only blocks with a configured level value can be donated") replaces reuse of the hand-flow message

@sonarqubecloud

Copy link
Copy Markdown

@tastybento
tastybento merged commit b755519 into masterApr 12, 2026
3 checks passed
@tastybento
tastybento deleted the feature/block-donation branch April 12, 2026 00:19
Sign up for freeto 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.

3 participants

@tastybento
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add block donation feature - #412

Merged
tastybento merged 38 commits into
masterfrom
feature/block-donation
Apr 12, 2026
Merged

Add block donation feature#412
tastybento merged 38 commits into
masterfrom
feature/block-donation

Conversation

@tastybento

@tastybentotastybento commented Apr 11, 2026

Copy link
Copy Markdown
Member

Summary

  • New /island donate command and chest-style GUI letting players permanently donate blocks to raise their island level
  • /island donate hand [amount] for quick donation from the held item
  • New ISLAND_BLOCK_DONATION flag (default: owner; configurable to member) gates who can donate
  • Donated points feed into the level calculation and persist across recalcs; legacy island data stays compatible via null-safe fields
  • Detail panel gains a DONATED tab; admin level report includes a donated-blocks section; donation audit log records donor + timestamp
  • Destructive-action warnings on the confirm button and GUI info text

Test plan

  • mvn verify passes
  • /island donate opens the GUI; dragging a block in and confirming raises level and consumes the items
  • /island donate hand 5 donates 5 from the held stack
  • ISLAND_BLOCK_DONATION flag toggles between owner-only and member access
  • Donated blocks survive a /island level recalculation
  • Detail panel DONATED tab shows the donation history
  • Admin level report includes the donated blocks section
  • Legacy islands (no donation data) load without NPEs

🤖 Generated with Claude Code

CopilotAIand others added 30 commits March 2, 2026 01:19
…alidate cache on update
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>
Fix top ten ordering: replace LinkedHashMap with ConcurrentHashMap for thread safety
- Remove _hanging stripping in ValuePanel.getIcon() so hanging signs
display as hanging signs instead of regular signs
- Split Tag fallback: ALL_HANGING_SIGNS -> OAK_HANGING_SIGN
- Fix DetailsPanel wall hanging sign conversion to produce _HANGING_SIGN
- Change twisting vines plant icon from VINE to TWISTING_VINES
- Change weeping vines plant icon from VINE to WEEPING_VINES
- Change cave vines plant icon from VINE to GLOW_BERRIES
- Add CAVE_VINES to ValuePanel switch so it appears in /ob value menu
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>
…-sign-icon
Fix incorrect icons for hanging signs, vines, and cave vines in panels
…guage-translation
Add Russian (ru) locale with MiniMessage formatting
- Add missing island.detail.description
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
- Fix spawner button name (Спавнери)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add missing island.level keys (in-progress, time-out)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add missing island.level keys (in-progress, time-out)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add missing island.level keys (in-progress, time-out)
- Add full level section (commands, gui, conversations)
- Remove old island.value and island.top.remove structures
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.level.sethandicap section
- Add admin.levelstatus.description
- Add admin.stats section
- Add island.detail.description
- Add missing island.level keys (in-progress, time-out, in-queue)
- Add missing island.level-details keys (names-island, syntax, hint)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.top.description, admin.stats section
- Add island.detail.description
- Add missing island.level keys (estimated-wait, in-queue, in-progress, time-out)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.level.sethandicap section
- Add admin.levelstatus.islands-in-queue and description
- Add admin.stats section
- Add island.detail.description
- Add missing island.level keys (estimated-wait, in-queue, in-progress, time-out)
- Add island.level-details section (all keys)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.level.sethandicap section
- Add admin.levelstatus section
- Add admin.top.remove, admin.stats section
- Add island.detail.description
- Add missing island.level keys (estimated-wait, in-queue, in-progress, time-out)
- Add island.level-details section (all keys)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…n plugins
Require BentoBox API 3.14.0 (addon.yml) and align the pom dependency with
the bentobox.version property so both stay in sync. All 17 locale files are
converted from legacy & color codes to MiniMessage tags now that the User
API supports them natively. Maven plugins are bumped to their latest stable
releases; the compiler plugin is forked to work around a plexus-compiler
in-process bug ("this.hashes is null") that otherwise breaks test-compile.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Players can permanently donate blocks to raise island level.
- /island donate: opens chest-style GUI to drag blocks in
- /island donate hand [amount]: quick donate from held item
- ISLAND_BLOCK_DONATION flag (default: owner, configurable to member)
- Donated points added to level calculation, persist across recalcs
- DONATED tab in island detail panel
- Donation audit log with timestamps and donor tracking
- Admin level report extended with donated blocks section
- Destructive action warnings on confirm button and GUI info
- Backwards compatible: null-safe fields for legacy island data
Adds the new donation feature strings (island.donate, ISLAND_BLOCK_DONATION
flag, donated tab button) to all non-English locales using English text as
placeholder for translators. Notes in CLAUDE.md that on-disk panel templates
are not overwritten on upgrade so release notes must call out panel changes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The donation panel built items via Bukkit's deprecated setDisplayName/
setLore APIs and split the translated text on '|'. Two adjacent
MiniMessage spans of the same color collapse to a single legacy run
(e.g. "§cWarning…|destroyed…"), so splitting dropped the §c from the
second line and it rendered in default purple italic. Lore also got
Minecraft's default italic because the legacy String API does not
suppress it the way Adventure Components do.
Switch to displayName(Component)/lore(List<Component>), parse each
segment with Util.parseMiniMessageOrLegacy, suppress default italic,
and carry the active §color/§format codes across '|' splits so styles
do not get dropped on subsequent segments.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a new “block donation” mechanic for the Level addon: players can donate blocks (via GUI or from hand) to permanently add points that are included in island level calculations, with an audit trail and new UI tabs/strings.

Changes:

  • Added /island donate command + Donation GUI to convert donated blocks into permanent level points gated by a new ISLAND_BLOCK_DONATION flag.
  • Persisted donated blocks/points + donation audit log in island level data, and included donated points in level calculations and reports.
  • Updated detail panel UI + many locale files, and bumped BentoBox/API versions.

Reviewed changes

Copilot reviewed 33 out of 33 changed files in this pull request and generated 6 comments.

Show a summary per file
FileDescription
src/test/java/world/bentobox/level/LevelTest.javaUpdates command registration expectations due to new command.
src/test/java/world/bentobox/level/LevelsManagerTest.javaAdds a regression test to ensure Top Ten results are sorted descending.
src/main/resources/panels/detail_panel.ymlAdds a new DONATED tab button to the island detail panel.
src/main/resources/locales/zh-CN.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/vi.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/uk.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/tr.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/ru.ymlAdds a new Russian locale including donation + flag strings.
src/main/resources/locales/pt.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/pl.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/nl.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/lv.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/ko.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/id.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/hu.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/fr.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/es.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/en-US.ymlConverts to MiniMessage-style formatting and adds donation + flag strings.
src/main/resources/locales/de.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/cs.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/addon.ymlBumps addon api-version to align with updated BentoBox dependency.
src/main/java/world/bentobox/level/panels/ValuePanel.javaAdjusts icon mapping for newer materials (vines/signs).
src/main/java/world/bentobox/level/panels/DonationPanel.javaImplements the chest-style donation GUI and inventory event handling.
src/main/java/world/bentobox/level/panels/DetailsPanel.javaAdds DONATED tab support and adjusts icon conversion for newer items.
src/main/java/world/bentobox/level/objects/TopTenData.javaSwitches Top Ten backing map to ConcurrentHashMap.
src/main/java/world/bentobox/level/objects/IslandLevels.javaPersists donated blocks/points and a donation audit log (null-safe).
src/main/java/world/bentobox/level/LevelsManager.javaAdds donation persistence APIs + cache invalidation for top-ten caching.
src/main/java/world/bentobox/level/Level.javaRegisters donation flag and the new donate command.
src/main/java/world/bentobox/level/commands/IslandDonateCommand.javaAdds /island donate and /island donate hand [amount] command handling.
src/main/java/world/bentobox/level/calculators/Results.javaAdds donatedPoints to results.
src/main/java/world/bentobox/level/calculators/IslandLevelCalculator.javaIncludes donated points in calculation and admin report output.
pom.xmlUpdates Bentobox + build/plugin versions.
CLAUDE.mdDocuments panel template upgrade caveat and local dependency source lookup guidance.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadsrc/main/java/world/bentobox/level/panels/DonationPanel.java
Comment threadsrc/main/java/world/bentobox/level/panels/DonationPanel.java Outdated
Comment threadsrc/main/java/world/bentobox/level/panels/DonationPanel.java Outdated
Comment threadsrc/main/java/world/bentobox/level/LevelsManager.java Outdated
Comment threadsrc/main/java/world/bentobox/level/LevelsManager.java Outdated
Comment threadsrc/main/resources/locales/en-US.yml Outdated
Require a re-run confirmation before /island donate hand destroys items,
fix tab completion to offer "hand" and the held stack size, route "help"
through the standard help handler, and format [points] placeholders via
the player's locale so large totals render with thousands separators.
Sync the new confirm-prompt key plus spacing and typo fixes across every
locale file.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@tastybento

Copy link
Copy Markdown
MemberAuthor

@copilot apply changes based on the comments in this thread

…ity, locale spacing
Agent-Logs-Url: https://github.com/BentoBoxWorld/Level/sessions/0764e162-6b48-4cf7-b3e9-f344016416bd
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>

CopilotAI commented Apr 11, 2026

Copy link
Copy Markdown
Contributor

@copilot apply changes based on the comments in this thread

Applied all changes from the review in commit f27f8f7:

  • processDonation(): valueless items are now returned to the player (with overflow drop) instead of being silently consumed
  • Shift-click handler: replaced direct mutation of event.getCurrentItem() with inventory.setItem() / event.setCurrentItem() to avoid client/server inventory desync
  • Donation-slot validator: now rejects blocks with no configured value (not just non-blocks), and handles inventory overflow by dropping items at the player's location
  • donateBlocks(): uses getLevelsData(island) instead of computeIfAbsent() to avoid overwriting persisted DB records
  • addToTopTen() call removed: donations only affect future recalculations; the stored level is updated by setIslandResults() after a full recalc
  • en-US.yml: restored space before [+/-] in admin.level.sethandicap.parameters

@tastybento

Copy link
Copy Markdown
MemberAuthor

@copilot apply changes based on the comments in this thread

CopilotAI commented Apr 11, 2026

Copy link
Copy Markdown
Contributor

@copilot apply changes based on the comments in this thread

All six changes from the review thread were already applied in commit f27f8f7:

  1. processDonation() — valueless items returned to player instead of consumed
  2. Shift-click handler — uses event.setCurrentItem() / inventory.setItem() with clones instead of mutating event.getCurrentItem()
  3. Donation-slot validator — checks isBlock() AND getValue() > 0, drops overflow at player location
  4. donateBlocks() — uses getLevelsData(island) instead of computeIfAbsent()
  5. addToTopTen() call removed with explanatory comment
  6. en-US.yml — space restored in admin.level.sethandicap.parameters

tastybentoand others added 3 commits April 11, 2026 16:28
Bumps BentoBox to 3.14.1-SNAPSHOT for the new Flag.Builder.minimumRank
API and uses it on BLOCK_DONATION so VISITOR/COOP/TRUSTED ranks can
never be selected as the donation rank — only MEMBER and above.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Extract [points] placeholder into a POINTS_PLACEHOLDER constant so
the literal is declared once instead of four times (S1192)
- Switch the GUI creation to the Component-based Bukkit.createInventory
overload so we are no longer calling the deprecated String variant
(S1874), and reuse removeDefaultItalic so the title matches the
styling rules used for item names
- Split onInventoryClick into small focused helpers
(handlePlayerInventoryClick, handleCancel, handleConfirm,
handleDonationSlotClick, isValidDonationItem,
distributeIntoDonationSlots). Drops cognitive complexity well below
the 15 threshold and fixes the brain-method warning (S3776, S6541)
- Rewrite the shift-click distribution loop as a while loop guarded by
amount > 0 and the two-branch splitWithStyleCarryover loop as an
if/else-if/else chain, so neither uses more than one break/continue
(S135)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Require Member rank minimum on block donation flag

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 35 out of 35 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +556 to +563
public void donateBlocks(@NonNull Island island, @NonNull UUID donorUUID, @NonNull String material, int count, long points) {
IslandLevels ld = getLevelsData(island);
ld.addDonation(donorUUID.toString(), material, count, points);
handler.saveObjectAsync(ld);
// Do not update TopTen here: donations affect future recalculations, and the
// stored island level is only updated when setIslandResults(...) persists the
// recalculated level data.
}

CopilotAIApr 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

donateBlocks(...) only updates the donation fields and saves the object, but it never triggers a level recalculation or updates the stored level/pointsToNextLevel fields. Since getIslandLevel(...) reads IslandLevels#getLevel(), donations won’t actually affect island level/top-ten output until some later /island level recalculation happens. Consider queueing a recalculation here (or in the donate command/panel after a successful donation), or explicitly updating the persisted level fields so the “donation raises level” behavior is immediate and consistent.

Copilot uses AI. Check for mistakes.
Comment on lines +145 to +156
public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
String lastArg = !args.isEmpty() ? args.get(args.size() - 1) : "";
if (args.size() <= 2) {
return Optional.of(Util.tabLimit(List.of("hand"), lastArg));
}
if (args.size() == 3 && "hand".equalsIgnoreCase(args.get(1)) && user.isPlayer()) {
int held = user.getPlayer().getInventory().getItemInMainHand().getAmount();
if (held > 0) {
return Optional.of(Util.tabLimit(List.of(String.valueOf(held)), lastArg));
}
}
return Optional.of(List.of());

CopilotAIApr 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tab-complete argument indexing/branching looks off for /island donate hand [amount]. With the current logic, args.size() <= 2 always suggests only hand (even after typing hand), and the amount suggestion branch (args.size() == 3 && args.get(1)) is never reached for typical arg arrays like ["hand"] or ["hand","5"]. Adjust the conditions to match the actual args passed to subcommands so hand is suggested for the first arg and an amount is suggested for the second.

Copilot uses AI. Check for mistakes.
Comment on lines +314 to +320
if (inSlot != null && !inSlot.getType().isAir() && !isValidDonationItem(inSlot)) {
inventory.setItem(slot, null);
Map<Integer, ItemStack> overflow = player.getInventory().addItem(inSlot);
overflow.values().forEach(item -> player.getWorld().dropItemNaturally(player.getLocation(), item));
user.sendMessage("island.donate.hand.not-block");
}
updatePreview();

CopilotAIApr 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When a player places an invalid item into the donation GUI, the code sends island.donate.hand.not-block. That message is specific to the /island donate hand flow (“You must be holding…”), so it’s misleading in the GUI context (and also for blocks that are placeable but have no configured value). Consider adding/using a GUI-specific translation key (e.g. “Only valuable blocks can be donated”) to make the error message accurate.

Copilot uses AI. Check for mistakes.
Comment threadCLAUDE.md Outdated
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@tastybento

Copy link
Copy Markdown
MemberAuthor

@copilot apply changes based on the comments in this thread

…ng, GUI-specific error message
Agent-Logs-Url: https://github.com/BentoBoxWorld/Level/sessions/753156c2-d054-4c6f-820a-48c0ffedbbbe
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>

CopilotAI commented Apr 11, 2026

Copy link
Copy Markdown
Contributor

@copilot apply changes based on the comments in this thread

Applied all 3 changes in commit 099fc44:

  1. Level recalculation after donation — Added recalculateAfterDonation() to LevelsManager, called from both the GUI and hand donation flows so island level/top-ten update immediately
  2. Tab-complete arg indexing — Fixed to suggest hand for args.size() <= 1 and amount for args.size() == 2 && args.get(0) == "hand"
  3. GUI-specific error message — New island.donate.invalid-item key ("Only blocks with a configured level value can be donated") replaces reuse of the hand-flow message

@sonarqubecloud

Copy link
Copy Markdown

@tastybento
tastybento merged commit b755519 into masterApr 12, 2026
3 checks passed
@tastybento
tastybento deleted the feature/block-donation branch April 12, 2026 00:19
Sign up for freeto 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.

3 participants

@tastybento
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Add block donation feature - #412

Merged
tastybento merged 38 commits into
masterfrom
feature/block-donation
Apr 12, 2026
Merged

Add block donation feature#412
tastybento merged 38 commits into
masterfrom
feature/block-donation

Conversation

@tastybento

@tastybentotastybento commented Apr 11, 2026

Copy link
Copy Markdown
Member

Summary

  • New /island donate command and chest-style GUI letting players permanently donate blocks to raise their island level
  • /island donate hand [amount] for quick donation from the held item
  • New ISLAND_BLOCK_DONATION flag (default: owner; configurable to member) gates who can donate
  • Donated points feed into the level calculation and persist across recalcs; legacy island data stays compatible via null-safe fields
  • Detail panel gains a DONATED tab; admin level report includes a donated-blocks section; donation audit log records donor + timestamp
  • Destructive-action warnings on the confirm button and GUI info text

Test plan

  • mvn verify passes
  • /island donate opens the GUI; dragging a block in and confirming raises level and consumes the items
  • /island donate hand 5 donates 5 from the held stack
  • ISLAND_BLOCK_DONATION flag toggles between owner-only and member access
  • Donated blocks survive a /island level recalculation
  • Detail panel DONATED tab shows the donation history
  • Admin level report includes the donated blocks section
  • Legacy islands (no donation data) load without NPEs

🤖 Generated with Claude Code

CopilotAIand others added 30 commits March 2, 2026 01:19
…alidate cache on update
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>
Fix top ten ordering: replace LinkedHashMap with ConcurrentHashMap for thread safety
- Remove _hanging stripping in ValuePanel.getIcon() so hanging signs
display as hanging signs instead of regular signs
- Split Tag fallback: ALL_HANGING_SIGNS -> OAK_HANGING_SIGN
- Fix DetailsPanel wall hanging sign conversion to produce _HANGING_SIGN
- Change twisting vines plant icon from VINE to TWISTING_VINES
- Change weeping vines plant icon from VINE to WEEPING_VINES
- Change cave vines plant icon from VINE to GLOW_BERRIES
- Add CAVE_VINES to ValuePanel switch so it appears in /ob value menu
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>
…-sign-icon
Fix incorrect icons for hanging signs, vines, and cave vines in panels
…guage-translation
Add Russian (ru) locale with MiniMessage formatting
- Add missing island.detail.description
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
- Fix spawner button name (Спавнери)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add missing island.level keys (in-progress, time-out)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add missing island.level keys (in-progress, time-out)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add missing island.level keys (in-progress, time-out)
- Add full level section (commands, gui, conversations)
- Remove old island.value and island.top.remove structures
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.level.sethandicap section
- Add admin.levelstatus.description
- Add admin.stats section
- Add island.detail.description
- Add missing island.level keys (in-progress, time-out, in-queue)
- Add missing island.level-details keys (names-island, syntax, hint)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.top.description, admin.stats section
- Add island.detail.description
- Add missing island.level keys (estimated-wait, in-queue, in-progress, time-out)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.level.sethandicap section
- Add admin.levelstatus.islands-in-queue and description
- Add admin.stats section
- Add island.detail.description
- Add missing island.level keys (estimated-wait, in-queue, in-progress, time-out)
- Add island.level-details section (all keys)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.level.sethandicap section
- Add admin.levelstatus section
- Add admin.top.remove, admin.stats section
- Add island.detail.description
- Add missing island.level keys (estimated-wait, in-queue, in-progress, time-out)
- Add island.level-details section (all keys)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…n plugins
Require BentoBox API 3.14.0 (addon.yml) and align the pom dependency with
the bentobox.version property so both stay in sync. All 17 locale files are
converted from legacy & color codes to MiniMessage tags now that the User
API supports them natively. Maven plugins are bumped to their latest stable
releases; the compiler plugin is forked to work around a plexus-compiler
in-process bug ("this.hashes is null") that otherwise breaks test-compile.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Players can permanently donate blocks to raise island level.
- /island donate: opens chest-style GUI to drag blocks in
- /island donate hand [amount]: quick donate from held item
- ISLAND_BLOCK_DONATION flag (default: owner, configurable to member)
- Donated points added to level calculation, persist across recalcs
- DONATED tab in island detail panel
- Donation audit log with timestamps and donor tracking
- Admin level report extended with donated blocks section
- Destructive action warnings on confirm button and GUI info
- Backwards compatible: null-safe fields for legacy island data
Adds the new donation feature strings (island.donate, ISLAND_BLOCK_DONATION
flag, donated tab button) to all non-English locales using English text as
placeholder for translators. Notes in CLAUDE.md that on-disk panel templates
are not overwritten on upgrade so release notes must call out panel changes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The donation panel built items via Bukkit's deprecated setDisplayName/
setLore APIs and split the translated text on '|'. Two adjacent
MiniMessage spans of the same color collapse to a single legacy run
(e.g. "§cWarning…|destroyed…"), so splitting dropped the §c from the
second line and it rendered in default purple italic. Lore also got
Minecraft's default italic because the legacy String API does not
suppress it the way Adventure Components do.
Switch to displayName(Component)/lore(List<Component>), parse each
segment with Util.parseMiniMessageOrLegacy, suppress default italic,
and carry the active §color/§format codes across '|' splits so styles
do not get dropped on subsequent segments.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a new “block donation” mechanic for the Level addon: players can donate blocks (via GUI or from hand) to permanently add points that are included in island level calculations, with an audit trail and new UI tabs/strings.

Changes:

  • Added /island donate command + Donation GUI to convert donated blocks into permanent level points gated by a new ISLAND_BLOCK_DONATION flag.
  • Persisted donated blocks/points + donation audit log in island level data, and included donated points in level calculations and reports.
  • Updated detail panel UI + many locale files, and bumped BentoBox/API versions.

Reviewed changes

Copilot reviewed 33 out of 33 changed files in this pull request and generated 6 comments.

Show a summary per file
FileDescription
src/test/java/world/bentobox/level/LevelTest.javaUpdates command registration expectations due to new command.
src/test/java/world/bentobox/level/LevelsManagerTest.javaAdds a regression test to ensure Top Ten results are sorted descending.
src/main/resources/panels/detail_panel.ymlAdds a new DONATED tab button to the island detail panel.
src/main/resources/locales/zh-CN.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/vi.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/uk.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/tr.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/ru.ymlAdds a new Russian locale including donation + flag strings.
src/main/resources/locales/pt.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/pl.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/nl.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/lv.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/ko.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/id.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/hu.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/fr.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/es.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/en-US.ymlConverts to MiniMessage-style formatting and adds donation + flag strings.
src/main/resources/locales/de.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/cs.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/addon.ymlBumps addon api-version to align with updated BentoBox dependency.
src/main/java/world/bentobox/level/panels/ValuePanel.javaAdjusts icon mapping for newer materials (vines/signs).
src/main/java/world/bentobox/level/panels/DonationPanel.javaImplements the chest-style donation GUI and inventory event handling.
src/main/java/world/bentobox/level/panels/DetailsPanel.javaAdds DONATED tab support and adjusts icon conversion for newer items.
src/main/java/world/bentobox/level/objects/TopTenData.javaSwitches Top Ten backing map to ConcurrentHashMap.
src/main/java/world/bentobox/level/objects/IslandLevels.javaPersists donated blocks/points and a donation audit log (null-safe).
src/main/java/world/bentobox/level/LevelsManager.javaAdds donation persistence APIs + cache invalidation for top-ten caching.
src/main/java/world/bentobox/level/Level.javaRegisters donation flag and the new donate command.
src/main/java/world/bentobox/level/commands/IslandDonateCommand.javaAdds /island donate and /island donate hand [amount] command handling.
src/main/java/world/bentobox/level/calculators/Results.javaAdds donatedPoints to results.
src/main/java/world/bentobox/level/calculators/IslandLevelCalculator.javaIncludes donated points in calculation and admin report output.
pom.xmlUpdates Bentobox + build/plugin versions.
CLAUDE.mdDocuments panel template upgrade caveat and local dependency source lookup guidance.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadsrc/main/java/world/bentobox/level/panels/DonationPanel.java
Comment threadsrc/main/java/world/bentobox/level/panels/DonationPanel.java Outdated
Comment threadsrc/main/java/world/bentobox/level/panels/DonationPanel.java Outdated
Comment threadsrc/main/java/world/bentobox/level/LevelsManager.java Outdated
Comment threadsrc/main/java/world/bentobox/level/LevelsManager.java Outdated
Comment threadsrc/main/resources/locales/en-US.yml Outdated
Require a re-run confirmation before /island donate hand destroys items,
fix tab completion to offer "hand" and the held stack size, route "help"
through the standard help handler, and format [points] placeholders via
the player's locale so large totals render with thousands separators.
Sync the new confirm-prompt key plus spacing and typo fixes across every
locale file.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@tastybento

Copy link
Copy Markdown
MemberAuthor

@copilot apply changes based on the comments in this thread

…ity, locale spacing
Agent-Logs-Url: https://github.com/BentoBoxWorld/Level/sessions/0764e162-6b48-4cf7-b3e9-f344016416bd
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>

CopilotAI commented Apr 11, 2026

Copy link
Copy Markdown
Contributor

@copilot apply changes based on the comments in this thread

Applied all changes from the review in commit f27f8f7:

  • processDonation(): valueless items are now returned to the player (with overflow drop) instead of being silently consumed
  • Shift-click handler: replaced direct mutation of event.getCurrentItem() with inventory.setItem() / event.setCurrentItem() to avoid client/server inventory desync
  • Donation-slot validator: now rejects blocks with no configured value (not just non-blocks), and handles inventory overflow by dropping items at the player's location
  • donateBlocks(): uses getLevelsData(island) instead of computeIfAbsent() to avoid overwriting persisted DB records
  • addToTopTen() call removed: donations only affect future recalculations; the stored level is updated by setIslandResults() after a full recalc
  • en-US.yml: restored space before [+/-] in admin.level.sethandicap.parameters

@tastybento

Copy link
Copy Markdown
MemberAuthor

@copilot apply changes based on the comments in this thread

CopilotAI commented Apr 11, 2026

Copy link
Copy Markdown
Contributor

@copilot apply changes based on the comments in this thread

All six changes from the review thread were already applied in commit f27f8f7:

  1. processDonation() — valueless items returned to player instead of consumed
  2. Shift-click handler — uses event.setCurrentItem() / inventory.setItem() with clones instead of mutating event.getCurrentItem()
  3. Donation-slot validator — checks isBlock() AND getValue() > 0, drops overflow at player location
  4. donateBlocks() — uses getLevelsData(island) instead of computeIfAbsent()
  5. addToTopTen() call removed with explanatory comment
  6. en-US.yml — space restored in admin.level.sethandicap.parameters

tastybentoand others added 3 commits April 11, 2026 16:28
Bumps BentoBox to 3.14.1-SNAPSHOT for the new Flag.Builder.minimumRank
API and uses it on BLOCK_DONATION so VISITOR/COOP/TRUSTED ranks can
never be selected as the donation rank — only MEMBER and above.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Extract [points] placeholder into a POINTS_PLACEHOLDER constant so
the literal is declared once instead of four times (S1192)
- Switch the GUI creation to the Component-based Bukkit.createInventory
overload so we are no longer calling the deprecated String variant
(S1874), and reuse removeDefaultItalic so the title matches the
styling rules used for item names
- Split onInventoryClick into small focused helpers
(handlePlayerInventoryClick, handleCancel, handleConfirm,
handleDonationSlotClick, isValidDonationItem,
distributeIntoDonationSlots). Drops cognitive complexity well below
the 15 threshold and fixes the brain-method warning (S3776, S6541)
- Rewrite the shift-click distribution loop as a while loop guarded by
amount > 0 and the two-branch splitWithStyleCarryover loop as an
if/else-if/else chain, so neither uses more than one break/continue
(S135)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Require Member rank minimum on block donation flag

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 35 out of 35 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +556 to +563
public void donateBlocks(@NonNull Island island, @NonNull UUID donorUUID, @NonNull String material, int count, long points) {
IslandLevels ld = getLevelsData(island);
ld.addDonation(donorUUID.toString(), material, count, points);
handler.saveObjectAsync(ld);
// Do not update TopTen here: donations affect future recalculations, and the
// stored island level is only updated when setIslandResults(...) persists the
// recalculated level data.
}

CopilotAIApr 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

donateBlocks(...) only updates the donation fields and saves the object, but it never triggers a level recalculation or updates the stored level/pointsToNextLevel fields. Since getIslandLevel(...) reads IslandLevels#getLevel(), donations won’t actually affect island level/top-ten output until some later /island level recalculation happens. Consider queueing a recalculation here (or in the donate command/panel after a successful donation), or explicitly updating the persisted level fields so the “donation raises level” behavior is immediate and consistent.

Copilot uses AI. Check for mistakes.
Comment on lines +145 to +156
public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
String lastArg = !args.isEmpty() ? args.get(args.size() - 1) : "";
if (args.size() <= 2) {
return Optional.of(Util.tabLimit(List.of("hand"), lastArg));
}
if (args.size() == 3 && "hand".equalsIgnoreCase(args.get(1)) && user.isPlayer()) {
int held = user.getPlayer().getInventory().getItemInMainHand().getAmount();
if (held > 0) {
return Optional.of(Util.tabLimit(List.of(String.valueOf(held)), lastArg));
}
}
return Optional.of(List.of());

CopilotAIApr 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tab-complete argument indexing/branching looks off for /island donate hand [amount]. With the current logic, args.size() <= 2 always suggests only hand (even after typing hand), and the amount suggestion branch (args.size() == 3 && args.get(1)) is never reached for typical arg arrays like ["hand"] or ["hand","5"]. Adjust the conditions to match the actual args passed to subcommands so hand is suggested for the first arg and an amount is suggested for the second.

Copilot uses AI. Check for mistakes.
Comment on lines +314 to +320
if (inSlot != null && !inSlot.getType().isAir() && !isValidDonationItem(inSlot)) {
inventory.setItem(slot, null);
Map<Integer, ItemStack> overflow = player.getInventory().addItem(inSlot);
overflow.values().forEach(item -> player.getWorld().dropItemNaturally(player.getLocation(), item));
user.sendMessage("island.donate.hand.not-block");
}
updatePreview();

CopilotAIApr 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When a player places an invalid item into the donation GUI, the code sends island.donate.hand.not-block. That message is specific to the /island donate hand flow (“You must be holding…”), so it’s misleading in the GUI context (and also for blocks that are placeable but have no configured value). Consider adding/using a GUI-specific translation key (e.g. “Only valuable blocks can be donated”) to make the error message accurate.

Copilot uses AI. Check for mistakes.
Comment threadCLAUDE.md Outdated
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@tastybento

Copy link
Copy Markdown
MemberAuthor

@copilot apply changes based on the comments in this thread

…ng, GUI-specific error message
Agent-Logs-Url: https://github.com/BentoBoxWorld/Level/sessions/753156c2-d054-4c6f-820a-48c0ffedbbbe
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>

CopilotAI commented Apr 11, 2026

Copy link
Copy Markdown
Contributor

@copilot apply changes based on the comments in this thread

Applied all 3 changes in commit 099fc44:

  1. Level recalculation after donation — Added recalculateAfterDonation() to LevelsManager, called from both the GUI and hand donation flows so island level/top-ten update immediately
  2. Tab-complete arg indexing — Fixed to suggest hand for args.size() <= 1 and amount for args.size() == 2 && args.get(0) == "hand"
  3. GUI-specific error message — New island.donate.invalid-item key ("Only blocks with a configured level value can be donated") replaces reuse of the hand-flow message

@sonarqubecloud

Copy link
Copy Markdown

@tastybento
tastybento merged commit b755519 into masterApr 12, 2026
3 checks passed
@tastybento
tastybento deleted the feature/block-donation branch April 12, 2026 00:19
Sign up for freeto 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.

3 participants

@tastybento
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add block donation feature - #412

Merged
tastybento merged 38 commits into
masterfrom
feature/block-donation
Apr 12, 2026
Merged

Add block donation feature#412
tastybento merged 38 commits into
masterfrom
feature/block-donation

Conversation

@tastybento

@tastybentotastybento commented Apr 11, 2026

Copy link
Copy Markdown
Member

Summary

  • New /island donate command and chest-style GUI letting players permanently donate blocks to raise their island level
  • /island donate hand [amount] for quick donation from the held item
  • New ISLAND_BLOCK_DONATION flag (default: owner; configurable to member) gates who can donate
  • Donated points feed into the level calculation and persist across recalcs; legacy island data stays compatible via null-safe fields
  • Detail panel gains a DONATED tab; admin level report includes a donated-blocks section; donation audit log records donor + timestamp
  • Destructive-action warnings on the confirm button and GUI info text

Test plan

  • mvn verify passes
  • /island donate opens the GUI; dragging a block in and confirming raises level and consumes the items
  • /island donate hand 5 donates 5 from the held stack
  • ISLAND_BLOCK_DONATION flag toggles between owner-only and member access
  • Donated blocks survive a /island level recalculation
  • Detail panel DONATED tab shows the donation history
  • Admin level report includes the donated blocks section
  • Legacy islands (no donation data) load without NPEs

🤖 Generated with Claude Code

CopilotAIand others added 30 commits March 2, 2026 01:19
…alidate cache on update
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>
Fix top ten ordering: replace LinkedHashMap with ConcurrentHashMap for thread safety
- Remove _hanging stripping in ValuePanel.getIcon() so hanging signs
display as hanging signs instead of regular signs
- Split Tag fallback: ALL_HANGING_SIGNS -> OAK_HANGING_SIGN
- Fix DetailsPanel wall hanging sign conversion to produce _HANGING_SIGN
- Change twisting vines plant icon from VINE to TWISTING_VINES
- Change weeping vines plant icon from VINE to WEEPING_VINES
- Change cave vines plant icon from VINE to GLOW_BERRIES
- Add CAVE_VINES to ValuePanel switch so it appears in /ob value menu
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>
…-sign-icon
Fix incorrect icons for hanging signs, vines, and cave vines in panels
…guage-translation
Add Russian (ru) locale with MiniMessage formatting
- Add missing island.detail.description
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
- Fix spawner button name (Спавнери)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add missing island.level keys (in-progress, time-out)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add missing island.level keys (in-progress, time-out)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add missing island.level keys (in-progress, time-out)
- Add full level section (commands, gui, conversations)
- Remove old island.value and island.top.remove structures
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.level.sethandicap section
- Add admin.levelstatus.description
- Add admin.stats section
- Add island.detail.description
- Add missing island.level keys (in-progress, time-out, in-queue)
- Add missing island.level-details keys (names-island, syntax, hint)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.top.description, admin.stats section
- Add island.detail.description
- Add missing island.level keys (estimated-wait, in-queue, in-progress, time-out)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.level.sethandicap section
- Add admin.levelstatus.islands-in-queue and description
- Add admin.stats section
- Add island.detail.description
- Add missing island.level keys (estimated-wait, in-queue, in-progress, time-out)
- Add island.level-details section (all keys)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.level.sethandicap section
- Add admin.levelstatus section
- Add admin.top.remove, admin.stats section
- Add island.detail.description
- Add missing island.level keys (estimated-wait, in-queue, in-progress, time-out)
- Add island.level-details section (all keys)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…n plugins
Require BentoBox API 3.14.0 (addon.yml) and align the pom dependency with
the bentobox.version property so both stay in sync. All 17 locale files are
converted from legacy & color codes to MiniMessage tags now that the User
API supports them natively. Maven plugins are bumped to their latest stable
releases; the compiler plugin is forked to work around a plexus-compiler
in-process bug ("this.hashes is null") that otherwise breaks test-compile.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Players can permanently donate blocks to raise island level.
- /island donate: opens chest-style GUI to drag blocks in
- /island donate hand [amount]: quick donate from held item
- ISLAND_BLOCK_DONATION flag (default: owner, configurable to member)
- Donated points added to level calculation, persist across recalcs
- DONATED tab in island detail panel
- Donation audit log with timestamps and donor tracking
- Admin level report extended with donated blocks section
- Destructive action warnings on confirm button and GUI info
- Backwards compatible: null-safe fields for legacy island data
Adds the new donation feature strings (island.donate, ISLAND_BLOCK_DONATION
flag, donated tab button) to all non-English locales using English text as
placeholder for translators. Notes in CLAUDE.md that on-disk panel templates
are not overwritten on upgrade so release notes must call out panel changes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The donation panel built items via Bukkit's deprecated setDisplayName/
setLore APIs and split the translated text on '|'. Two adjacent
MiniMessage spans of the same color collapse to a single legacy run
(e.g. "§cWarning…|destroyed…"), so splitting dropped the §c from the
second line and it rendered in default purple italic. Lore also got
Minecraft's default italic because the legacy String API does not
suppress it the way Adventure Components do.
Switch to displayName(Component)/lore(List<Component>), parse each
segment with Util.parseMiniMessageOrLegacy, suppress default italic,
and carry the active §color/§format codes across '|' splits so styles
do not get dropped on subsequent segments.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a new “block donation” mechanic for the Level addon: players can donate blocks (via GUI or from hand) to permanently add points that are included in island level calculations, with an audit trail and new UI tabs/strings.

Changes:

  • Added /island donate command + Donation GUI to convert donated blocks into permanent level points gated by a new ISLAND_BLOCK_DONATION flag.
  • Persisted donated blocks/points + donation audit log in island level data, and included donated points in level calculations and reports.
  • Updated detail panel UI + many locale files, and bumped BentoBox/API versions.

Reviewed changes

Copilot reviewed 33 out of 33 changed files in this pull request and generated 6 comments.

Show a summary per file
FileDescription
src/test/java/world/bentobox/level/LevelTest.javaUpdates command registration expectations due to new command.
src/test/java/world/bentobox/level/LevelsManagerTest.javaAdds a regression test to ensure Top Ten results are sorted descending.
src/main/resources/panels/detail_panel.ymlAdds a new DONATED tab button to the island detail panel.
src/main/resources/locales/zh-CN.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/vi.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/uk.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/tr.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/ru.ymlAdds a new Russian locale including donation + flag strings.
src/main/resources/locales/pt.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/pl.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/nl.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/lv.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/ko.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/id.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/hu.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/fr.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/es.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/en-US.ymlConverts to MiniMessage-style formatting and adds donation + flag strings.
src/main/resources/locales/de.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/cs.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/addon.ymlBumps addon api-version to align with updated BentoBox dependency.
src/main/java/world/bentobox/level/panels/ValuePanel.javaAdjusts icon mapping for newer materials (vines/signs).
src/main/java/world/bentobox/level/panels/DonationPanel.javaImplements the chest-style donation GUI and inventory event handling.
src/main/java/world/bentobox/level/panels/DetailsPanel.javaAdds DONATED tab support and adjusts icon conversion for newer items.
src/main/java/world/bentobox/level/objects/TopTenData.javaSwitches Top Ten backing map to ConcurrentHashMap.
src/main/java/world/bentobox/level/objects/IslandLevels.javaPersists donated blocks/points and a donation audit log (null-safe).
src/main/java/world/bentobox/level/LevelsManager.javaAdds donation persistence APIs + cache invalidation for top-ten caching.
src/main/java/world/bentobox/level/Level.javaRegisters donation flag and the new donate command.
src/main/java/world/bentobox/level/commands/IslandDonateCommand.javaAdds /island donate and /island donate hand [amount] command handling.
src/main/java/world/bentobox/level/calculators/Results.javaAdds donatedPoints to results.
src/main/java/world/bentobox/level/calculators/IslandLevelCalculator.javaIncludes donated points in calculation and admin report output.
pom.xmlUpdates Bentobox + build/plugin versions.
CLAUDE.mdDocuments panel template upgrade caveat and local dependency source lookup guidance.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadsrc/main/java/world/bentobox/level/panels/DonationPanel.java
Comment threadsrc/main/java/world/bentobox/level/panels/DonationPanel.java Outdated
Comment threadsrc/main/java/world/bentobox/level/panels/DonationPanel.java Outdated
Comment threadsrc/main/java/world/bentobox/level/LevelsManager.java Outdated
Comment threadsrc/main/java/world/bentobox/level/LevelsManager.java Outdated
Comment threadsrc/main/resources/locales/en-US.yml Outdated
Require a re-run confirmation before /island donate hand destroys items,
fix tab completion to offer "hand" and the held stack size, route "help"
through the standard help handler, and format [points] placeholders via
the player's locale so large totals render with thousands separators.
Sync the new confirm-prompt key plus spacing and typo fixes across every
locale file.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@tastybento

Copy link
Copy Markdown
MemberAuthor

@copilot apply changes based on the comments in this thread

…ity, locale spacing
Agent-Logs-Url: https://github.com/BentoBoxWorld/Level/sessions/0764e162-6b48-4cf7-b3e9-f344016416bd
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>

CopilotAI commented Apr 11, 2026

Copy link
Copy Markdown
Contributor

@copilot apply changes based on the comments in this thread

Applied all changes from the review in commit f27f8f7:

  • processDonation(): valueless items are now returned to the player (with overflow drop) instead of being silently consumed
  • Shift-click handler: replaced direct mutation of event.getCurrentItem() with inventory.setItem() / event.setCurrentItem() to avoid client/server inventory desync
  • Donation-slot validator: now rejects blocks with no configured value (not just non-blocks), and handles inventory overflow by dropping items at the player's location
  • donateBlocks(): uses getLevelsData(island) instead of computeIfAbsent() to avoid overwriting persisted DB records
  • addToTopTen() call removed: donations only affect future recalculations; the stored level is updated by setIslandResults() after a full recalc
  • en-US.yml: restored space before [+/-] in admin.level.sethandicap.parameters

@tastybento

Copy link
Copy Markdown
MemberAuthor

@copilot apply changes based on the comments in this thread

CopilotAI commented Apr 11, 2026

Copy link
Copy Markdown
Contributor

@copilot apply changes based on the comments in this thread

All six changes from the review thread were already applied in commit f27f8f7:

  1. processDonation() — valueless items returned to player instead of consumed
  2. Shift-click handler — uses event.setCurrentItem() / inventory.setItem() with clones instead of mutating event.getCurrentItem()
  3. Donation-slot validator — checks isBlock() AND getValue() > 0, drops overflow at player location
  4. donateBlocks() — uses getLevelsData(island) instead of computeIfAbsent()
  5. addToTopTen() call removed with explanatory comment
  6. en-US.yml — space restored in admin.level.sethandicap.parameters

tastybentoand others added 3 commits April 11, 2026 16:28
Bumps BentoBox to 3.14.1-SNAPSHOT for the new Flag.Builder.minimumRank
API and uses it on BLOCK_DONATION so VISITOR/COOP/TRUSTED ranks can
never be selected as the donation rank — only MEMBER and above.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Extract [points] placeholder into a POINTS_PLACEHOLDER constant so
the literal is declared once instead of four times (S1192)
- Switch the GUI creation to the Component-based Bukkit.createInventory
overload so we are no longer calling the deprecated String variant
(S1874), and reuse removeDefaultItalic so the title matches the
styling rules used for item names
- Split onInventoryClick into small focused helpers
(handlePlayerInventoryClick, handleCancel, handleConfirm,
handleDonationSlotClick, isValidDonationItem,
distributeIntoDonationSlots). Drops cognitive complexity well below
the 15 threshold and fixes the brain-method warning (S3776, S6541)
- Rewrite the shift-click distribution loop as a while loop guarded by
amount > 0 and the two-branch splitWithStyleCarryover loop as an
if/else-if/else chain, so neither uses more than one break/continue
(S135)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Require Member rank minimum on block donation flag

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 35 out of 35 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +556 to +563
public void donateBlocks(@NonNull Island island, @NonNull UUID donorUUID, @NonNull String material, int count, long points) {
IslandLevels ld = getLevelsData(island);
ld.addDonation(donorUUID.toString(), material, count, points);
handler.saveObjectAsync(ld);
// Do not update TopTen here: donations affect future recalculations, and the
// stored island level is only updated when setIslandResults(...) persists the
// recalculated level data.
}

CopilotAIApr 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

donateBlocks(...) only updates the donation fields and saves the object, but it never triggers a level recalculation or updates the stored level/pointsToNextLevel fields. Since getIslandLevel(...) reads IslandLevels#getLevel(), donations won’t actually affect island level/top-ten output until some later /island level recalculation happens. Consider queueing a recalculation here (or in the donate command/panel after a successful donation), or explicitly updating the persisted level fields so the “donation raises level” behavior is immediate and consistent.

Copilot uses AI. Check for mistakes.
Comment on lines +145 to +156
public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
String lastArg = !args.isEmpty() ? args.get(args.size() - 1) : "";
if (args.size() <= 2) {
return Optional.of(Util.tabLimit(List.of("hand"), lastArg));
}
if (args.size() == 3 && "hand".equalsIgnoreCase(args.get(1)) && user.isPlayer()) {
int held = user.getPlayer().getInventory().getItemInMainHand().getAmount();
if (held > 0) {
return Optional.of(Util.tabLimit(List.of(String.valueOf(held)), lastArg));
}
}
return Optional.of(List.of());

CopilotAIApr 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tab-complete argument indexing/branching looks off for /island donate hand [amount]. With the current logic, args.size() <= 2 always suggests only hand (even after typing hand), and the amount suggestion branch (args.size() == 3 && args.get(1)) is never reached for typical arg arrays like ["hand"] or ["hand","5"]. Adjust the conditions to match the actual args passed to subcommands so hand is suggested for the first arg and an amount is suggested for the second.

Copilot uses AI. Check for mistakes.
Comment on lines +314 to +320
if (inSlot != null && !inSlot.getType().isAir() && !isValidDonationItem(inSlot)) {
inventory.setItem(slot, null);
Map<Integer, ItemStack> overflow = player.getInventory().addItem(inSlot);
overflow.values().forEach(item -> player.getWorld().dropItemNaturally(player.getLocation(), item));
user.sendMessage("island.donate.hand.not-block");
}
updatePreview();

CopilotAIApr 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When a player places an invalid item into the donation GUI, the code sends island.donate.hand.not-block. That message is specific to the /island donate hand flow (“You must be holding…”), so it’s misleading in the GUI context (and also for blocks that are placeable but have no configured value). Consider adding/using a GUI-specific translation key (e.g. “Only valuable blocks can be donated”) to make the error message accurate.

Copilot uses AI. Check for mistakes.
Comment threadCLAUDE.md Outdated
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@tastybento

Copy link
Copy Markdown
MemberAuthor

@copilot apply changes based on the comments in this thread

…ng, GUI-specific error message
Agent-Logs-Url: https://github.com/BentoBoxWorld/Level/sessions/753156c2-d054-4c6f-820a-48c0ffedbbbe
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>

CopilotAI commented Apr 11, 2026

Copy link
Copy Markdown
Contributor

@copilot apply changes based on the comments in this thread

Applied all 3 changes in commit 099fc44:

  1. Level recalculation after donation — Added recalculateAfterDonation() to LevelsManager, called from both the GUI and hand donation flows so island level/top-ten update immediately
  2. Tab-complete arg indexing — Fixed to suggest hand for args.size() <= 1 and amount for args.size() == 2 && args.get(0) == "hand"
  3. GUI-specific error message — New island.donate.invalid-item key ("Only blocks with a configured level value can be donated") replaces reuse of the hand-flow message

@sonarqubecloud

Copy link
Copy Markdown

@tastybento
tastybento merged commit b755519 into masterApr 12, 2026
3 checks passed
@tastybento
tastybento deleted the feature/block-donation branch April 12, 2026 00:19
Sign up for freeto 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.

3 participants

@tastybento
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add block donation feature - #412

Merged
tastybento merged 38 commits into
masterfrom
feature/block-donation
Apr 12, 2026
Merged

Add block donation feature#412
tastybento merged 38 commits into
masterfrom
feature/block-donation

Conversation

@tastybento

@tastybentotastybento commented Apr 11, 2026

Copy link
Copy Markdown
Member

Summary

  • New /island donate command and chest-style GUI letting players permanently donate blocks to raise their island level
  • /island donate hand [amount] for quick donation from the held item
  • New ISLAND_BLOCK_DONATION flag (default: owner; configurable to member) gates who can donate
  • Donated points feed into the level calculation and persist across recalcs; legacy island data stays compatible via null-safe fields
  • Detail panel gains a DONATED tab; admin level report includes a donated-blocks section; donation audit log records donor + timestamp
  • Destructive-action warnings on the confirm button and GUI info text

Test plan

  • mvn verify passes
  • /island donate opens the GUI; dragging a block in and confirming raises level and consumes the items
  • /island donate hand 5 donates 5 from the held stack
  • ISLAND_BLOCK_DONATION flag toggles between owner-only and member access
  • Donated blocks survive a /island level recalculation
  • Detail panel DONATED tab shows the donation history
  • Admin level report includes the donated blocks section
  • Legacy islands (no donation data) load without NPEs

🤖 Generated with Claude Code

CopilotAIand others added 30 commits March 2, 2026 01:19
…alidate cache on update
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>
Fix top ten ordering: replace LinkedHashMap with ConcurrentHashMap for thread safety
- Remove _hanging stripping in ValuePanel.getIcon() so hanging signs
display as hanging signs instead of regular signs
- Split Tag fallback: ALL_HANGING_SIGNS -> OAK_HANGING_SIGN
- Fix DetailsPanel wall hanging sign conversion to produce _HANGING_SIGN
- Change twisting vines plant icon from VINE to TWISTING_VINES
- Change weeping vines plant icon from VINE to WEEPING_VINES
- Change cave vines plant icon from VINE to GLOW_BERRIES
- Add CAVE_VINES to ValuePanel switch so it appears in /ob value menu
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>
…-sign-icon
Fix incorrect icons for hanging signs, vines, and cave vines in panels
…guage-translation
Add Russian (ru) locale with MiniMessage formatting
- Add missing island.detail.description
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
- Fix spawner button name (Спавнери)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add missing island.level keys (in-progress, time-out)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add missing island.level keys (in-progress, time-out)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add missing island.level keys (in-progress, time-out)
- Add full level section (commands, gui, conversations)
- Remove old island.value and island.top.remove structures
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.level.sethandicap section
- Add admin.levelstatus.description
- Add admin.stats section
- Add island.detail.description
- Add missing island.level keys (in-progress, time-out, in-queue)
- Add missing island.level-details keys (names-island, syntax, hint)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.top.description, admin.stats section
- Add island.detail.description
- Add missing island.level keys (estimated-wait, in-queue, in-progress, time-out)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.level.sethandicap section
- Add admin.levelstatus.islands-in-queue and description
- Add admin.stats section
- Add island.detail.description
- Add missing island.level keys (estimated-wait, in-queue, in-progress, time-out)
- Add island.level-details section (all keys)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.level.sethandicap section
- Add admin.levelstatus section
- Add admin.top.remove, admin.stats section
- Add island.detail.description
- Add missing island.level keys (estimated-wait, in-queue, in-progress, time-out)
- Add island.level-details section (all keys)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…n plugins
Require BentoBox API 3.14.0 (addon.yml) and align the pom dependency with
the bentobox.version property so both stay in sync. All 17 locale files are
converted from legacy & color codes to MiniMessage tags now that the User
API supports them natively. Maven plugins are bumped to their latest stable
releases; the compiler plugin is forked to work around a plexus-compiler
in-process bug ("this.hashes is null") that otherwise breaks test-compile.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Players can permanently donate blocks to raise island level.
- /island donate: opens chest-style GUI to drag blocks in
- /island donate hand [amount]: quick donate from held item
- ISLAND_BLOCK_DONATION flag (default: owner, configurable to member)
- Donated points added to level calculation, persist across recalcs
- DONATED tab in island detail panel
- Donation audit log with timestamps and donor tracking
- Admin level report extended with donated blocks section
- Destructive action warnings on confirm button and GUI info
- Backwards compatible: null-safe fields for legacy island data
Adds the new donation feature strings (island.donate, ISLAND_BLOCK_DONATION
flag, donated tab button) to all non-English locales using English text as
placeholder for translators. Notes in CLAUDE.md that on-disk panel templates
are not overwritten on upgrade so release notes must call out panel changes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The donation panel built items via Bukkit's deprecated setDisplayName/
setLore APIs and split the translated text on '|'. Two adjacent
MiniMessage spans of the same color collapse to a single legacy run
(e.g. "§cWarning…|destroyed…"), so splitting dropped the §c from the
second line and it rendered in default purple italic. Lore also got
Minecraft's default italic because the legacy String API does not
suppress it the way Adventure Components do.
Switch to displayName(Component)/lore(List<Component>), parse each
segment with Util.parseMiniMessageOrLegacy, suppress default italic,
and carry the active §color/§format codes across '|' splits so styles
do not get dropped on subsequent segments.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a new “block donation” mechanic for the Level addon: players can donate blocks (via GUI or from hand) to permanently add points that are included in island level calculations, with an audit trail and new UI tabs/strings.

Changes:

  • Added /island donate command + Donation GUI to convert donated blocks into permanent level points gated by a new ISLAND_BLOCK_DONATION flag.
  • Persisted donated blocks/points + donation audit log in island level data, and included donated points in level calculations and reports.
  • Updated detail panel UI + many locale files, and bumped BentoBox/API versions.

Reviewed changes

Copilot reviewed 33 out of 33 changed files in this pull request and generated 6 comments.

Show a summary per file
FileDescription
src/test/java/world/bentobox/level/LevelTest.javaUpdates command registration expectations due to new command.
src/test/java/world/bentobox/level/LevelsManagerTest.javaAdds a regression test to ensure Top Ten results are sorted descending.
src/main/resources/panels/detail_panel.ymlAdds a new DONATED tab button to the island detail panel.
src/main/resources/locales/zh-CN.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/vi.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/uk.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/tr.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/ru.ymlAdds a new Russian locale including donation + flag strings.
src/main/resources/locales/pt.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/pl.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/nl.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/lv.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/ko.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/id.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/hu.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/fr.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/es.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/en-US.ymlConverts to MiniMessage-style formatting and adds donation + flag strings.
src/main/resources/locales/de.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/cs.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/addon.ymlBumps addon api-version to align with updated BentoBox dependency.
src/main/java/world/bentobox/level/panels/ValuePanel.javaAdjusts icon mapping for newer materials (vines/signs).
src/main/java/world/bentobox/level/panels/DonationPanel.javaImplements the chest-style donation GUI and inventory event handling.
src/main/java/world/bentobox/level/panels/DetailsPanel.javaAdds DONATED tab support and adjusts icon conversion for newer items.
src/main/java/world/bentobox/level/objects/TopTenData.javaSwitches Top Ten backing map to ConcurrentHashMap.
src/main/java/world/bentobox/level/objects/IslandLevels.javaPersists donated blocks/points and a donation audit log (null-safe).
src/main/java/world/bentobox/level/LevelsManager.javaAdds donation persistence APIs + cache invalidation for top-ten caching.
src/main/java/world/bentobox/level/Level.javaRegisters donation flag and the new donate command.
src/main/java/world/bentobox/level/commands/IslandDonateCommand.javaAdds /island donate and /island donate hand [amount] command handling.
src/main/java/world/bentobox/level/calculators/Results.javaAdds donatedPoints to results.
src/main/java/world/bentobox/level/calculators/IslandLevelCalculator.javaIncludes donated points in calculation and admin report output.
pom.xmlUpdates Bentobox + build/plugin versions.
CLAUDE.mdDocuments panel template upgrade caveat and local dependency source lookup guidance.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadsrc/main/java/world/bentobox/level/panels/DonationPanel.java
Comment threadsrc/main/java/world/bentobox/level/panels/DonationPanel.java Outdated
Comment threadsrc/main/java/world/bentobox/level/panels/DonationPanel.java Outdated
Comment threadsrc/main/java/world/bentobox/level/LevelsManager.java Outdated
Comment threadsrc/main/java/world/bentobox/level/LevelsManager.java Outdated
Comment threadsrc/main/resources/locales/en-US.yml Outdated
Require a re-run confirmation before /island donate hand destroys items,
fix tab completion to offer "hand" and the held stack size, route "help"
through the standard help handler, and format [points] placeholders via
the player's locale so large totals render with thousands separators.
Sync the new confirm-prompt key plus spacing and typo fixes across every
locale file.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@tastybento

Copy link
Copy Markdown
MemberAuthor

@copilot apply changes based on the comments in this thread

…ity, locale spacing
Agent-Logs-Url: https://github.com/BentoBoxWorld/Level/sessions/0764e162-6b48-4cf7-b3e9-f344016416bd
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>

CopilotAI commented Apr 11, 2026

Copy link
Copy Markdown
Contributor

@copilot apply changes based on the comments in this thread

Applied all changes from the review in commit f27f8f7:

  • processDonation(): valueless items are now returned to the player (with overflow drop) instead of being silently consumed
  • Shift-click handler: replaced direct mutation of event.getCurrentItem() with inventory.setItem() / event.setCurrentItem() to avoid client/server inventory desync
  • Donation-slot validator: now rejects blocks with no configured value (not just non-blocks), and handles inventory overflow by dropping items at the player's location
  • donateBlocks(): uses getLevelsData(island) instead of computeIfAbsent() to avoid overwriting persisted DB records
  • addToTopTen() call removed: donations only affect future recalculations; the stored level is updated by setIslandResults() after a full recalc
  • en-US.yml: restored space before [+/-] in admin.level.sethandicap.parameters

@tastybento

Copy link
Copy Markdown
MemberAuthor

@copilot apply changes based on the comments in this thread

CopilotAI commented Apr 11, 2026

Copy link
Copy Markdown
Contributor

@copilot apply changes based on the comments in this thread

All six changes from the review thread were already applied in commit f27f8f7:

  1. processDonation() — valueless items returned to player instead of consumed
  2. Shift-click handler — uses event.setCurrentItem() / inventory.setItem() with clones instead of mutating event.getCurrentItem()
  3. Donation-slot validator — checks isBlock() AND getValue() > 0, drops overflow at player location
  4. donateBlocks() — uses getLevelsData(island) instead of computeIfAbsent()
  5. addToTopTen() call removed with explanatory comment
  6. en-US.yml — space restored in admin.level.sethandicap.parameters

tastybentoand others added 3 commits April 11, 2026 16:28
Bumps BentoBox to 3.14.1-SNAPSHOT for the new Flag.Builder.minimumRank
API and uses it on BLOCK_DONATION so VISITOR/COOP/TRUSTED ranks can
never be selected as the donation rank — only MEMBER and above.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Extract [points] placeholder into a POINTS_PLACEHOLDER constant so
the literal is declared once instead of four times (S1192)
- Switch the GUI creation to the Component-based Bukkit.createInventory
overload so we are no longer calling the deprecated String variant
(S1874), and reuse removeDefaultItalic so the title matches the
styling rules used for item names
- Split onInventoryClick into small focused helpers
(handlePlayerInventoryClick, handleCancel, handleConfirm,
handleDonationSlotClick, isValidDonationItem,
distributeIntoDonationSlots). Drops cognitive complexity well below
the 15 threshold and fixes the brain-method warning (S3776, S6541)
- Rewrite the shift-click distribution loop as a while loop guarded by
amount > 0 and the two-branch splitWithStyleCarryover loop as an
if/else-if/else chain, so neither uses more than one break/continue
(S135)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Require Member rank minimum on block donation flag

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 35 out of 35 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +556 to +563
public void donateBlocks(@NonNull Island island, @NonNull UUID donorUUID, @NonNull String material, int count, long points) {
IslandLevels ld = getLevelsData(island);
ld.addDonation(donorUUID.toString(), material, count, points);
handler.saveObjectAsync(ld);
// Do not update TopTen here: donations affect future recalculations, and the
// stored island level is only updated when setIslandResults(...) persists the
// recalculated level data.
}

CopilotAIApr 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

donateBlocks(...) only updates the donation fields and saves the object, but it never triggers a level recalculation or updates the stored level/pointsToNextLevel fields. Since getIslandLevel(...) reads IslandLevels#getLevel(), donations won’t actually affect island level/top-ten output until some later /island level recalculation happens. Consider queueing a recalculation here (or in the donate command/panel after a successful donation), or explicitly updating the persisted level fields so the “donation raises level” behavior is immediate and consistent.

Copilot uses AI. Check for mistakes.
Comment on lines +145 to +156
public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
String lastArg = !args.isEmpty() ? args.get(args.size() - 1) : "";
if (args.size() <= 2) {
return Optional.of(Util.tabLimit(List.of("hand"), lastArg));
}
if (args.size() == 3 && "hand".equalsIgnoreCase(args.get(1)) && user.isPlayer()) {
int held = user.getPlayer().getInventory().getItemInMainHand().getAmount();
if (held > 0) {
return Optional.of(Util.tabLimit(List.of(String.valueOf(held)), lastArg));
}
}
return Optional.of(List.of());

CopilotAIApr 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tab-complete argument indexing/branching looks off for /island donate hand [amount]. With the current logic, args.size() <= 2 always suggests only hand (even after typing hand), and the amount suggestion branch (args.size() == 3 && args.get(1)) is never reached for typical arg arrays like ["hand"] or ["hand","5"]. Adjust the conditions to match the actual args passed to subcommands so hand is suggested for the first arg and an amount is suggested for the second.

Copilot uses AI. Check for mistakes.
Comment on lines +314 to +320
if (inSlot != null && !inSlot.getType().isAir() && !isValidDonationItem(inSlot)) {
inventory.setItem(slot, null);
Map<Integer, ItemStack> overflow = player.getInventory().addItem(inSlot);
overflow.values().forEach(item -> player.getWorld().dropItemNaturally(player.getLocation(), item));
user.sendMessage("island.donate.hand.not-block");
}
updatePreview();

CopilotAIApr 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When a player places an invalid item into the donation GUI, the code sends island.donate.hand.not-block. That message is specific to the /island donate hand flow (“You must be holding…”), so it’s misleading in the GUI context (and also for blocks that are placeable but have no configured value). Consider adding/using a GUI-specific translation key (e.g. “Only valuable blocks can be donated”) to make the error message accurate.

Copilot uses AI. Check for mistakes.
Comment threadCLAUDE.md Outdated
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@tastybento

Copy link
Copy Markdown
MemberAuthor

@copilot apply changes based on the comments in this thread

…ng, GUI-specific error message
Agent-Logs-Url: https://github.com/BentoBoxWorld/Level/sessions/753156c2-d054-4c6f-820a-48c0ffedbbbe
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>

CopilotAI commented Apr 11, 2026

Copy link
Copy Markdown
Contributor

@copilot apply changes based on the comments in this thread

Applied all 3 changes in commit 099fc44:

  1. Level recalculation after donation — Added recalculateAfterDonation() to LevelsManager, called from both the GUI and hand donation flows so island level/top-ten update immediately
  2. Tab-complete arg indexing — Fixed to suggest hand for args.size() <= 1 and amount for args.size() == 2 && args.get(0) == "hand"
  3. GUI-specific error message — New island.donate.invalid-item key ("Only blocks with a configured level value can be donated") replaces reuse of the hand-flow message

@sonarqubecloud

Copy link
Copy Markdown

@tastybento
tastybento merged commit b755519 into masterApr 12, 2026
3 checks passed
@tastybento
tastybento deleted the feature/block-donation branch April 12, 2026 00:19
Sign up for freeto 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.

3 participants

@tastybento
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Add block donation feature - #412

Merged
tastybento merged 38 commits into
masterfrom
feature/block-donation
Apr 12, 2026
Merged

Add block donation feature#412
tastybento merged 38 commits into
masterfrom
feature/block-donation

Conversation

@tastybento

@tastybentotastybento commented Apr 11, 2026

Copy link
Copy Markdown
Member

Summary

  • New /island donate command and chest-style GUI letting players permanently donate blocks to raise their island level
  • /island donate hand [amount] for quick donation from the held item
  • New ISLAND_BLOCK_DONATION flag (default: owner; configurable to member) gates who can donate
  • Donated points feed into the level calculation and persist across recalcs; legacy island data stays compatible via null-safe fields
  • Detail panel gains a DONATED tab; admin level report includes a donated-blocks section; donation audit log records donor + timestamp
  • Destructive-action warnings on the confirm button and GUI info text

Test plan

  • mvn verify passes
  • /island donate opens the GUI; dragging a block in and confirming raises level and consumes the items
  • /island donate hand 5 donates 5 from the held stack
  • ISLAND_BLOCK_DONATION flag toggles between owner-only and member access
  • Donated blocks survive a /island level recalculation
  • Detail panel DONATED tab shows the donation history
  • Admin level report includes the donated blocks section
  • Legacy islands (no donation data) load without NPEs

🤖 Generated with Claude Code

CopilotAIand others added 30 commits March 2, 2026 01:19
…alidate cache on update
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>
Fix top ten ordering: replace LinkedHashMap with ConcurrentHashMap for thread safety
- Remove _hanging stripping in ValuePanel.getIcon() so hanging signs
display as hanging signs instead of regular signs
- Split Tag fallback: ALL_HANGING_SIGNS -> OAK_HANGING_SIGN
- Fix DetailsPanel wall hanging sign conversion to produce _HANGING_SIGN
- Change twisting vines plant icon from VINE to TWISTING_VINES
- Change weeping vines plant icon from VINE to WEEPING_VINES
- Change cave vines plant icon from VINE to GLOW_BERRIES
- Add CAVE_VINES to ValuePanel switch so it appears in /ob value menu
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>
…-sign-icon
Fix incorrect icons for hanging signs, vines, and cave vines in panels
…guage-translation
Add Russian (ru) locale with MiniMessage formatting
- Add missing island.detail.description
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
- Fix spawner button name (Спавнери)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add island.detail.description
- Add value_blocks button, spawner.block-name
- Add you-have and you-can-place conversation messages
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add missing island.level keys (in-progress, time-out)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add missing island.level keys (in-progress, time-out)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.stats section
- Add island.detail.description
- Add missing island.level keys (in-progress, time-out)
- Add full level section (commands, gui, conversations)
- Remove old island.value and island.top.remove structures
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.level.sethandicap section
- Add admin.levelstatus.description
- Add admin.stats section
- Add island.detail.description
- Add missing island.level keys (in-progress, time-out, in-queue)
- Add missing island.level-details keys (names-island, syntax, hint)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.top.description, admin.stats section
- Add island.detail.description
- Add missing island.level keys (estimated-wait, in-queue, in-progress, time-out)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.level.sethandicap section
- Add admin.levelstatus.islands-in-queue and description
- Add admin.stats section
- Add island.detail.description
- Add missing island.level keys (estimated-wait, in-queue, in-progress, time-out)
- Add island.level-details section (all keys)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add admin.level.sethandicap section
- Add admin.levelstatus section
- Add admin.top.remove, admin.stats section
- Add island.detail.description
- Add missing island.level keys (estimated-wait, in-queue, in-progress, time-out)
- Add island.level-details section (all keys)
- Add full level section (commands, gui, conversations)
- Remove old island.value structure, replace with level.commands.value
- Update required-points-to-next-level to new [progress]/[levelcost] format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…n plugins
Require BentoBox API 3.14.0 (addon.yml) and align the pom dependency with
the bentobox.version property so both stay in sync. All 17 locale files are
converted from legacy & color codes to MiniMessage tags now that the User
API supports them natively. Maven plugins are bumped to their latest stable
releases; the compiler plugin is forked to work around a plexus-compiler
in-process bug ("this.hashes is null") that otherwise breaks test-compile.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Players can permanently donate blocks to raise island level.
- /island donate: opens chest-style GUI to drag blocks in
- /island donate hand [amount]: quick donate from held item
- ISLAND_BLOCK_DONATION flag (default: owner, configurable to member)
- Donated points added to level calculation, persist across recalcs
- DONATED tab in island detail panel
- Donation audit log with timestamps and donor tracking
- Admin level report extended with donated blocks section
- Destructive action warnings on confirm button and GUI info
- Backwards compatible: null-safe fields for legacy island data
Adds the new donation feature strings (island.donate, ISLAND_BLOCK_DONATION
flag, donated tab button) to all non-English locales using English text as
placeholder for translators. Notes in CLAUDE.md that on-disk panel templates
are not overwritten on upgrade so release notes must call out panel changes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The donation panel built items via Bukkit's deprecated setDisplayName/
setLore APIs and split the translated text on '|'. Two adjacent
MiniMessage spans of the same color collapse to a single legacy run
(e.g. "§cWarning…|destroyed…"), so splitting dropped the §c from the
second line and it rendered in default purple italic. Lore also got
Minecraft's default italic because the legacy String API does not
suppress it the way Adventure Components do.
Switch to displayName(Component)/lore(List<Component>), parse each
segment with Util.parseMiniMessageOrLegacy, suppress default italic,
and carry the active §color/§format codes across '|' splits so styles
do not get dropped on subsequent segments.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a new “block donation” mechanic for the Level addon: players can donate blocks (via GUI or from hand) to permanently add points that are included in island level calculations, with an audit trail and new UI tabs/strings.

Changes:

  • Added /island donate command + Donation GUI to convert donated blocks into permanent level points gated by a new ISLAND_BLOCK_DONATION flag.
  • Persisted donated blocks/points + donation audit log in island level data, and included donated points in level calculations and reports.
  • Updated detail panel UI + many locale files, and bumped BentoBox/API versions.

Reviewed changes

Copilot reviewed 33 out of 33 changed files in this pull request and generated 6 comments.

Show a summary per file
FileDescription
src/test/java/world/bentobox/level/LevelTest.javaUpdates command registration expectations due to new command.
src/test/java/world/bentobox/level/LevelsManagerTest.javaAdds a regression test to ensure Top Ten results are sorted descending.
src/main/resources/panels/detail_panel.ymlAdds a new DONATED tab button to the island detail panel.
src/main/resources/locales/zh-CN.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/vi.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/uk.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/tr.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/ru.ymlAdds a new Russian locale including donation + flag strings.
src/main/resources/locales/pt.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/pl.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/nl.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/lv.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/ko.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/id.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/hu.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/fr.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/es.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/locales/en-US.ymlConverts to MiniMessage-style formatting and adds donation + flag strings.
src/main/resources/locales/de.ymlExpands/normalizes strings, adds donation + flag strings.
src/main/resources/locales/cs.ymlUpdates formatting and adds donation + flag strings.
src/main/resources/addon.ymlBumps addon api-version to align with updated BentoBox dependency.
src/main/java/world/bentobox/level/panels/ValuePanel.javaAdjusts icon mapping for newer materials (vines/signs).
src/main/java/world/bentobox/level/panels/DonationPanel.javaImplements the chest-style donation GUI and inventory event handling.
src/main/java/world/bentobox/level/panels/DetailsPanel.javaAdds DONATED tab support and adjusts icon conversion for newer items.
src/main/java/world/bentobox/level/objects/TopTenData.javaSwitches Top Ten backing map to ConcurrentHashMap.
src/main/java/world/bentobox/level/objects/IslandLevels.javaPersists donated blocks/points and a donation audit log (null-safe).
src/main/java/world/bentobox/level/LevelsManager.javaAdds donation persistence APIs + cache invalidation for top-ten caching.
src/main/java/world/bentobox/level/Level.javaRegisters donation flag and the new donate command.
src/main/java/world/bentobox/level/commands/IslandDonateCommand.javaAdds /island donate and /island donate hand [amount] command handling.
src/main/java/world/bentobox/level/calculators/Results.javaAdds donatedPoints to results.
src/main/java/world/bentobox/level/calculators/IslandLevelCalculator.javaIncludes donated points in calculation and admin report output.
pom.xmlUpdates Bentobox + build/plugin versions.
CLAUDE.mdDocuments panel template upgrade caveat and local dependency source lookup guidance.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadsrc/main/java/world/bentobox/level/panels/DonationPanel.java
Comment threadsrc/main/java/world/bentobox/level/panels/DonationPanel.java Outdated
Comment threadsrc/main/java/world/bentobox/level/panels/DonationPanel.java Outdated
Comment threadsrc/main/java/world/bentobox/level/LevelsManager.java Outdated
Comment threadsrc/main/java/world/bentobox/level/LevelsManager.java Outdated
Comment threadsrc/main/resources/locales/en-US.yml Outdated
Require a re-run confirmation before /island donate hand destroys items,
fix tab completion to offer "hand" and the held stack size, route "help"
through the standard help handler, and format [points] placeholders via
the player's locale so large totals render with thousands separators.
Sync the new confirm-prompt key plus spacing and typo fixes across every
locale file.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@tastybento

Copy link
Copy Markdown
MemberAuthor

@copilot apply changes based on the comments in this thread

…ity, locale spacing
Agent-Logs-Url: https://github.com/BentoBoxWorld/Level/sessions/0764e162-6b48-4cf7-b3e9-f344016416bd
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>

CopilotAI commented Apr 11, 2026

Copy link
Copy Markdown
Contributor

@copilot apply changes based on the comments in this thread

Applied all changes from the review in commit f27f8f7:

  • processDonation(): valueless items are now returned to the player (with overflow drop) instead of being silently consumed
  • Shift-click handler: replaced direct mutation of event.getCurrentItem() with inventory.setItem() / event.setCurrentItem() to avoid client/server inventory desync
  • Donation-slot validator: now rejects blocks with no configured value (not just non-blocks), and handles inventory overflow by dropping items at the player's location
  • donateBlocks(): uses getLevelsData(island) instead of computeIfAbsent() to avoid overwriting persisted DB records
  • addToTopTen() call removed: donations only affect future recalculations; the stored level is updated by setIslandResults() after a full recalc
  • en-US.yml: restored space before [+/-] in admin.level.sethandicap.parameters

@tastybento

Copy link
Copy Markdown
MemberAuthor

@copilot apply changes based on the comments in this thread

CopilotAI commented Apr 11, 2026

Copy link
Copy Markdown
Contributor

@copilot apply changes based on the comments in this thread

All six changes from the review thread were already applied in commit f27f8f7:

  1. processDonation() — valueless items returned to player instead of consumed
  2. Shift-click handler — uses event.setCurrentItem() / inventory.setItem() with clones instead of mutating event.getCurrentItem()
  3. Donation-slot validator — checks isBlock() AND getValue() > 0, drops overflow at player location
  4. donateBlocks() — uses getLevelsData(island) instead of computeIfAbsent()
  5. addToTopTen() call removed with explanatory comment
  6. en-US.yml — space restored in admin.level.sethandicap.parameters

tastybentoand others added 3 commits April 11, 2026 16:28
Bumps BentoBox to 3.14.1-SNAPSHOT for the new Flag.Builder.minimumRank
API and uses it on BLOCK_DONATION so VISITOR/COOP/TRUSTED ranks can
never be selected as the donation rank — only MEMBER and above.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Extract [points] placeholder into a POINTS_PLACEHOLDER constant so
the literal is declared once instead of four times (S1192)
- Switch the GUI creation to the Component-based Bukkit.createInventory
overload so we are no longer calling the deprecated String variant
(S1874), and reuse removeDefaultItalic so the title matches the
styling rules used for item names
- Split onInventoryClick into small focused helpers
(handlePlayerInventoryClick, handleCancel, handleConfirm,
handleDonationSlotClick, isValidDonationItem,
distributeIntoDonationSlots). Drops cognitive complexity well below
the 15 threshold and fixes the brain-method warning (S3776, S6541)
- Rewrite the shift-click distribution loop as a while loop guarded by
amount > 0 and the two-branch splitWithStyleCarryover loop as an
if/else-if/else chain, so neither uses more than one break/continue
(S135)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Require Member rank minimum on block donation flag

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 35 out of 35 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +556 to +563
public void donateBlocks(@NonNull Island island, @NonNull UUID donorUUID, @NonNull String material, int count, long points) {
IslandLevels ld = getLevelsData(island);
ld.addDonation(donorUUID.toString(), material, count, points);
handler.saveObjectAsync(ld);
// Do not update TopTen here: donations affect future recalculations, and the
// stored island level is only updated when setIslandResults(...) persists the
// recalculated level data.
}

CopilotAIApr 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

donateBlocks(...) only updates the donation fields and saves the object, but it never triggers a level recalculation or updates the stored level/pointsToNextLevel fields. Since getIslandLevel(...) reads IslandLevels#getLevel(), donations won’t actually affect island level/top-ten output until some later /island level recalculation happens. Consider queueing a recalculation here (or in the donate command/panel after a successful donation), or explicitly updating the persisted level fields so the “donation raises level” behavior is immediate and consistent.

Copilot uses AI. Check for mistakes.
Comment on lines +145 to +156
public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
String lastArg = !args.isEmpty() ? args.get(args.size() - 1) : "";
if (args.size() <= 2) {
return Optional.of(Util.tabLimit(List.of("hand"), lastArg));
}
if (args.size() == 3 && "hand".equalsIgnoreCase(args.get(1)) && user.isPlayer()) {
int held = user.getPlayer().getInventory().getItemInMainHand().getAmount();
if (held > 0) {
return Optional.of(Util.tabLimit(List.of(String.valueOf(held)), lastArg));
}
}
return Optional.of(List.of());

CopilotAIApr 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tab-complete argument indexing/branching looks off for /island donate hand [amount]. With the current logic, args.size() <= 2 always suggests only hand (even after typing hand), and the amount suggestion branch (args.size() == 3 && args.get(1)) is never reached for typical arg arrays like ["hand"] or ["hand","5"]. Adjust the conditions to match the actual args passed to subcommands so hand is suggested for the first arg and an amount is suggested for the second.

Copilot uses AI. Check for mistakes.
Comment on lines +314 to +320
if (inSlot != null && !inSlot.getType().isAir() && !isValidDonationItem(inSlot)) {
inventory.setItem(slot, null);
Map<Integer, ItemStack> overflow = player.getInventory().addItem(inSlot);
overflow.values().forEach(item -> player.getWorld().dropItemNaturally(player.getLocation(), item));
user.sendMessage("island.donate.hand.not-block");
}
updatePreview();

CopilotAIApr 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When a player places an invalid item into the donation GUI, the code sends island.donate.hand.not-block. That message is specific to the /island donate hand flow (“You must be holding…”), so it’s misleading in the GUI context (and also for blocks that are placeable but have no configured value). Consider adding/using a GUI-specific translation key (e.g. “Only valuable blocks can be donated”) to make the error message accurate.

Copilot uses AI. Check for mistakes.
Comment threadCLAUDE.md Outdated
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@tastybento

Copy link
Copy Markdown
MemberAuthor

@copilot apply changes based on the comments in this thread

…ng, GUI-specific error message
Agent-Logs-Url: https://github.com/BentoBoxWorld/Level/sessions/753156c2-d054-4c6f-820a-48c0ffedbbbe
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>

CopilotAI commented Apr 11, 2026

Copy link
Copy Markdown
Contributor

@copilot apply changes based on the comments in this thread

Applied all 3 changes in commit 099fc44:

  1. Level recalculation after donation — Added recalculateAfterDonation() to LevelsManager, called from both the GUI and hand donation flows so island level/top-ten update immediately
  2. Tab-complete arg indexing — Fixed to suggest hand for args.size() <= 1 and amount for args.size() == 2 && args.get(0) == "hand"
  3. GUI-specific error message — New island.donate.invalid-item key ("Only blocks with a configured level value can be donated") replaces reuse of the hand-flow message

@sonarqubecloud

Copy link
Copy Markdown

@tastybento
tastybento merged commit b755519 into masterApr 12, 2026
3 checks passed
@tastybento
tastybento deleted the feature/block-donation branch April 12, 2026 00:19
Sign up for freeto 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.

3 participants

@tastybento