Release 2.27.0 - #431

Merged
tastybento merged 24 commits into
masterfrom
develop
May 13, 2026
Merged

Release 2.27.0#431
tastybento merged 24 commits into
masterfrom
develop

Conversation

@tastybento

Copy link
Copy Markdown
Member

No description provided.

tastybentoand others added 18 commits May 3, 2026 22:10
Adds a confirmable "inv" subcommand that scans the player's inventory
for donatable blocks, lists each material with its point value plus a
total in the confirmation prompt, and on confirm donates all of them
in one go. Items with no value or that are not donatable blocks remain
in the inventory.
Also fixes the donate tab-complete: the args list BentoBox passes to a
subcommand includes the leaf label at index 0, so the previous
size-1 check never fired in real use and only the auto "help"
suggestion appeared. Tests now exercise the realistic args shape.
Bumps build version to 2.27.0.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds the four new island.donate.inv keys (keyword, confirm-header,
confirm-line, confirm-total) to every non-English locale file. MiniMessage
tags and placeholders are preserved verbatim; only the human-readable
text was translated.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Addresses SonarCloud findings about duplicated string literals in
IslandDonateCommand.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
feat: /island donate inv — donate everything from inventory
…e, detail, and donate menus
Agent-Logs-Url: https://github.com/BentoBoxWorld/Level/sessions/daf183a6-549f-4946-900c-5719c0a27e81
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>
…inv donation value
Agent-Logs-Url: https://github.com/BentoBoxWorld/Level/sessions/daf183a6-549f-4946-900c-5719c0a27e81
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>
FIXED: Negative values in progression while using a non-linear function.
The forward and backward point-boundary scans could each iterate up to
10M times calling calculateLevel() (string parse + eval) on the primary
thread. Binary search reduces this to ~23 iterations. Also adds missing
ResultsTest coverage for pointsFromCurrentLevel.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…upport-menu
Add custom block support (Oraxen/Nexo/ItemsAdder/CraftEngine) in value, detail, and donate menus
The /is value panel rendered Oraxen/Nexo/ItemsAdder blocks as paper with
the prettified config key as the name. Look up the real ItemStack from
the plugin's registry and use it as the icon, plus the item meta display
name when present. Lookup helper is extracted to Utils so DetailsPanel
and ValuePanel share it.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…and-name
Fix custom-block icon and display name in value panel (#426)
Three call sites were missing CraftEngine support, so /is value hand
returned "no value" for held CraftEngine items, the value panel showed
a paper icon with the prettified namespaced key, and the chat output
used the raw key instead of the configured display name:
- Level.getCustomBlockId now checks CraftEngineHook.getItemId, so a
held custom item is mapped to its namespaced ID.
- Utils.getCustomBlockItemStack now delegates to
CraftEngineHook.getItemStack so the panel renders the real icon.
- Utils.getCustomBlockDisplayName now also reads the modern
minecraft:item_name component (hasItemName/getItemName) used by
CraftEngine, in addition to the legacy display.Name used by Oraxen,
Nexo, and ItemsAdder.
- IslandValueCommand.printValue routes string IDs through the same
getCustomBlockItemStack/getCustomBlockDisplayName path used by the
panel, so the chat message shows the configured display name.
Requires BentoBox >= 3.15.1-SNAPSHOT (BentoBoxWorld/BentoBox#2973 for
the new getItemId helper).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…y-name
fix: recognize CraftEngine items in value lookups (#428)

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

Release 2.27.0 expands Level’s donation and custom-block support, improves level-progress reporting for non-linear formulas, and updates project/version metadata.

Changes:

  • Add /island donate inv flow (tab-complete, confirmation prompt, inventory scan + donation logging) and localize new messages.
  • Improve custom-block rendering by resolving representative ItemStacks (Oraxen/Nexo/ItemsAdder/CraftEngine) and using item meta display names in panels/commands.
  • Compute “points within current level” and use it to show accurate level progress for non-linear level formulas; bump addon + dependency versions.

Reviewed changes

Copilot reviewed 31 out of 31 changed files in this pull request and generated 2 comments.

Show a summary per file
FileDescription
src/main/java/world/bentobox/level/commands/IslandDonateCommand.javaAdds inv subcommand, inventory donation execution, and revised tab-complete logic.
src/test/java/world/bentobox/level/commands/IslandDonateCommandTest.javaAdds tab-complete and inv donation tests.
src/main/resources/locales/en-US.ymlUpdates donate usage string; adds donate.inv.* messages.
src/main/resources/locales/cs.ymlAdds donate.inv.* messages.
src/main/resources/locales/de.ymlAdds donate.inv.* messages.
src/main/resources/locales/es.ymlAdds donate.inv.* messages.
src/main/resources/locales/fr.ymlAdds donate.inv.* messages.
src/main/resources/locales/hu.ymlAdds donate.inv.* messages.
src/main/resources/locales/id.ymlAdds donate.inv.* messages.
src/main/resources/locales/ko.ymlAdds donate.inv.* messages.
src/main/resources/locales/lv.ymlAdds donate.inv.* messages.
src/main/resources/locales/nl.ymlAdds donate.inv.* messages.
src/main/resources/locales/pl.ymlAdds donate.inv.* messages.
src/main/resources/locales/pt.ymlAdds donate.inv.* messages.
src/main/resources/locales/ru.ymlAdds donate.inv.* messages.
src/main/resources/locales/tr.ymlAdds donate.inv.* messages.
src/main/resources/locales/uk.ymlAdds donate.inv.* messages.
src/main/resources/locales/vi.ymlAdds donate.inv.* messages.
src/main/resources/locales/zh-CN.ymlAdds donate.inv.* messages.
src/main/java/world/bentobox/level/util/Utils.javaAdds helpers to resolve custom-block ItemStacks and display names.
src/main/java/world/bentobox/level/panels/ValuePanel.javaUses custom-block ItemStack icons + display names where available.
src/main/java/world/bentobox/level/panels/DonationPanel.javaSupports custom-block IDs for value lookup and donation logging.
src/main/java/world/bentobox/level/panels/DetailsPanel.javaUses shared custom-block resolution/display-name helpers.
src/main/java/world/bentobox/level/Level.javaAdds getCustomBlockId(ItemStack) for Oraxen/Nexo/ItemsAdder/CraftEngine.
src/main/java/world/bentobox/level/commands/IslandValueCommand.javaUses getCustomBlockId() and custom display-name resolution for “hand” value lookups.
src/main/java/world/bentobox/level/commands/IslandLevelCommand.javaDisplays progress using “points from current level” and computed interval size.
src/main/java/world/bentobox/level/calculators/Results.javaAdds pointsFromCurrentLevel field + getters/setters.
src/test/java/world/bentobox/level/calculators/ResultsTest.javaAdds unit tests for pointsFromCurrentLevel.
src/main/java/world/bentobox/level/calculators/IslandLevelCalculator.javaUses binary search to compute points-to-next-level and points-within-current-level.
src/main/resources/addon.ymlBumps addon api-version.
pom.xmlBumps build version to 2.27.0 and BentoBox dependency to 3.15.1-SNAPSHOT.
Comments suppressed due to low confidence (1)

src/main/java/world/bentobox/level/commands/IslandDonateCommand.java:300

  • tabComplete() now assumes BentoBox prepends the leaf command label into args (using args.get(1) for the first user argument). This is inconsistent with other commands/tests in this repo (which treat args as only user-typed arguments) and breaks completion for /island donate hand <TAB>: with args like ["hand", ""], the code returns hand/inv suggestions instead of the held amount. Consider supporting the existing args shape (no label) or handling both forms by detecting and adjusting the starting index dynamically.
 public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
// BentoBox includes the command label as args.get(0); the user-typed args start at index 1.
String lastArg = !args.isEmpty() ? args.get(args.size() - 1) : "";
String handKeyword = user.getTranslation("island.donate.hand.keyword");
String invKeyword = user.getTranslation("island.donate.inv.keyword");
// First user-arg slot: suggest "hand" and "inv".
if (args.size() <= 2) {
return Optional.of(Util.tabLimit(List.of(handKeyword, invKeyword), lastArg));
}
// Second user-arg slot after "hand": suggest the held count.
if (args.size() == 3 && isHandKeyword(user, 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());

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

Comment on lines +175 to +183
@Test
void testTabCompleteFirstArgFromBentoBoxFlow() {
// BentoBox passes the leaf command label as args.get(0); the partial first
// user arg sits in args.get(1). Empty string = bare "/island donate <TAB>".
var result = cmd.tabComplete(user, "donate", List.of("donate", ""));
assertTrue(result.isPresent());
assertTrue(result.get().contains("hand"));
assertTrue(result.get().contains("inv"));
}
time-out: "<red>The level calculation took too long. Please try again later."
donate:
parameters: "[hand [amount]]"
parameters: "[hand [amount]] [inv]"
tastybentoand others added 6 commits May 11, 2026 20:38
Adds a `donations-only` config option that bypasses the island chunk scan
entirely. The island level is computed only from blocks donated via
`/island donate`, removing the per-recalculation CPU cost of scanning.
When the option is enabled:
- IslandLevelCalculator.scanIsland short-circuits to tidyUp(), which adds
the donated points (`LevelsManager.getDonatedPoints`) and runs the
configured level-calc formula on those points alone.
- The /island detail command is not registered, since there are no
scanned blocks to break down per the issue thread.
- /island level, /island top, /island value, and /island donate continue
to work; /island level reports the level based on donations only.
Closes#430.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When an admin enables donations-only mid-game, existing islands already
have an `initialCount` recorded from the original starter-island scan.
The level formula subtracts `initialCount` from raw points when
`zero-new-island-levels` is on — but under donations-only, raw points
are just the donated total, which is typically much smaller than the
recorded initial count. The result was a huge negative `modifiedPoints`
and a wildly negative level.
Ignore `initialCount` (treat as 0) whenever donations-only is enabled:
- `calculateLevel(rawPoints)` no longer subtracts it
- the `pointsFromCurrentLevel` binary search no longer floors at it
- the report no longer prints it (would be misleading, since it isn't
applied to the level math)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The previous short-circuit in scanIsland skipped every scan when
donations-only was enabled — including the zero-island scan that fires
on IslandCreatedEvent / IslandResettedEvent. That meant new islands
created during a donations-only window got initialCount = 0, so if an
admin later disabled donations-only the player's entire current block
total would count toward their level (no handicap subtracted).
Restrict the short-circuit to non-zero-island scans. The zero-island
scan still runs and records the real handicap into initialCount; it is
just ignored by calculateLevel while donations-only is on (per the
existing fix in this PR). When donations-only is later disabled, the
stored initialCount is correctly subtracted by calculateLevel as before.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The viewer button at the bottom of the top-ten panel rendered with a
"Click to view" tooltip and opened the details panel on click. That
panel breaks down scanned blocks, which is meaningless in donations-only
mode (and /island detail is not registered there either).
Add a donations-only check to the VIEW action filter so it's removed
from activeActions for that button when donations-only is enabled.
Filtering it out also drops the "Click to view" tooltip — no template
or locale change needed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ore-initial-count
fix: ignore initialCount in donations-only mode (#430)
@sonarqubecloud

Copy link
Copy Markdown

@tastybento
tastybento merged commit 23e4e77 into masterMay 13, 2026
5 checks passed
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.

4 participants

@tastybento@msmith-codes
, '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

Release 2.27.0 - #431

Merged
tastybento merged 24 commits into
masterfrom
develop
May 13, 2026
Merged

Release 2.27.0#431
tastybento merged 24 commits into
masterfrom
develop

Conversation

@tastybento

Copy link
Copy Markdown
Member

No description provided.

tastybentoand others added 18 commits May 3, 2026 22:10
Adds a confirmable "inv" subcommand that scans the player's inventory
for donatable blocks, lists each material with its point value plus a
total in the confirmation prompt, and on confirm donates all of them
in one go. Items with no value or that are not donatable blocks remain
in the inventory.
Also fixes the donate tab-complete: the args list BentoBox passes to a
subcommand includes the leaf label at index 0, so the previous
size-1 check never fired in real use and only the auto "help"
suggestion appeared. Tests now exercise the realistic args shape.
Bumps build version to 2.27.0.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds the four new island.donate.inv keys (keyword, confirm-header,
confirm-line, confirm-total) to every non-English locale file. MiniMessage
tags and placeholders are preserved verbatim; only the human-readable
text was translated.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Addresses SonarCloud findings about duplicated string literals in
IslandDonateCommand.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
feat: /island donate inv — donate everything from inventory
…e, detail, and donate menus
Agent-Logs-Url: https://github.com/BentoBoxWorld/Level/sessions/daf183a6-549f-4946-900c-5719c0a27e81
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>
…inv donation value
Agent-Logs-Url: https://github.com/BentoBoxWorld/Level/sessions/daf183a6-549f-4946-900c-5719c0a27e81
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>
FIXED: Negative values in progression while using a non-linear function.
The forward and backward point-boundary scans could each iterate up to
10M times calling calculateLevel() (string parse + eval) on the primary
thread. Binary search reduces this to ~23 iterations. Also adds missing
ResultsTest coverage for pointsFromCurrentLevel.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…upport-menu
Add custom block support (Oraxen/Nexo/ItemsAdder/CraftEngine) in value, detail, and donate menus
The /is value panel rendered Oraxen/Nexo/ItemsAdder blocks as paper with
the prettified config key as the name. Look up the real ItemStack from
the plugin's registry and use it as the icon, plus the item meta display
name when present. Lookup helper is extracted to Utils so DetailsPanel
and ValuePanel share it.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…and-name
Fix custom-block icon and display name in value panel (#426)
Three call sites were missing CraftEngine support, so /is value hand
returned "no value" for held CraftEngine items, the value panel showed
a paper icon with the prettified namespaced key, and the chat output
used the raw key instead of the configured display name:
- Level.getCustomBlockId now checks CraftEngineHook.getItemId, so a
held custom item is mapped to its namespaced ID.
- Utils.getCustomBlockItemStack now delegates to
CraftEngineHook.getItemStack so the panel renders the real icon.
- Utils.getCustomBlockDisplayName now also reads the modern
minecraft:item_name component (hasItemName/getItemName) used by
CraftEngine, in addition to the legacy display.Name used by Oraxen,
Nexo, and ItemsAdder.
- IslandValueCommand.printValue routes string IDs through the same
getCustomBlockItemStack/getCustomBlockDisplayName path used by the
panel, so the chat message shows the configured display name.
Requires BentoBox >= 3.15.1-SNAPSHOT (BentoBoxWorld/BentoBox#2973 for
the new getItemId helper).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…y-name
fix: recognize CraftEngine items in value lookups (#428)

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

Release 2.27.0 expands Level’s donation and custom-block support, improves level-progress reporting for non-linear formulas, and updates project/version metadata.

Changes:

  • Add /island donate inv flow (tab-complete, confirmation prompt, inventory scan + donation logging) and localize new messages.
  • Improve custom-block rendering by resolving representative ItemStacks (Oraxen/Nexo/ItemsAdder/CraftEngine) and using item meta display names in panels/commands.
  • Compute “points within current level” and use it to show accurate level progress for non-linear level formulas; bump addon + dependency versions.

Reviewed changes

Copilot reviewed 31 out of 31 changed files in this pull request and generated 2 comments.

Show a summary per file
FileDescription
src/main/java/world/bentobox/level/commands/IslandDonateCommand.javaAdds inv subcommand, inventory donation execution, and revised tab-complete logic.
src/test/java/world/bentobox/level/commands/IslandDonateCommandTest.javaAdds tab-complete and inv donation tests.
src/main/resources/locales/en-US.ymlUpdates donate usage string; adds donate.inv.* messages.
src/main/resources/locales/cs.ymlAdds donate.inv.* messages.
src/main/resources/locales/de.ymlAdds donate.inv.* messages.
src/main/resources/locales/es.ymlAdds donate.inv.* messages.
src/main/resources/locales/fr.ymlAdds donate.inv.* messages.
src/main/resources/locales/hu.ymlAdds donate.inv.* messages.
src/main/resources/locales/id.ymlAdds donate.inv.* messages.
src/main/resources/locales/ko.ymlAdds donate.inv.* messages.
src/main/resources/locales/lv.ymlAdds donate.inv.* messages.
src/main/resources/locales/nl.ymlAdds donate.inv.* messages.
src/main/resources/locales/pl.ymlAdds donate.inv.* messages.
src/main/resources/locales/pt.ymlAdds donate.inv.* messages.
src/main/resources/locales/ru.ymlAdds donate.inv.* messages.
src/main/resources/locales/tr.ymlAdds donate.inv.* messages.
src/main/resources/locales/uk.ymlAdds donate.inv.* messages.
src/main/resources/locales/vi.ymlAdds donate.inv.* messages.
src/main/resources/locales/zh-CN.ymlAdds donate.inv.* messages.
src/main/java/world/bentobox/level/util/Utils.javaAdds helpers to resolve custom-block ItemStacks and display names.
src/main/java/world/bentobox/level/panels/ValuePanel.javaUses custom-block ItemStack icons + display names where available.
src/main/java/world/bentobox/level/panels/DonationPanel.javaSupports custom-block IDs for value lookup and donation logging.
src/main/java/world/bentobox/level/panels/DetailsPanel.javaUses shared custom-block resolution/display-name helpers.
src/main/java/world/bentobox/level/Level.javaAdds getCustomBlockId(ItemStack) for Oraxen/Nexo/ItemsAdder/CraftEngine.
src/main/java/world/bentobox/level/commands/IslandValueCommand.javaUses getCustomBlockId() and custom display-name resolution for “hand” value lookups.
src/main/java/world/bentobox/level/commands/IslandLevelCommand.javaDisplays progress using “points from current level” and computed interval size.
src/main/java/world/bentobox/level/calculators/Results.javaAdds pointsFromCurrentLevel field + getters/setters.
src/test/java/world/bentobox/level/calculators/ResultsTest.javaAdds unit tests for pointsFromCurrentLevel.
src/main/java/world/bentobox/level/calculators/IslandLevelCalculator.javaUses binary search to compute points-to-next-level and points-within-current-level.
src/main/resources/addon.ymlBumps addon api-version.
pom.xmlBumps build version to 2.27.0 and BentoBox dependency to 3.15.1-SNAPSHOT.
Comments suppressed due to low confidence (1)

src/main/java/world/bentobox/level/commands/IslandDonateCommand.java:300

  • tabComplete() now assumes BentoBox prepends the leaf command label into args (using args.get(1) for the first user argument). This is inconsistent with other commands/tests in this repo (which treat args as only user-typed arguments) and breaks completion for /island donate hand <TAB>: with args like ["hand", ""], the code returns hand/inv suggestions instead of the held amount. Consider supporting the existing args shape (no label) or handling both forms by detecting and adjusting the starting index dynamically.
 public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
// BentoBox includes the command label as args.get(0); the user-typed args start at index 1.
String lastArg = !args.isEmpty() ? args.get(args.size() - 1) : "";
String handKeyword = user.getTranslation("island.donate.hand.keyword");
String invKeyword = user.getTranslation("island.donate.inv.keyword");
// First user-arg slot: suggest "hand" and "inv".
if (args.size() <= 2) {
return Optional.of(Util.tabLimit(List.of(handKeyword, invKeyword), lastArg));
}
// Second user-arg slot after "hand": suggest the held count.
if (args.size() == 3 && isHandKeyword(user, 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());

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

Comment on lines +175 to +183
@Test
void testTabCompleteFirstArgFromBentoBoxFlow() {
// BentoBox passes the leaf command label as args.get(0); the partial first
// user arg sits in args.get(1). Empty string = bare "/island donate <TAB>".
var result = cmd.tabComplete(user, "donate", List.of("donate", ""));
assertTrue(result.isPresent());
assertTrue(result.get().contains("hand"));
assertTrue(result.get().contains("inv"));
}
time-out: "<red>The level calculation took too long. Please try again later."
donate:
parameters: "[hand [amount]]"
parameters: "[hand [amount]] [inv]"
tastybentoand others added 6 commits May 11, 2026 20:38
Adds a `donations-only` config option that bypasses the island chunk scan
entirely. The island level is computed only from blocks donated via
`/island donate`, removing the per-recalculation CPU cost of scanning.
When the option is enabled:
- IslandLevelCalculator.scanIsland short-circuits to tidyUp(), which adds
the donated points (`LevelsManager.getDonatedPoints`) and runs the
configured level-calc formula on those points alone.
- The /island detail command is not registered, since there are no
scanned blocks to break down per the issue thread.
- /island level, /island top, /island value, and /island donate continue
to work; /island level reports the level based on donations only.
Closes#430.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When an admin enables donations-only mid-game, existing islands already
have an `initialCount` recorded from the original starter-island scan.
The level formula subtracts `initialCount` from raw points when
`zero-new-island-levels` is on — but under donations-only, raw points
are just the donated total, which is typically much smaller than the
recorded initial count. The result was a huge negative `modifiedPoints`
and a wildly negative level.
Ignore `initialCount` (treat as 0) whenever donations-only is enabled:
- `calculateLevel(rawPoints)` no longer subtracts it
- the `pointsFromCurrentLevel` binary search no longer floors at it
- the report no longer prints it (would be misleading, since it isn't
applied to the level math)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The previous short-circuit in scanIsland skipped every scan when
donations-only was enabled — including the zero-island scan that fires
on IslandCreatedEvent / IslandResettedEvent. That meant new islands
created during a donations-only window got initialCount = 0, so if an
admin later disabled donations-only the player's entire current block
total would count toward their level (no handicap subtracted).
Restrict the short-circuit to non-zero-island scans. The zero-island
scan still runs and records the real handicap into initialCount; it is
just ignored by calculateLevel while donations-only is on (per the
existing fix in this PR). When donations-only is later disabled, the
stored initialCount is correctly subtracted by calculateLevel as before.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The viewer button at the bottom of the top-ten panel rendered with a
"Click to view" tooltip and opened the details panel on click. That
panel breaks down scanned blocks, which is meaningless in donations-only
mode (and /island detail is not registered there either).
Add a donations-only check to the VIEW action filter so it's removed
from activeActions for that button when donations-only is enabled.
Filtering it out also drops the "Click to view" tooltip — no template
or locale change needed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ore-initial-count
fix: ignore initialCount in donations-only mode (#430)
@sonarqubecloud

Copy link
Copy Markdown

@tastybento
tastybento merged commit 23e4e77 into masterMay 13, 2026
5 checks passed
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.

4 participants

@tastybento@msmith-codes
, '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

Release 2.27.0 - #431

Merged
tastybento merged 24 commits into
masterfrom
develop
May 13, 2026
Merged

Release 2.27.0#431
tastybento merged 24 commits into
masterfrom
develop

Conversation

@tastybento

Copy link
Copy Markdown
Member

No description provided.

tastybentoand others added 18 commits May 3, 2026 22:10
Adds a confirmable "inv" subcommand that scans the player's inventory
for donatable blocks, lists each material with its point value plus a
total in the confirmation prompt, and on confirm donates all of them
in one go. Items with no value or that are not donatable blocks remain
in the inventory.
Also fixes the donate tab-complete: the args list BentoBox passes to a
subcommand includes the leaf label at index 0, so the previous
size-1 check never fired in real use and only the auto "help"
suggestion appeared. Tests now exercise the realistic args shape.
Bumps build version to 2.27.0.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds the four new island.donate.inv keys (keyword, confirm-header,
confirm-line, confirm-total) to every non-English locale file. MiniMessage
tags and placeholders are preserved verbatim; only the human-readable
text was translated.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Addresses SonarCloud findings about duplicated string literals in
IslandDonateCommand.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
feat: /island donate inv — donate everything from inventory
…e, detail, and donate menus
Agent-Logs-Url: https://github.com/BentoBoxWorld/Level/sessions/daf183a6-549f-4946-900c-5719c0a27e81
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>
…inv donation value
Agent-Logs-Url: https://github.com/BentoBoxWorld/Level/sessions/daf183a6-549f-4946-900c-5719c0a27e81
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>
FIXED: Negative values in progression while using a non-linear function.
The forward and backward point-boundary scans could each iterate up to
10M times calling calculateLevel() (string parse + eval) on the primary
thread. Binary search reduces this to ~23 iterations. Also adds missing
ResultsTest coverage for pointsFromCurrentLevel.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…upport-menu
Add custom block support (Oraxen/Nexo/ItemsAdder/CraftEngine) in value, detail, and donate menus
The /is value panel rendered Oraxen/Nexo/ItemsAdder blocks as paper with
the prettified config key as the name. Look up the real ItemStack from
the plugin's registry and use it as the icon, plus the item meta display
name when present. Lookup helper is extracted to Utils so DetailsPanel
and ValuePanel share it.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…and-name
Fix custom-block icon and display name in value panel (#426)
Three call sites were missing CraftEngine support, so /is value hand
returned "no value" for held CraftEngine items, the value panel showed
a paper icon with the prettified namespaced key, and the chat output
used the raw key instead of the configured display name:
- Level.getCustomBlockId now checks CraftEngineHook.getItemId, so a
held custom item is mapped to its namespaced ID.
- Utils.getCustomBlockItemStack now delegates to
CraftEngineHook.getItemStack so the panel renders the real icon.
- Utils.getCustomBlockDisplayName now also reads the modern
minecraft:item_name component (hasItemName/getItemName) used by
CraftEngine, in addition to the legacy display.Name used by Oraxen,
Nexo, and ItemsAdder.
- IslandValueCommand.printValue routes string IDs through the same
getCustomBlockItemStack/getCustomBlockDisplayName path used by the
panel, so the chat message shows the configured display name.
Requires BentoBox >= 3.15.1-SNAPSHOT (BentoBoxWorld/BentoBox#2973 for
the new getItemId helper).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…y-name
fix: recognize CraftEngine items in value lookups (#428)

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

Release 2.27.0 expands Level’s donation and custom-block support, improves level-progress reporting for non-linear formulas, and updates project/version metadata.

Changes:

  • Add /island donate inv flow (tab-complete, confirmation prompt, inventory scan + donation logging) and localize new messages.
  • Improve custom-block rendering by resolving representative ItemStacks (Oraxen/Nexo/ItemsAdder/CraftEngine) and using item meta display names in panels/commands.
  • Compute “points within current level” and use it to show accurate level progress for non-linear level formulas; bump addon + dependency versions.

Reviewed changes

Copilot reviewed 31 out of 31 changed files in this pull request and generated 2 comments.

Show a summary per file
FileDescription
src/main/java/world/bentobox/level/commands/IslandDonateCommand.javaAdds inv subcommand, inventory donation execution, and revised tab-complete logic.
src/test/java/world/bentobox/level/commands/IslandDonateCommandTest.javaAdds tab-complete and inv donation tests.
src/main/resources/locales/en-US.ymlUpdates donate usage string; adds donate.inv.* messages.
src/main/resources/locales/cs.ymlAdds donate.inv.* messages.
src/main/resources/locales/de.ymlAdds donate.inv.* messages.
src/main/resources/locales/es.ymlAdds donate.inv.* messages.
src/main/resources/locales/fr.ymlAdds donate.inv.* messages.
src/main/resources/locales/hu.ymlAdds donate.inv.* messages.
src/main/resources/locales/id.ymlAdds donate.inv.* messages.
src/main/resources/locales/ko.ymlAdds donate.inv.* messages.
src/main/resources/locales/lv.ymlAdds donate.inv.* messages.
src/main/resources/locales/nl.ymlAdds donate.inv.* messages.
src/main/resources/locales/pl.ymlAdds donate.inv.* messages.
src/main/resources/locales/pt.ymlAdds donate.inv.* messages.
src/main/resources/locales/ru.ymlAdds donate.inv.* messages.
src/main/resources/locales/tr.ymlAdds donate.inv.* messages.
src/main/resources/locales/uk.ymlAdds donate.inv.* messages.
src/main/resources/locales/vi.ymlAdds donate.inv.* messages.
src/main/resources/locales/zh-CN.ymlAdds donate.inv.* messages.
src/main/java/world/bentobox/level/util/Utils.javaAdds helpers to resolve custom-block ItemStacks and display names.
src/main/java/world/bentobox/level/panels/ValuePanel.javaUses custom-block ItemStack icons + display names where available.
src/main/java/world/bentobox/level/panels/DonationPanel.javaSupports custom-block IDs for value lookup and donation logging.
src/main/java/world/bentobox/level/panels/DetailsPanel.javaUses shared custom-block resolution/display-name helpers.
src/main/java/world/bentobox/level/Level.javaAdds getCustomBlockId(ItemStack) for Oraxen/Nexo/ItemsAdder/CraftEngine.
src/main/java/world/bentobox/level/commands/IslandValueCommand.javaUses getCustomBlockId() and custom display-name resolution for “hand” value lookups.
src/main/java/world/bentobox/level/commands/IslandLevelCommand.javaDisplays progress using “points from current level” and computed interval size.
src/main/java/world/bentobox/level/calculators/Results.javaAdds pointsFromCurrentLevel field + getters/setters.
src/test/java/world/bentobox/level/calculators/ResultsTest.javaAdds unit tests for pointsFromCurrentLevel.
src/main/java/world/bentobox/level/calculators/IslandLevelCalculator.javaUses binary search to compute points-to-next-level and points-within-current-level.
src/main/resources/addon.ymlBumps addon api-version.
pom.xmlBumps build version to 2.27.0 and BentoBox dependency to 3.15.1-SNAPSHOT.
Comments suppressed due to low confidence (1)

src/main/java/world/bentobox/level/commands/IslandDonateCommand.java:300

  • tabComplete() now assumes BentoBox prepends the leaf command label into args (using args.get(1) for the first user argument). This is inconsistent with other commands/tests in this repo (which treat args as only user-typed arguments) and breaks completion for /island donate hand <TAB>: with args like ["hand", ""], the code returns hand/inv suggestions instead of the held amount. Consider supporting the existing args shape (no label) or handling both forms by detecting and adjusting the starting index dynamically.
 public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
// BentoBox includes the command label as args.get(0); the user-typed args start at index 1.
String lastArg = !args.isEmpty() ? args.get(args.size() - 1) : "";
String handKeyword = user.getTranslation("island.donate.hand.keyword");
String invKeyword = user.getTranslation("island.donate.inv.keyword");
// First user-arg slot: suggest "hand" and "inv".
if (args.size() <= 2) {
return Optional.of(Util.tabLimit(List.of(handKeyword, invKeyword), lastArg));
}
// Second user-arg slot after "hand": suggest the held count.
if (args.size() == 3 && isHandKeyword(user, 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());

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

Comment on lines +175 to +183
@Test
void testTabCompleteFirstArgFromBentoBoxFlow() {
// BentoBox passes the leaf command label as args.get(0); the partial first
// user arg sits in args.get(1). Empty string = bare "/island donate <TAB>".
var result = cmd.tabComplete(user, "donate", List.of("donate", ""));
assertTrue(result.isPresent());
assertTrue(result.get().contains("hand"));
assertTrue(result.get().contains("inv"));
}
time-out: "<red>The level calculation took too long. Please try again later."
donate:
parameters: "[hand [amount]]"
parameters: "[hand [amount]] [inv]"
tastybentoand others added 6 commits May 11, 2026 20:38
Adds a `donations-only` config option that bypasses the island chunk scan
entirely. The island level is computed only from blocks donated via
`/island donate`, removing the per-recalculation CPU cost of scanning.
When the option is enabled:
- IslandLevelCalculator.scanIsland short-circuits to tidyUp(), which adds
the donated points (`LevelsManager.getDonatedPoints`) and runs the
configured level-calc formula on those points alone.
- The /island detail command is not registered, since there are no
scanned blocks to break down per the issue thread.
- /island level, /island top, /island value, and /island donate continue
to work; /island level reports the level based on donations only.
Closes#430.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When an admin enables donations-only mid-game, existing islands already
have an `initialCount` recorded from the original starter-island scan.
The level formula subtracts `initialCount` from raw points when
`zero-new-island-levels` is on — but under donations-only, raw points
are just the donated total, which is typically much smaller than the
recorded initial count. The result was a huge negative `modifiedPoints`
and a wildly negative level.
Ignore `initialCount` (treat as 0) whenever donations-only is enabled:
- `calculateLevel(rawPoints)` no longer subtracts it
- the `pointsFromCurrentLevel` binary search no longer floors at it
- the report no longer prints it (would be misleading, since it isn't
applied to the level math)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The previous short-circuit in scanIsland skipped every scan when
donations-only was enabled — including the zero-island scan that fires
on IslandCreatedEvent / IslandResettedEvent. That meant new islands
created during a donations-only window got initialCount = 0, so if an
admin later disabled donations-only the player's entire current block
total would count toward their level (no handicap subtracted).
Restrict the short-circuit to non-zero-island scans. The zero-island
scan still runs and records the real handicap into initialCount; it is
just ignored by calculateLevel while donations-only is on (per the
existing fix in this PR). When donations-only is later disabled, the
stored initialCount is correctly subtracted by calculateLevel as before.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The viewer button at the bottom of the top-ten panel rendered with a
"Click to view" tooltip and opened the details panel on click. That
panel breaks down scanned blocks, which is meaningless in donations-only
mode (and /island detail is not registered there either).
Add a donations-only check to the VIEW action filter so it's removed
from activeActions for that button when donations-only is enabled.
Filtering it out also drops the "Click to view" tooltip — no template
or locale change needed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ore-initial-count
fix: ignore initialCount in donations-only mode (#430)
@sonarqubecloud

Copy link
Copy Markdown

@tastybento
tastybento merged commit 23e4e77 into masterMay 13, 2026
5 checks passed
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.

4 participants

@tastybento@msmith-codes
, '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

Release 2.27.0 - #431

Merged
tastybento merged 24 commits into
masterfrom
develop
May 13, 2026
Merged

Release 2.27.0#431
tastybento merged 24 commits into
masterfrom
develop

Conversation

@tastybento

Copy link
Copy Markdown
Member

No description provided.

tastybentoand others added 18 commits May 3, 2026 22:10
Adds a confirmable "inv" subcommand that scans the player's inventory
for donatable blocks, lists each material with its point value plus a
total in the confirmation prompt, and on confirm donates all of them
in one go. Items with no value or that are not donatable blocks remain
in the inventory.
Also fixes the donate tab-complete: the args list BentoBox passes to a
subcommand includes the leaf label at index 0, so the previous
size-1 check never fired in real use and only the auto "help"
suggestion appeared. Tests now exercise the realistic args shape.
Bumps build version to 2.27.0.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds the four new island.donate.inv keys (keyword, confirm-header,
confirm-line, confirm-total) to every non-English locale file. MiniMessage
tags and placeholders are preserved verbatim; only the human-readable
text was translated.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Addresses SonarCloud findings about duplicated string literals in
IslandDonateCommand.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
feat: /island donate inv — donate everything from inventory
…e, detail, and donate menus
Agent-Logs-Url: https://github.com/BentoBoxWorld/Level/sessions/daf183a6-549f-4946-900c-5719c0a27e81
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>
…inv donation value
Agent-Logs-Url: https://github.com/BentoBoxWorld/Level/sessions/daf183a6-549f-4946-900c-5719c0a27e81
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>
FIXED: Negative values in progression while using a non-linear function.
The forward and backward point-boundary scans could each iterate up to
10M times calling calculateLevel() (string parse + eval) on the primary
thread. Binary search reduces this to ~23 iterations. Also adds missing
ResultsTest coverage for pointsFromCurrentLevel.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…upport-menu
Add custom block support (Oraxen/Nexo/ItemsAdder/CraftEngine) in value, detail, and donate menus
The /is value panel rendered Oraxen/Nexo/ItemsAdder blocks as paper with
the prettified config key as the name. Look up the real ItemStack from
the plugin's registry and use it as the icon, plus the item meta display
name when present. Lookup helper is extracted to Utils so DetailsPanel
and ValuePanel share it.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…and-name
Fix custom-block icon and display name in value panel (#426)
Three call sites were missing CraftEngine support, so /is value hand
returned "no value" for held CraftEngine items, the value panel showed
a paper icon with the prettified namespaced key, and the chat output
used the raw key instead of the configured display name:
- Level.getCustomBlockId now checks CraftEngineHook.getItemId, so a
held custom item is mapped to its namespaced ID.
- Utils.getCustomBlockItemStack now delegates to
CraftEngineHook.getItemStack so the panel renders the real icon.
- Utils.getCustomBlockDisplayName now also reads the modern
minecraft:item_name component (hasItemName/getItemName) used by
CraftEngine, in addition to the legacy display.Name used by Oraxen,
Nexo, and ItemsAdder.
- IslandValueCommand.printValue routes string IDs through the same
getCustomBlockItemStack/getCustomBlockDisplayName path used by the
panel, so the chat message shows the configured display name.
Requires BentoBox >= 3.15.1-SNAPSHOT (BentoBoxWorld/BentoBox#2973 for
the new getItemId helper).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…y-name
fix: recognize CraftEngine items in value lookups (#428)

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

Release 2.27.0 expands Level’s donation and custom-block support, improves level-progress reporting for non-linear formulas, and updates project/version metadata.

Changes:

  • Add /island donate inv flow (tab-complete, confirmation prompt, inventory scan + donation logging) and localize new messages.
  • Improve custom-block rendering by resolving representative ItemStacks (Oraxen/Nexo/ItemsAdder/CraftEngine) and using item meta display names in panels/commands.
  • Compute “points within current level” and use it to show accurate level progress for non-linear level formulas; bump addon + dependency versions.

Reviewed changes

Copilot reviewed 31 out of 31 changed files in this pull request and generated 2 comments.

Show a summary per file
FileDescription
src/main/java/world/bentobox/level/commands/IslandDonateCommand.javaAdds inv subcommand, inventory donation execution, and revised tab-complete logic.
src/test/java/world/bentobox/level/commands/IslandDonateCommandTest.javaAdds tab-complete and inv donation tests.
src/main/resources/locales/en-US.ymlUpdates donate usage string; adds donate.inv.* messages.
src/main/resources/locales/cs.ymlAdds donate.inv.* messages.
src/main/resources/locales/de.ymlAdds donate.inv.* messages.
src/main/resources/locales/es.ymlAdds donate.inv.* messages.
src/main/resources/locales/fr.ymlAdds donate.inv.* messages.
src/main/resources/locales/hu.ymlAdds donate.inv.* messages.
src/main/resources/locales/id.ymlAdds donate.inv.* messages.
src/main/resources/locales/ko.ymlAdds donate.inv.* messages.
src/main/resources/locales/lv.ymlAdds donate.inv.* messages.
src/main/resources/locales/nl.ymlAdds donate.inv.* messages.
src/main/resources/locales/pl.ymlAdds donate.inv.* messages.
src/main/resources/locales/pt.ymlAdds donate.inv.* messages.
src/main/resources/locales/ru.ymlAdds donate.inv.* messages.
src/main/resources/locales/tr.ymlAdds donate.inv.* messages.
src/main/resources/locales/uk.ymlAdds donate.inv.* messages.
src/main/resources/locales/vi.ymlAdds donate.inv.* messages.
src/main/resources/locales/zh-CN.ymlAdds donate.inv.* messages.
src/main/java/world/bentobox/level/util/Utils.javaAdds helpers to resolve custom-block ItemStacks and display names.
src/main/java/world/bentobox/level/panels/ValuePanel.javaUses custom-block ItemStack icons + display names where available.
src/main/java/world/bentobox/level/panels/DonationPanel.javaSupports custom-block IDs for value lookup and donation logging.
src/main/java/world/bentobox/level/panels/DetailsPanel.javaUses shared custom-block resolution/display-name helpers.
src/main/java/world/bentobox/level/Level.javaAdds getCustomBlockId(ItemStack) for Oraxen/Nexo/ItemsAdder/CraftEngine.
src/main/java/world/bentobox/level/commands/IslandValueCommand.javaUses getCustomBlockId() and custom display-name resolution for “hand” value lookups.
src/main/java/world/bentobox/level/commands/IslandLevelCommand.javaDisplays progress using “points from current level” and computed interval size.
src/main/java/world/bentobox/level/calculators/Results.javaAdds pointsFromCurrentLevel field + getters/setters.
src/test/java/world/bentobox/level/calculators/ResultsTest.javaAdds unit tests for pointsFromCurrentLevel.
src/main/java/world/bentobox/level/calculators/IslandLevelCalculator.javaUses binary search to compute points-to-next-level and points-within-current-level.
src/main/resources/addon.ymlBumps addon api-version.
pom.xmlBumps build version to 2.27.0 and BentoBox dependency to 3.15.1-SNAPSHOT.
Comments suppressed due to low confidence (1)

src/main/java/world/bentobox/level/commands/IslandDonateCommand.java:300

  • tabComplete() now assumes BentoBox prepends the leaf command label into args (using args.get(1) for the first user argument). This is inconsistent with other commands/tests in this repo (which treat args as only user-typed arguments) and breaks completion for /island donate hand <TAB>: with args like ["hand", ""], the code returns hand/inv suggestions instead of the held amount. Consider supporting the existing args shape (no label) or handling both forms by detecting and adjusting the starting index dynamically.
 public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
// BentoBox includes the command label as args.get(0); the user-typed args start at index 1.
String lastArg = !args.isEmpty() ? args.get(args.size() - 1) : "";
String handKeyword = user.getTranslation("island.donate.hand.keyword");
String invKeyword = user.getTranslation("island.donate.inv.keyword");
// First user-arg slot: suggest "hand" and "inv".
if (args.size() <= 2) {
return Optional.of(Util.tabLimit(List.of(handKeyword, invKeyword), lastArg));
}
// Second user-arg slot after "hand": suggest the held count.
if (args.size() == 3 && isHandKeyword(user, 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());

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

Comment on lines +175 to +183
@Test
void testTabCompleteFirstArgFromBentoBoxFlow() {
// BentoBox passes the leaf command label as args.get(0); the partial first
// user arg sits in args.get(1). Empty string = bare "/island donate <TAB>".
var result = cmd.tabComplete(user, "donate", List.of("donate", ""));
assertTrue(result.isPresent());
assertTrue(result.get().contains("hand"));
assertTrue(result.get().contains("inv"));
}
time-out: "<red>The level calculation took too long. Please try again later."
donate:
parameters: "[hand [amount]]"
parameters: "[hand [amount]] [inv]"
tastybentoand others added 6 commits May 11, 2026 20:38
Adds a `donations-only` config option that bypasses the island chunk scan
entirely. The island level is computed only from blocks donated via
`/island donate`, removing the per-recalculation CPU cost of scanning.
When the option is enabled:
- IslandLevelCalculator.scanIsland short-circuits to tidyUp(), which adds
the donated points (`LevelsManager.getDonatedPoints`) and runs the
configured level-calc formula on those points alone.
- The /island detail command is not registered, since there are no
scanned blocks to break down per the issue thread.
- /island level, /island top, /island value, and /island donate continue
to work; /island level reports the level based on donations only.
Closes#430.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When an admin enables donations-only mid-game, existing islands already
have an `initialCount` recorded from the original starter-island scan.
The level formula subtracts `initialCount` from raw points when
`zero-new-island-levels` is on — but under donations-only, raw points
are just the donated total, which is typically much smaller than the
recorded initial count. The result was a huge negative `modifiedPoints`
and a wildly negative level.
Ignore `initialCount` (treat as 0) whenever donations-only is enabled:
- `calculateLevel(rawPoints)` no longer subtracts it
- the `pointsFromCurrentLevel` binary search no longer floors at it
- the report no longer prints it (would be misleading, since it isn't
applied to the level math)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The previous short-circuit in scanIsland skipped every scan when
donations-only was enabled — including the zero-island scan that fires
on IslandCreatedEvent / IslandResettedEvent. That meant new islands
created during a donations-only window got initialCount = 0, so if an
admin later disabled donations-only the player's entire current block
total would count toward their level (no handicap subtracted).
Restrict the short-circuit to non-zero-island scans. The zero-island
scan still runs and records the real handicap into initialCount; it is
just ignored by calculateLevel while donations-only is on (per the
existing fix in this PR). When donations-only is later disabled, the
stored initialCount is correctly subtracted by calculateLevel as before.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The viewer button at the bottom of the top-ten panel rendered with a
"Click to view" tooltip and opened the details panel on click. That
panel breaks down scanned blocks, which is meaningless in donations-only
mode (and /island detail is not registered there either).
Add a donations-only check to the VIEW action filter so it's removed
from activeActions for that button when donations-only is enabled.
Filtering it out also drops the "Click to view" tooltip — no template
or locale change needed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ore-initial-count
fix: ignore initialCount in donations-only mode (#430)
@sonarqubecloud

Copy link
Copy Markdown

@tastybento
tastybento merged commit 23e4e77 into masterMay 13, 2026
5 checks passed
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.

4 participants

@tastybento@msmith-codes
, '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

Release 2.27.0 - #431

Merged
tastybento merged 24 commits into
masterfrom
develop
May 13, 2026
Merged

Release 2.27.0#431
tastybento merged 24 commits into
masterfrom
develop

Conversation

@tastybento

Copy link
Copy Markdown
Member

No description provided.

tastybentoand others added 18 commits May 3, 2026 22:10
Adds a confirmable "inv" subcommand that scans the player's inventory
for donatable blocks, lists each material with its point value plus a
total in the confirmation prompt, and on confirm donates all of them
in one go. Items with no value or that are not donatable blocks remain
in the inventory.
Also fixes the donate tab-complete: the args list BentoBox passes to a
subcommand includes the leaf label at index 0, so the previous
size-1 check never fired in real use and only the auto "help"
suggestion appeared. Tests now exercise the realistic args shape.
Bumps build version to 2.27.0.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds the four new island.donate.inv keys (keyword, confirm-header,
confirm-line, confirm-total) to every non-English locale file. MiniMessage
tags and placeholders are preserved verbatim; only the human-readable
text was translated.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Addresses SonarCloud findings about duplicated string literals in
IslandDonateCommand.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
feat: /island donate inv — donate everything from inventory
…e, detail, and donate menus
Agent-Logs-Url: https://github.com/BentoBoxWorld/Level/sessions/daf183a6-549f-4946-900c-5719c0a27e81
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>
…inv donation value
Agent-Logs-Url: https://github.com/BentoBoxWorld/Level/sessions/daf183a6-549f-4946-900c-5719c0a27e81
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>
FIXED: Negative values in progression while using a non-linear function.
The forward and backward point-boundary scans could each iterate up to
10M times calling calculateLevel() (string parse + eval) on the primary
thread. Binary search reduces this to ~23 iterations. Also adds missing
ResultsTest coverage for pointsFromCurrentLevel.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…upport-menu
Add custom block support (Oraxen/Nexo/ItemsAdder/CraftEngine) in value, detail, and donate menus
The /is value panel rendered Oraxen/Nexo/ItemsAdder blocks as paper with
the prettified config key as the name. Look up the real ItemStack from
the plugin's registry and use it as the icon, plus the item meta display
name when present. Lookup helper is extracted to Utils so DetailsPanel
and ValuePanel share it.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…and-name
Fix custom-block icon and display name in value panel (#426)
Three call sites were missing CraftEngine support, so /is value hand
returned "no value" for held CraftEngine items, the value panel showed
a paper icon with the prettified namespaced key, and the chat output
used the raw key instead of the configured display name:
- Level.getCustomBlockId now checks CraftEngineHook.getItemId, so a
held custom item is mapped to its namespaced ID.
- Utils.getCustomBlockItemStack now delegates to
CraftEngineHook.getItemStack so the panel renders the real icon.
- Utils.getCustomBlockDisplayName now also reads the modern
minecraft:item_name component (hasItemName/getItemName) used by
CraftEngine, in addition to the legacy display.Name used by Oraxen,
Nexo, and ItemsAdder.
- IslandValueCommand.printValue routes string IDs through the same
getCustomBlockItemStack/getCustomBlockDisplayName path used by the
panel, so the chat message shows the configured display name.
Requires BentoBox >= 3.15.1-SNAPSHOT (BentoBoxWorld/BentoBox#2973 for
the new getItemId helper).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…y-name
fix: recognize CraftEngine items in value lookups (#428)

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

Release 2.27.0 expands Level’s donation and custom-block support, improves level-progress reporting for non-linear formulas, and updates project/version metadata.

Changes:

  • Add /island donate inv flow (tab-complete, confirmation prompt, inventory scan + donation logging) and localize new messages.
  • Improve custom-block rendering by resolving representative ItemStacks (Oraxen/Nexo/ItemsAdder/CraftEngine) and using item meta display names in panels/commands.
  • Compute “points within current level” and use it to show accurate level progress for non-linear level formulas; bump addon + dependency versions.

Reviewed changes

Copilot reviewed 31 out of 31 changed files in this pull request and generated 2 comments.

Show a summary per file
FileDescription
src/main/java/world/bentobox/level/commands/IslandDonateCommand.javaAdds inv subcommand, inventory donation execution, and revised tab-complete logic.
src/test/java/world/bentobox/level/commands/IslandDonateCommandTest.javaAdds tab-complete and inv donation tests.
src/main/resources/locales/en-US.ymlUpdates donate usage string; adds donate.inv.* messages.
src/main/resources/locales/cs.ymlAdds donate.inv.* messages.
src/main/resources/locales/de.ymlAdds donate.inv.* messages.
src/main/resources/locales/es.ymlAdds donate.inv.* messages.
src/main/resources/locales/fr.ymlAdds donate.inv.* messages.
src/main/resources/locales/hu.ymlAdds donate.inv.* messages.
src/main/resources/locales/id.ymlAdds donate.inv.* messages.
src/main/resources/locales/ko.ymlAdds donate.inv.* messages.
src/main/resources/locales/lv.ymlAdds donate.inv.* messages.
src/main/resources/locales/nl.ymlAdds donate.inv.* messages.
src/main/resources/locales/pl.ymlAdds donate.inv.* messages.
src/main/resources/locales/pt.ymlAdds donate.inv.* messages.
src/main/resources/locales/ru.ymlAdds donate.inv.* messages.
src/main/resources/locales/tr.ymlAdds donate.inv.* messages.
src/main/resources/locales/uk.ymlAdds donate.inv.* messages.
src/main/resources/locales/vi.ymlAdds donate.inv.* messages.
src/main/resources/locales/zh-CN.ymlAdds donate.inv.* messages.
src/main/java/world/bentobox/level/util/Utils.javaAdds helpers to resolve custom-block ItemStacks and display names.
src/main/java/world/bentobox/level/panels/ValuePanel.javaUses custom-block ItemStack icons + display names where available.
src/main/java/world/bentobox/level/panels/DonationPanel.javaSupports custom-block IDs for value lookup and donation logging.
src/main/java/world/bentobox/level/panels/DetailsPanel.javaUses shared custom-block resolution/display-name helpers.
src/main/java/world/bentobox/level/Level.javaAdds getCustomBlockId(ItemStack) for Oraxen/Nexo/ItemsAdder/CraftEngine.
src/main/java/world/bentobox/level/commands/IslandValueCommand.javaUses getCustomBlockId() and custom display-name resolution for “hand” value lookups.
src/main/java/world/bentobox/level/commands/IslandLevelCommand.javaDisplays progress using “points from current level” and computed interval size.
src/main/java/world/bentobox/level/calculators/Results.javaAdds pointsFromCurrentLevel field + getters/setters.
src/test/java/world/bentobox/level/calculators/ResultsTest.javaAdds unit tests for pointsFromCurrentLevel.
src/main/java/world/bentobox/level/calculators/IslandLevelCalculator.javaUses binary search to compute points-to-next-level and points-within-current-level.
src/main/resources/addon.ymlBumps addon api-version.
pom.xmlBumps build version to 2.27.0 and BentoBox dependency to 3.15.1-SNAPSHOT.
Comments suppressed due to low confidence (1)

src/main/java/world/bentobox/level/commands/IslandDonateCommand.java:300

  • tabComplete() now assumes BentoBox prepends the leaf command label into args (using args.get(1) for the first user argument). This is inconsistent with other commands/tests in this repo (which treat args as only user-typed arguments) and breaks completion for /island donate hand <TAB>: with args like ["hand", ""], the code returns hand/inv suggestions instead of the held amount. Consider supporting the existing args shape (no label) or handling both forms by detecting and adjusting the starting index dynamically.
 public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
// BentoBox includes the command label as args.get(0); the user-typed args start at index 1.
String lastArg = !args.isEmpty() ? args.get(args.size() - 1) : "";
String handKeyword = user.getTranslation("island.donate.hand.keyword");
String invKeyword = user.getTranslation("island.donate.inv.keyword");
// First user-arg slot: suggest "hand" and "inv".
if (args.size() <= 2) {
return Optional.of(Util.tabLimit(List.of(handKeyword, invKeyword), lastArg));
}
// Second user-arg slot after "hand": suggest the held count.
if (args.size() == 3 && isHandKeyword(user, 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());

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

Comment on lines +175 to +183
@Test
void testTabCompleteFirstArgFromBentoBoxFlow() {
// BentoBox passes the leaf command label as args.get(0); the partial first
// user arg sits in args.get(1). Empty string = bare "/island donate <TAB>".
var result = cmd.tabComplete(user, "donate", List.of("donate", ""));
assertTrue(result.isPresent());
assertTrue(result.get().contains("hand"));
assertTrue(result.get().contains("inv"));
}
time-out: "<red>The level calculation took too long. Please try again later."
donate:
parameters: "[hand [amount]]"
parameters: "[hand [amount]] [inv]"
tastybentoand others added 6 commits May 11, 2026 20:38
Adds a `donations-only` config option that bypasses the island chunk scan
entirely. The island level is computed only from blocks donated via
`/island donate`, removing the per-recalculation CPU cost of scanning.
When the option is enabled:
- IslandLevelCalculator.scanIsland short-circuits to tidyUp(), which adds
the donated points (`LevelsManager.getDonatedPoints`) and runs the
configured level-calc formula on those points alone.
- The /island detail command is not registered, since there are no
scanned blocks to break down per the issue thread.
- /island level, /island top, /island value, and /island donate continue
to work; /island level reports the level based on donations only.
Closes#430.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When an admin enables donations-only mid-game, existing islands already
have an `initialCount` recorded from the original starter-island scan.
The level formula subtracts `initialCount` from raw points when
`zero-new-island-levels` is on — but under donations-only, raw points
are just the donated total, which is typically much smaller than the
recorded initial count. The result was a huge negative `modifiedPoints`
and a wildly negative level.
Ignore `initialCount` (treat as 0) whenever donations-only is enabled:
- `calculateLevel(rawPoints)` no longer subtracts it
- the `pointsFromCurrentLevel` binary search no longer floors at it
- the report no longer prints it (would be misleading, since it isn't
applied to the level math)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The previous short-circuit in scanIsland skipped every scan when
donations-only was enabled — including the zero-island scan that fires
on IslandCreatedEvent / IslandResettedEvent. That meant new islands
created during a donations-only window got initialCount = 0, so if an
admin later disabled donations-only the player's entire current block
total would count toward their level (no handicap subtracted).
Restrict the short-circuit to non-zero-island scans. The zero-island
scan still runs and records the real handicap into initialCount; it is
just ignored by calculateLevel while donations-only is on (per the
existing fix in this PR). When donations-only is later disabled, the
stored initialCount is correctly subtracted by calculateLevel as before.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The viewer button at the bottom of the top-ten panel rendered with a
"Click to view" tooltip and opened the details panel on click. That
panel breaks down scanned blocks, which is meaningless in donations-only
mode (and /island detail is not registered there either).
Add a donations-only check to the VIEW action filter so it's removed
from activeActions for that button when donations-only is enabled.
Filtering it out also drops the "Click to view" tooltip — no template
or locale change needed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ore-initial-count
fix: ignore initialCount in donations-only mode (#430)
@sonarqubecloud

Copy link
Copy Markdown

@tastybento
tastybento merged commit 23e4e77 into masterMay 13, 2026
5 checks passed
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.

4 participants

@tastybento@msmith-codes
, '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

Release 2.27.0 - #431

Merged
tastybento merged 24 commits into
masterfrom
develop
May 13, 2026
Merged

Release 2.27.0#431
tastybento merged 24 commits into
masterfrom
develop

Conversation

@tastybento

Copy link
Copy Markdown
Member

No description provided.

tastybentoand others added 18 commits May 3, 2026 22:10
Adds a confirmable "inv" subcommand that scans the player's inventory
for donatable blocks, lists each material with its point value plus a
total in the confirmation prompt, and on confirm donates all of them
in one go. Items with no value or that are not donatable blocks remain
in the inventory.
Also fixes the donate tab-complete: the args list BentoBox passes to a
subcommand includes the leaf label at index 0, so the previous
size-1 check never fired in real use and only the auto "help"
suggestion appeared. Tests now exercise the realistic args shape.
Bumps build version to 2.27.0.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds the four new island.donate.inv keys (keyword, confirm-header,
confirm-line, confirm-total) to every non-English locale file. MiniMessage
tags and placeholders are preserved verbatim; only the human-readable
text was translated.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Addresses SonarCloud findings about duplicated string literals in
IslandDonateCommand.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
feat: /island donate inv — donate everything from inventory
…e, detail, and donate menus
Agent-Logs-Url: https://github.com/BentoBoxWorld/Level/sessions/daf183a6-549f-4946-900c-5719c0a27e81
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>
…inv donation value
Agent-Logs-Url: https://github.com/BentoBoxWorld/Level/sessions/daf183a6-549f-4946-900c-5719c0a27e81
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>
FIXED: Negative values in progression while using a non-linear function.
The forward and backward point-boundary scans could each iterate up to
10M times calling calculateLevel() (string parse + eval) on the primary
thread. Binary search reduces this to ~23 iterations. Also adds missing
ResultsTest coverage for pointsFromCurrentLevel.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…upport-menu
Add custom block support (Oraxen/Nexo/ItemsAdder/CraftEngine) in value, detail, and donate menus
The /is value panel rendered Oraxen/Nexo/ItemsAdder blocks as paper with
the prettified config key as the name. Look up the real ItemStack from
the plugin's registry and use it as the icon, plus the item meta display
name when present. Lookup helper is extracted to Utils so DetailsPanel
and ValuePanel share it.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…and-name
Fix custom-block icon and display name in value panel (#426)
Three call sites were missing CraftEngine support, so /is value hand
returned "no value" for held CraftEngine items, the value panel showed
a paper icon with the prettified namespaced key, and the chat output
used the raw key instead of the configured display name:
- Level.getCustomBlockId now checks CraftEngineHook.getItemId, so a
held custom item is mapped to its namespaced ID.
- Utils.getCustomBlockItemStack now delegates to
CraftEngineHook.getItemStack so the panel renders the real icon.
- Utils.getCustomBlockDisplayName now also reads the modern
minecraft:item_name component (hasItemName/getItemName) used by
CraftEngine, in addition to the legacy display.Name used by Oraxen,
Nexo, and ItemsAdder.
- IslandValueCommand.printValue routes string IDs through the same
getCustomBlockItemStack/getCustomBlockDisplayName path used by the
panel, so the chat message shows the configured display name.
Requires BentoBox >= 3.15.1-SNAPSHOT (BentoBoxWorld/BentoBox#2973 for
the new getItemId helper).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…y-name
fix: recognize CraftEngine items in value lookups (#428)

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

Release 2.27.0 expands Level’s donation and custom-block support, improves level-progress reporting for non-linear formulas, and updates project/version metadata.

Changes:

  • Add /island donate inv flow (tab-complete, confirmation prompt, inventory scan + donation logging) and localize new messages.
  • Improve custom-block rendering by resolving representative ItemStacks (Oraxen/Nexo/ItemsAdder/CraftEngine) and using item meta display names in panels/commands.
  • Compute “points within current level” and use it to show accurate level progress for non-linear level formulas; bump addon + dependency versions.

Reviewed changes

Copilot reviewed 31 out of 31 changed files in this pull request and generated 2 comments.

Show a summary per file
FileDescription
src/main/java/world/bentobox/level/commands/IslandDonateCommand.javaAdds inv subcommand, inventory donation execution, and revised tab-complete logic.
src/test/java/world/bentobox/level/commands/IslandDonateCommandTest.javaAdds tab-complete and inv donation tests.
src/main/resources/locales/en-US.ymlUpdates donate usage string; adds donate.inv.* messages.
src/main/resources/locales/cs.ymlAdds donate.inv.* messages.
src/main/resources/locales/de.ymlAdds donate.inv.* messages.
src/main/resources/locales/es.ymlAdds donate.inv.* messages.
src/main/resources/locales/fr.ymlAdds donate.inv.* messages.
src/main/resources/locales/hu.ymlAdds donate.inv.* messages.
src/main/resources/locales/id.ymlAdds donate.inv.* messages.
src/main/resources/locales/ko.ymlAdds donate.inv.* messages.
src/main/resources/locales/lv.ymlAdds donate.inv.* messages.
src/main/resources/locales/nl.ymlAdds donate.inv.* messages.
src/main/resources/locales/pl.ymlAdds donate.inv.* messages.
src/main/resources/locales/pt.ymlAdds donate.inv.* messages.
src/main/resources/locales/ru.ymlAdds donate.inv.* messages.
src/main/resources/locales/tr.ymlAdds donate.inv.* messages.
src/main/resources/locales/uk.ymlAdds donate.inv.* messages.
src/main/resources/locales/vi.ymlAdds donate.inv.* messages.
src/main/resources/locales/zh-CN.ymlAdds donate.inv.* messages.
src/main/java/world/bentobox/level/util/Utils.javaAdds helpers to resolve custom-block ItemStacks and display names.
src/main/java/world/bentobox/level/panels/ValuePanel.javaUses custom-block ItemStack icons + display names where available.
src/main/java/world/bentobox/level/panels/DonationPanel.javaSupports custom-block IDs for value lookup and donation logging.
src/main/java/world/bentobox/level/panels/DetailsPanel.javaUses shared custom-block resolution/display-name helpers.
src/main/java/world/bentobox/level/Level.javaAdds getCustomBlockId(ItemStack) for Oraxen/Nexo/ItemsAdder/CraftEngine.
src/main/java/world/bentobox/level/commands/IslandValueCommand.javaUses getCustomBlockId() and custom display-name resolution for “hand” value lookups.
src/main/java/world/bentobox/level/commands/IslandLevelCommand.javaDisplays progress using “points from current level” and computed interval size.
src/main/java/world/bentobox/level/calculators/Results.javaAdds pointsFromCurrentLevel field + getters/setters.
src/test/java/world/bentobox/level/calculators/ResultsTest.javaAdds unit tests for pointsFromCurrentLevel.
src/main/java/world/bentobox/level/calculators/IslandLevelCalculator.javaUses binary search to compute points-to-next-level and points-within-current-level.
src/main/resources/addon.ymlBumps addon api-version.
pom.xmlBumps build version to 2.27.0 and BentoBox dependency to 3.15.1-SNAPSHOT.
Comments suppressed due to low confidence (1)

src/main/java/world/bentobox/level/commands/IslandDonateCommand.java:300

  • tabComplete() now assumes BentoBox prepends the leaf command label into args (using args.get(1) for the first user argument). This is inconsistent with other commands/tests in this repo (which treat args as only user-typed arguments) and breaks completion for /island donate hand <TAB>: with args like ["hand", ""], the code returns hand/inv suggestions instead of the held amount. Consider supporting the existing args shape (no label) or handling both forms by detecting and adjusting the starting index dynamically.
 public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
// BentoBox includes the command label as args.get(0); the user-typed args start at index 1.
String lastArg = !args.isEmpty() ? args.get(args.size() - 1) : "";
String handKeyword = user.getTranslation("island.donate.hand.keyword");
String invKeyword = user.getTranslation("island.donate.inv.keyword");
// First user-arg slot: suggest "hand" and "inv".
if (args.size() <= 2) {
return Optional.of(Util.tabLimit(List.of(handKeyword, invKeyword), lastArg));
}
// Second user-arg slot after "hand": suggest the held count.
if (args.size() == 3 && isHandKeyword(user, 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());

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

Comment on lines +175 to +183
@Test
void testTabCompleteFirstArgFromBentoBoxFlow() {
// BentoBox passes the leaf command label as args.get(0); the partial first
// user arg sits in args.get(1). Empty string = bare "/island donate <TAB>".
var result = cmd.tabComplete(user, "donate", List.of("donate", ""));
assertTrue(result.isPresent());
assertTrue(result.get().contains("hand"));
assertTrue(result.get().contains("inv"));
}
time-out: "<red>The level calculation took too long. Please try again later."
donate:
parameters: "[hand [amount]]"
parameters: "[hand [amount]] [inv]"
tastybentoand others added 6 commits May 11, 2026 20:38
Adds a `donations-only` config option that bypasses the island chunk scan
entirely. The island level is computed only from blocks donated via
`/island donate`, removing the per-recalculation CPU cost of scanning.
When the option is enabled:
- IslandLevelCalculator.scanIsland short-circuits to tidyUp(), which adds
the donated points (`LevelsManager.getDonatedPoints`) and runs the
configured level-calc formula on those points alone.
- The /island detail command is not registered, since there are no
scanned blocks to break down per the issue thread.
- /island level, /island top, /island value, and /island donate continue
to work; /island level reports the level based on donations only.
Closes#430.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When an admin enables donations-only mid-game, existing islands already
have an `initialCount` recorded from the original starter-island scan.
The level formula subtracts `initialCount` from raw points when
`zero-new-island-levels` is on — but under donations-only, raw points
are just the donated total, which is typically much smaller than the
recorded initial count. The result was a huge negative `modifiedPoints`
and a wildly negative level.
Ignore `initialCount` (treat as 0) whenever donations-only is enabled:
- `calculateLevel(rawPoints)` no longer subtracts it
- the `pointsFromCurrentLevel` binary search no longer floors at it
- the report no longer prints it (would be misleading, since it isn't
applied to the level math)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The previous short-circuit in scanIsland skipped every scan when
donations-only was enabled — including the zero-island scan that fires
on IslandCreatedEvent / IslandResettedEvent. That meant new islands
created during a donations-only window got initialCount = 0, so if an
admin later disabled donations-only the player's entire current block
total would count toward their level (no handicap subtracted).
Restrict the short-circuit to non-zero-island scans. The zero-island
scan still runs and records the real handicap into initialCount; it is
just ignored by calculateLevel while donations-only is on (per the
existing fix in this PR). When donations-only is later disabled, the
stored initialCount is correctly subtracted by calculateLevel as before.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The viewer button at the bottom of the top-ten panel rendered with a
"Click to view" tooltip and opened the details panel on click. That
panel breaks down scanned blocks, which is meaningless in donations-only
mode (and /island detail is not registered there either).
Add a donations-only check to the VIEW action filter so it's removed
from activeActions for that button when donations-only is enabled.
Filtering it out also drops the "Click to view" tooltip — no template
or locale change needed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ore-initial-count
fix: ignore initialCount in donations-only mode (#430)
@sonarqubecloud

Copy link
Copy Markdown

@tastybento
tastybento merged commit 23e4e77 into masterMay 13, 2026
5 checks passed
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.

4 participants

@tastybento@msmith-codes
, '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

Release 2.27.0 - #431

Merged
tastybento merged 24 commits into
masterfrom
develop
May 13, 2026
Merged

Release 2.27.0#431
tastybento merged 24 commits into
masterfrom
develop

Conversation

@tastybento

Copy link
Copy Markdown
Member

No description provided.

tastybentoand others added 18 commits May 3, 2026 22:10
Adds a confirmable "inv" subcommand that scans the player's inventory
for donatable blocks, lists each material with its point value plus a
total in the confirmation prompt, and on confirm donates all of them
in one go. Items with no value or that are not donatable blocks remain
in the inventory.
Also fixes the donate tab-complete: the args list BentoBox passes to a
subcommand includes the leaf label at index 0, so the previous
size-1 check never fired in real use and only the auto "help"
suggestion appeared. Tests now exercise the realistic args shape.
Bumps build version to 2.27.0.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds the four new island.donate.inv keys (keyword, confirm-header,
confirm-line, confirm-total) to every non-English locale file. MiniMessage
tags and placeholders are preserved verbatim; only the human-readable
text was translated.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Addresses SonarCloud findings about duplicated string literals in
IslandDonateCommand.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
feat: /island donate inv — donate everything from inventory
…e, detail, and donate menus
Agent-Logs-Url: https://github.com/BentoBoxWorld/Level/sessions/daf183a6-549f-4946-900c-5719c0a27e81
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>
…inv donation value
Agent-Logs-Url: https://github.com/BentoBoxWorld/Level/sessions/daf183a6-549f-4946-900c-5719c0a27e81
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>
FIXED: Negative values in progression while using a non-linear function.
The forward and backward point-boundary scans could each iterate up to
10M times calling calculateLevel() (string parse + eval) on the primary
thread. Binary search reduces this to ~23 iterations. Also adds missing
ResultsTest coverage for pointsFromCurrentLevel.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…upport-menu
Add custom block support (Oraxen/Nexo/ItemsAdder/CraftEngine) in value, detail, and donate menus
The /is value panel rendered Oraxen/Nexo/ItemsAdder blocks as paper with
the prettified config key as the name. Look up the real ItemStack from
the plugin's registry and use it as the icon, plus the item meta display
name when present. Lookup helper is extracted to Utils so DetailsPanel
and ValuePanel share it.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…and-name
Fix custom-block icon and display name in value panel (#426)
Three call sites were missing CraftEngine support, so /is value hand
returned "no value" for held CraftEngine items, the value panel showed
a paper icon with the prettified namespaced key, and the chat output
used the raw key instead of the configured display name:
- Level.getCustomBlockId now checks CraftEngineHook.getItemId, so a
held custom item is mapped to its namespaced ID.
- Utils.getCustomBlockItemStack now delegates to
CraftEngineHook.getItemStack so the panel renders the real icon.
- Utils.getCustomBlockDisplayName now also reads the modern
minecraft:item_name component (hasItemName/getItemName) used by
CraftEngine, in addition to the legacy display.Name used by Oraxen,
Nexo, and ItemsAdder.
- IslandValueCommand.printValue routes string IDs through the same
getCustomBlockItemStack/getCustomBlockDisplayName path used by the
panel, so the chat message shows the configured display name.
Requires BentoBox >= 3.15.1-SNAPSHOT (BentoBoxWorld/BentoBox#2973 for
the new getItemId helper).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…y-name
fix: recognize CraftEngine items in value lookups (#428)

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

Release 2.27.0 expands Level’s donation and custom-block support, improves level-progress reporting for non-linear formulas, and updates project/version metadata.

Changes:

  • Add /island donate inv flow (tab-complete, confirmation prompt, inventory scan + donation logging) and localize new messages.
  • Improve custom-block rendering by resolving representative ItemStacks (Oraxen/Nexo/ItemsAdder/CraftEngine) and using item meta display names in panels/commands.
  • Compute “points within current level” and use it to show accurate level progress for non-linear level formulas; bump addon + dependency versions.

Reviewed changes

Copilot reviewed 31 out of 31 changed files in this pull request and generated 2 comments.

Show a summary per file
FileDescription
src/main/java/world/bentobox/level/commands/IslandDonateCommand.javaAdds inv subcommand, inventory donation execution, and revised tab-complete logic.
src/test/java/world/bentobox/level/commands/IslandDonateCommandTest.javaAdds tab-complete and inv donation tests.
src/main/resources/locales/en-US.ymlUpdates donate usage string; adds donate.inv.* messages.
src/main/resources/locales/cs.ymlAdds donate.inv.* messages.
src/main/resources/locales/de.ymlAdds donate.inv.* messages.
src/main/resources/locales/es.ymlAdds donate.inv.* messages.
src/main/resources/locales/fr.ymlAdds donate.inv.* messages.
src/main/resources/locales/hu.ymlAdds donate.inv.* messages.
src/main/resources/locales/id.ymlAdds donate.inv.* messages.
src/main/resources/locales/ko.ymlAdds donate.inv.* messages.
src/main/resources/locales/lv.ymlAdds donate.inv.* messages.
src/main/resources/locales/nl.ymlAdds donate.inv.* messages.
src/main/resources/locales/pl.ymlAdds donate.inv.* messages.
src/main/resources/locales/pt.ymlAdds donate.inv.* messages.
src/main/resources/locales/ru.ymlAdds donate.inv.* messages.
src/main/resources/locales/tr.ymlAdds donate.inv.* messages.
src/main/resources/locales/uk.ymlAdds donate.inv.* messages.
src/main/resources/locales/vi.ymlAdds donate.inv.* messages.
src/main/resources/locales/zh-CN.ymlAdds donate.inv.* messages.
src/main/java/world/bentobox/level/util/Utils.javaAdds helpers to resolve custom-block ItemStacks and display names.
src/main/java/world/bentobox/level/panels/ValuePanel.javaUses custom-block ItemStack icons + display names where available.
src/main/java/world/bentobox/level/panels/DonationPanel.javaSupports custom-block IDs for value lookup and donation logging.
src/main/java/world/bentobox/level/panels/DetailsPanel.javaUses shared custom-block resolution/display-name helpers.
src/main/java/world/bentobox/level/Level.javaAdds getCustomBlockId(ItemStack) for Oraxen/Nexo/ItemsAdder/CraftEngine.
src/main/java/world/bentobox/level/commands/IslandValueCommand.javaUses getCustomBlockId() and custom display-name resolution for “hand” value lookups.
src/main/java/world/bentobox/level/commands/IslandLevelCommand.javaDisplays progress using “points from current level” and computed interval size.
src/main/java/world/bentobox/level/calculators/Results.javaAdds pointsFromCurrentLevel field + getters/setters.
src/test/java/world/bentobox/level/calculators/ResultsTest.javaAdds unit tests for pointsFromCurrentLevel.
src/main/java/world/bentobox/level/calculators/IslandLevelCalculator.javaUses binary search to compute points-to-next-level and points-within-current-level.
src/main/resources/addon.ymlBumps addon api-version.
pom.xmlBumps build version to 2.27.0 and BentoBox dependency to 3.15.1-SNAPSHOT.
Comments suppressed due to low confidence (1)

src/main/java/world/bentobox/level/commands/IslandDonateCommand.java:300

  • tabComplete() now assumes BentoBox prepends the leaf command label into args (using args.get(1) for the first user argument). This is inconsistent with other commands/tests in this repo (which treat args as only user-typed arguments) and breaks completion for /island donate hand <TAB>: with args like ["hand", ""], the code returns hand/inv suggestions instead of the held amount. Consider supporting the existing args shape (no label) or handling both forms by detecting and adjusting the starting index dynamically.
 public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
// BentoBox includes the command label as args.get(0); the user-typed args start at index 1.
String lastArg = !args.isEmpty() ? args.get(args.size() - 1) : "";
String handKeyword = user.getTranslation("island.donate.hand.keyword");
String invKeyword = user.getTranslation("island.donate.inv.keyword");
// First user-arg slot: suggest "hand" and "inv".
if (args.size() <= 2) {
return Optional.of(Util.tabLimit(List.of(handKeyword, invKeyword), lastArg));
}
// Second user-arg slot after "hand": suggest the held count.
if (args.size() == 3 && isHandKeyword(user, 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());

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

Comment on lines +175 to +183
@Test
void testTabCompleteFirstArgFromBentoBoxFlow() {
// BentoBox passes the leaf command label as args.get(0); the partial first
// user arg sits in args.get(1). Empty string = bare "/island donate <TAB>".
var result = cmd.tabComplete(user, "donate", List.of("donate", ""));
assertTrue(result.isPresent());
assertTrue(result.get().contains("hand"));
assertTrue(result.get().contains("inv"));
}
time-out: "<red>The level calculation took too long. Please try again later."
donate:
parameters: "[hand [amount]]"
parameters: "[hand [amount]] [inv]"
tastybentoand others added 6 commits May 11, 2026 20:38
Adds a `donations-only` config option that bypasses the island chunk scan
entirely. The island level is computed only from blocks donated via
`/island donate`, removing the per-recalculation CPU cost of scanning.
When the option is enabled:
- IslandLevelCalculator.scanIsland short-circuits to tidyUp(), which adds
the donated points (`LevelsManager.getDonatedPoints`) and runs the
configured level-calc formula on those points alone.
- The /island detail command is not registered, since there are no
scanned blocks to break down per the issue thread.
- /island level, /island top, /island value, and /island donate continue
to work; /island level reports the level based on donations only.
Closes#430.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When an admin enables donations-only mid-game, existing islands already
have an `initialCount` recorded from the original starter-island scan.
The level formula subtracts `initialCount` from raw points when
`zero-new-island-levels` is on — but under donations-only, raw points
are just the donated total, which is typically much smaller than the
recorded initial count. The result was a huge negative `modifiedPoints`
and a wildly negative level.
Ignore `initialCount` (treat as 0) whenever donations-only is enabled:
- `calculateLevel(rawPoints)` no longer subtracts it
- the `pointsFromCurrentLevel` binary search no longer floors at it
- the report no longer prints it (would be misleading, since it isn't
applied to the level math)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The previous short-circuit in scanIsland skipped every scan when
donations-only was enabled — including the zero-island scan that fires
on IslandCreatedEvent / IslandResettedEvent. That meant new islands
created during a donations-only window got initialCount = 0, so if an
admin later disabled donations-only the player's entire current block
total would count toward their level (no handicap subtracted).
Restrict the short-circuit to non-zero-island scans. The zero-island
scan still runs and records the real handicap into initialCount; it is
just ignored by calculateLevel while donations-only is on (per the
existing fix in this PR). When donations-only is later disabled, the
stored initialCount is correctly subtracted by calculateLevel as before.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The viewer button at the bottom of the top-ten panel rendered with a
"Click to view" tooltip and opened the details panel on click. That
panel breaks down scanned blocks, which is meaningless in donations-only
mode (and /island detail is not registered there either).
Add a donations-only check to the VIEW action filter so it's removed
from activeActions for that button when donations-only is enabled.
Filtering it out also drops the "Click to view" tooltip — no template
or locale change needed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ore-initial-count
fix: ignore initialCount in donations-only mode (#430)
@sonarqubecloud

Copy link
Copy Markdown

@tastybento
tastybento merged commit 23e4e77 into masterMay 13, 2026
5 checks passed
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.

4 participants

@tastybento@msmith-codes
, '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

Release 2.27.0 - #431

Merged
tastybento merged 24 commits into
masterfrom
develop
May 13, 2026
Merged

Release 2.27.0#431
tastybento merged 24 commits into
masterfrom
develop

Conversation

@tastybento

Copy link
Copy Markdown
Member

No description provided.

tastybentoand others added 18 commits May 3, 2026 22:10
Adds a confirmable "inv" subcommand that scans the player's inventory
for donatable blocks, lists each material with its point value plus a
total in the confirmation prompt, and on confirm donates all of them
in one go. Items with no value or that are not donatable blocks remain
in the inventory.
Also fixes the donate tab-complete: the args list BentoBox passes to a
subcommand includes the leaf label at index 0, so the previous
size-1 check never fired in real use and only the auto "help"
suggestion appeared. Tests now exercise the realistic args shape.
Bumps build version to 2.27.0.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds the four new island.donate.inv keys (keyword, confirm-header,
confirm-line, confirm-total) to every non-English locale file. MiniMessage
tags and placeholders are preserved verbatim; only the human-readable
text was translated.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Addresses SonarCloud findings about duplicated string literals in
IslandDonateCommand.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
feat: /island donate inv — donate everything from inventory
…e, detail, and donate menus
Agent-Logs-Url: https://github.com/BentoBoxWorld/Level/sessions/daf183a6-549f-4946-900c-5719c0a27e81
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>
…inv donation value
Agent-Logs-Url: https://github.com/BentoBoxWorld/Level/sessions/daf183a6-549f-4946-900c-5719c0a27e81
Co-authored-by: tastybento <4407265+tastybento@users.noreply.github.com>
FIXED: Negative values in progression while using a non-linear function.
The forward and backward point-boundary scans could each iterate up to
10M times calling calculateLevel() (string parse + eval) on the primary
thread. Binary search reduces this to ~23 iterations. Also adds missing
ResultsTest coverage for pointsFromCurrentLevel.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…upport-menu
Add custom block support (Oraxen/Nexo/ItemsAdder/CraftEngine) in value, detail, and donate menus
The /is value panel rendered Oraxen/Nexo/ItemsAdder blocks as paper with
the prettified config key as the name. Look up the real ItemStack from
the plugin's registry and use it as the icon, plus the item meta display
name when present. Lookup helper is extracted to Utils so DetailsPanel
and ValuePanel share it.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…and-name
Fix custom-block icon and display name in value panel (#426)
Three call sites were missing CraftEngine support, so /is value hand
returned "no value" for held CraftEngine items, the value panel showed
a paper icon with the prettified namespaced key, and the chat output
used the raw key instead of the configured display name:
- Level.getCustomBlockId now checks CraftEngineHook.getItemId, so a
held custom item is mapped to its namespaced ID.
- Utils.getCustomBlockItemStack now delegates to
CraftEngineHook.getItemStack so the panel renders the real icon.
- Utils.getCustomBlockDisplayName now also reads the modern
minecraft:item_name component (hasItemName/getItemName) used by
CraftEngine, in addition to the legacy display.Name used by Oraxen,
Nexo, and ItemsAdder.
- IslandValueCommand.printValue routes string IDs through the same
getCustomBlockItemStack/getCustomBlockDisplayName path used by the
panel, so the chat message shows the configured display name.
Requires BentoBox >= 3.15.1-SNAPSHOT (BentoBoxWorld/BentoBox#2973 for
the new getItemId helper).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…y-name
fix: recognize CraftEngine items in value lookups (#428)

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

Release 2.27.0 expands Level’s donation and custom-block support, improves level-progress reporting for non-linear formulas, and updates project/version metadata.

Changes:

  • Add /island donate inv flow (tab-complete, confirmation prompt, inventory scan + donation logging) and localize new messages.
  • Improve custom-block rendering by resolving representative ItemStacks (Oraxen/Nexo/ItemsAdder/CraftEngine) and using item meta display names in panels/commands.
  • Compute “points within current level” and use it to show accurate level progress for non-linear level formulas; bump addon + dependency versions.

Reviewed changes

Copilot reviewed 31 out of 31 changed files in this pull request and generated 2 comments.

Show a summary per file
FileDescription
src/main/java/world/bentobox/level/commands/IslandDonateCommand.javaAdds inv subcommand, inventory donation execution, and revised tab-complete logic.
src/test/java/world/bentobox/level/commands/IslandDonateCommandTest.javaAdds tab-complete and inv donation tests.
src/main/resources/locales/en-US.ymlUpdates donate usage string; adds donate.inv.* messages.
src/main/resources/locales/cs.ymlAdds donate.inv.* messages.
src/main/resources/locales/de.ymlAdds donate.inv.* messages.
src/main/resources/locales/es.ymlAdds donate.inv.* messages.
src/main/resources/locales/fr.ymlAdds donate.inv.* messages.
src/main/resources/locales/hu.ymlAdds donate.inv.* messages.
src/main/resources/locales/id.ymlAdds donate.inv.* messages.
src/main/resources/locales/ko.ymlAdds donate.inv.* messages.
src/main/resources/locales/lv.ymlAdds donate.inv.* messages.
src/main/resources/locales/nl.ymlAdds donate.inv.* messages.
src/main/resources/locales/pl.ymlAdds donate.inv.* messages.
src/main/resources/locales/pt.ymlAdds donate.inv.* messages.
src/main/resources/locales/ru.ymlAdds donate.inv.* messages.
src/main/resources/locales/tr.ymlAdds donate.inv.* messages.
src/main/resources/locales/uk.ymlAdds donate.inv.* messages.
src/main/resources/locales/vi.ymlAdds donate.inv.* messages.
src/main/resources/locales/zh-CN.ymlAdds donate.inv.* messages.
src/main/java/world/bentobox/level/util/Utils.javaAdds helpers to resolve custom-block ItemStacks and display names.
src/main/java/world/bentobox/level/panels/ValuePanel.javaUses custom-block ItemStack icons + display names where available.
src/main/java/world/bentobox/level/panels/DonationPanel.javaSupports custom-block IDs for value lookup and donation logging.
src/main/java/world/bentobox/level/panels/DetailsPanel.javaUses shared custom-block resolution/display-name helpers.
src/main/java/world/bentobox/level/Level.javaAdds getCustomBlockId(ItemStack) for Oraxen/Nexo/ItemsAdder/CraftEngine.
src/main/java/world/bentobox/level/commands/IslandValueCommand.javaUses getCustomBlockId() and custom display-name resolution for “hand” value lookups.
src/main/java/world/bentobox/level/commands/IslandLevelCommand.javaDisplays progress using “points from current level” and computed interval size.
src/main/java/world/bentobox/level/calculators/Results.javaAdds pointsFromCurrentLevel field + getters/setters.
src/test/java/world/bentobox/level/calculators/ResultsTest.javaAdds unit tests for pointsFromCurrentLevel.
src/main/java/world/bentobox/level/calculators/IslandLevelCalculator.javaUses binary search to compute points-to-next-level and points-within-current-level.
src/main/resources/addon.ymlBumps addon api-version.
pom.xmlBumps build version to 2.27.0 and BentoBox dependency to 3.15.1-SNAPSHOT.
Comments suppressed due to low confidence (1)

src/main/java/world/bentobox/level/commands/IslandDonateCommand.java:300

  • tabComplete() now assumes BentoBox prepends the leaf command label into args (using args.get(1) for the first user argument). This is inconsistent with other commands/tests in this repo (which treat args as only user-typed arguments) and breaks completion for /island donate hand <TAB>: with args like ["hand", ""], the code returns hand/inv suggestions instead of the held amount. Consider supporting the existing args shape (no label) or handling both forms by detecting and adjusting the starting index dynamically.
 public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
// BentoBox includes the command label as args.get(0); the user-typed args start at index 1.
String lastArg = !args.isEmpty() ? args.get(args.size() - 1) : "";
String handKeyword = user.getTranslation("island.donate.hand.keyword");
String invKeyword = user.getTranslation("island.donate.inv.keyword");
// First user-arg slot: suggest "hand" and "inv".
if (args.size() <= 2) {
return Optional.of(Util.tabLimit(List.of(handKeyword, invKeyword), lastArg));
}
// Second user-arg slot after "hand": suggest the held count.
if (args.size() == 3 && isHandKeyword(user, 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());

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

Comment on lines +175 to +183
@Test
void testTabCompleteFirstArgFromBentoBoxFlow() {
// BentoBox passes the leaf command label as args.get(0); the partial first
// user arg sits in args.get(1). Empty string = bare "/island donate <TAB>".
var result = cmd.tabComplete(user, "donate", List.of("donate", ""));
assertTrue(result.isPresent());
assertTrue(result.get().contains("hand"));
assertTrue(result.get().contains("inv"));
}
time-out: "<red>The level calculation took too long. Please try again later."
donate:
parameters: "[hand [amount]]"
parameters: "[hand [amount]] [inv]"
tastybentoand others added 6 commits May 11, 2026 20:38
Adds a `donations-only` config option that bypasses the island chunk scan
entirely. The island level is computed only from blocks donated via
`/island donate`, removing the per-recalculation CPU cost of scanning.
When the option is enabled:
- IslandLevelCalculator.scanIsland short-circuits to tidyUp(), which adds
the donated points (`LevelsManager.getDonatedPoints`) and runs the
configured level-calc formula on those points alone.
- The /island detail command is not registered, since there are no
scanned blocks to break down per the issue thread.
- /island level, /island top, /island value, and /island donate continue
to work; /island level reports the level based on donations only.
Closes#430.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When an admin enables donations-only mid-game, existing islands already
have an `initialCount` recorded from the original starter-island scan.
The level formula subtracts `initialCount` from raw points when
`zero-new-island-levels` is on — but under donations-only, raw points
are just the donated total, which is typically much smaller than the
recorded initial count. The result was a huge negative `modifiedPoints`
and a wildly negative level.
Ignore `initialCount` (treat as 0) whenever donations-only is enabled:
- `calculateLevel(rawPoints)` no longer subtracts it
- the `pointsFromCurrentLevel` binary search no longer floors at it
- the report no longer prints it (would be misleading, since it isn't
applied to the level math)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The previous short-circuit in scanIsland skipped every scan when
donations-only was enabled — including the zero-island scan that fires
on IslandCreatedEvent / IslandResettedEvent. That meant new islands
created during a donations-only window got initialCount = 0, so if an
admin later disabled donations-only the player's entire current block
total would count toward their level (no handicap subtracted).
Restrict the short-circuit to non-zero-island scans. The zero-island
scan still runs and records the real handicap into initialCount; it is
just ignored by calculateLevel while donations-only is on (per the
existing fix in this PR). When donations-only is later disabled, the
stored initialCount is correctly subtracted by calculateLevel as before.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The viewer button at the bottom of the top-ten panel rendered with a
"Click to view" tooltip and opened the details panel on click. That
panel breaks down scanned blocks, which is meaningless in donations-only
mode (and /island detail is not registered there either).
Add a donations-only check to the VIEW action filter so it's removed
from activeActions for that button when donations-only is enabled.
Filtering it out also drops the "Click to view" tooltip — no template
or locale change needed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ore-initial-count
fix: ignore initialCount in donations-only mode (#430)
@sonarqubecloud

Copy link
Copy Markdown

@tastybento
tastybento merged commit 23e4e77 into masterMay 13, 2026
5 checks passed
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.

4 participants

@tastybento@msmith-codes