Release 3.22.4 - #3078
Merged
Merged
Release 3.22.4#3078
Conversation
Addons like TopBlock ask BentoBox for player heads by name, and the resolver always went to the web (mc-heads or the Mojang API) even when the server already had the answer. On busy servers the web calls get rate limited and panels show default Steve heads. Two-tier fix in HeadGetter: - getHead() now short-circuits on the main thread when the player is online: Player#getPlayerProfile() is already complete with textures, so the head is cached and delivered synchronously. This also removes the async-callback race against a GUI that has since been redrawn. - The async resolver first asks the server to complete the profile via Bukkit.createPlayerProfile(...).update(), which Paper serves from its own session-service cache for any player who has logged in, with proper rate limiting for the rest. The mc-heads / Mojang HTTP paths remain as fallbacks for names the server cannot resolve. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018whk2Jwzd7iqEKFnwWqgQY
…ead-profiles Use server-provided player profiles for heads
zh-TW.yml was created from a copy of en-US.yml and kept its banner — the red/white stripes with a blue canton — so the language panel showed the US flag for Traditional Chinese. Replace it with a red field and blue canton, the closest banner-pattern approximation of the ROC flag. Every other locale already has its own design; this was the only copy. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PtmXKNJ5fSZ9sEumeFDEBc
fix: give zh-TW its own locale banner instead of the US flag
- S8786: replace super-linear \s*+ regex prefixes with linear alternatives in PlaceholderGrouper.stripTrailingHashNumber and the AddonClassLoader depend/softdepend splitting (split on the literal comma and strip each entry) - S9365: explicitly initialize commandRanks and metaData in the Island copy constructor instead of leaving them conditionally unassigned - Fix a genuine bug found alongside: the Island copy constructor wrote cloned spawn points back into the source island's map instead of the copy's, so spawn points were never copied Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018PgvHCn8nEPbF2MhZeebY2
Revert "fix: give zh-TW its own locale banner instead of the US flag"
… name] arg `/[admin] info <player>` used IslandsManager.getIsland(world, uuid), which only returns the player's primary/active island, so admins looking up a player with several islands only ever saw one of them. - `/[admin] info <player>` now loops over getIslands(world, uuid) and prints the admin info block for each island (own and team islands), matching what `/[admin] tp <player> <name>` already considers reachable. - New optional `[island name]` argument: `/[admin] info <player> <island name>` resolves island and home names via IslandGoCommand.getNameIslandMap with the same forgiving matching as `/[player] go` (exact, then case/space-insensitive, then unique prefix). Unknown names list the valid ones, as `tp` does. - Tab completion offers the target player's island/home names for arg 2. - Admin info now prints the island name (new `commands.admin.info.island-name` key) so the blocks can be told apart; translated into all bundled locales. - IslandGoCommand.resolveName is now public so admin commands can share it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WjU4tEg1H9fbcdErGLATAj
…lands feat(admin): show every island in /[admin] info <player>, add [island name] arg
…ProtectionCenter`
refactor: performance improvements
- S2789: replace the null-assigned Optional in LockAndBanListener.onVehicleMove with Optional.empty() plus an islandResolved flag, keeping the lazy single lookup per vehicle - S2583: drop the @nonnull generic annotations on IslandCache#grids - Map#get legitimately returns null for worlds with no grid, and the value annotation made those null checks look impossible - S2637: pass Objects.requireNonNull(p.getLocation()) to getIslandAt in InvincibleVisitorsListener - a live player's location is never null - S2184: cast the chunk coordinate additions to double in ClosestSafeSpotTeleport#scanAndPopulateBlockQueue before the implicit widening in BoundingBox#contains Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018PgvHCn8nEPbF2MhZeebY2
The setting was added after the 3.22.4 version bump, so 3.22.3 was stale on the @ConfigEntry and the getter/setter javadocs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018PgvHCn8nEPbF2MhZeebY2
- S6322: the flag/mob-limit click handlers mutated the lists returned by IWM#getHiddenFlags/getMobLimitSettings/getGeoLimitSettings, which are Collections.emptyList() (immutable) when the world is not a game world. Mutate the game mode's live WorldSettings list inside getAddon(world) .ifPresent(...) and save there - one addon lookup instead of several (CycleClick, IslandToggleClick, CommandCycleClick, GeoMobLimitTab) - S2259: User#closeInventory dereferenced the nullable player field; now a no-op for non-players - S2259: IslandResetCommand#resetIsland passed a possibly-null island to deleteOldIsland with only a post-hoc assert; replaced with a proper null guard and error message - S2259: IslandTeamGUI#leave used clickingUser.getUniqueId().equals(...) which NPEs for non-player users; switched to Objects.equals - S2259 (false positives): annotate the user parameter @nonnull on the command entry points the analyzer flagged - it assumed user could be null because IslandsManager#getIsland null-checks its parameter, then reported the user.sendMessage calls in the island==null branches. The framework never passes a null User here. - tests: stub GameModeAddon#getWorldSettings in the click-handler tests to carry the mutable lists the handlers now edit Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018PgvHCn8nEPbF2MhZeebY2
CompositeCommand.getCommandFromArgs called setLabel(arg) on the shared sub-command object while walking the typed arguments. After any player used /island h, every other player's tab completion advertised "h" in place of "go", and it flipped again whenever someone typed another alias. Brigadier made this far more visible because tabComplete now runs on every keystroke, so merely typing the alias was enough. execute() already derives the typed alias from the args array and passes it to call(), so the mutation was redundant. Drop it and add a regression test. Fixes #3075 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QTSR5y1ScxFzCqcXiAXXFT
…-mutation Stop renaming sub-commands to the alias a player typed (#3075)
PurgeRegionsService.delete() is dispatched from an async task by both the admin purge command and the housekeeping auto-purge, but it fired IslandEvent (DELETED / PURGED) directly from that thread. Paper rejects synchronous events fired off the main thread, so the age sweep crashed with "IslandEvent may only be triggered synchronously" after the region files had already been deleted, leaving island DB rows orphaned and reporting the purge as failed. Split delete() into two phases: disk I/O (region files, residual check, player data) stays on the calling thread, and the event firing plus cache/database removal is hopped onto the main thread via the scheduler and awaited, so the return value and summary log still reflect the final state. When already on the main thread the finalization runs inline. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XZRwXXfTUJLJFwSnzSgeRb
Fire purge IslandEvents on the main thread
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Release 3.22.4 — bug fix and performance release.
IslandEvent may only be triggered synchronously(Fire purge IslandEvents on the main thread #3077)/[admin] info <player>shows every island, adds[island name]argument (feat(admin): show every island in /[admin] info <player>, add [island name] arg #3074)island.history.max-entriesconfig option (refactor: performance improvements #3073)Draft release notes: https://github.com/BentoBoxWorld/BentoBox/releases (tag 3.22.4, draft)
🤖 Generated with Claude Code
https://claude.ai/code/session_01XZRwXXfTUJLJFwSnzSgeRb