Skip to content

Release 1.27.0 - #552

Merged
tastybento merged 10 commits into
masterfrom
develop
Aug 8, 2026
Merged

Release 1.27.0#552
tastybento merged 10 commits into
masterfrom
develop

Conversation

@tastybento

Copy link
Copy Markdown
Member

Release 1.27.0.

Headline

Island progress is no longer lost when the server restarts. Reported on Discord as "it's not saving the progress" — a player online through a restart came back with their block count rolled back to the last checkpoint, up to 49 blocks undone, every restart. The shutdown save was queued rather than written, and every BentoBox before 3.22.0 discarded that queue on the way out.

Also in this release: MiniMessage and hex colours in phase text (holograms, action bar, locale strings), a new island.save-every setting, and a rewritten reference phase file.

🔺 This release raises the minimum BentoBox version

bentobox.version and addon.yml api-version both move to 3.22.0, because the shutdown fix uses saveObjectNow() which was added there. Without the api-version bump the addon would load on an older core and throw NoSuchMethodError at shutdown — worse than the bug being fixed. It now refuses to load with "Please update BentoBox".

Knock-on effect for admins: BentoBox 3.18.0+ requires a Java 25 server, so 1.27.0 does too. This is called out prominently in the release notes.

What's in it

PR Change
#550 🔺⚙️ Shutdown save writes directly; new island.save-every (default 10, was a hardcoded 50)
#551 MiniMessage, hex and gradient support in phase text; fixes § codes rendering literally
#548 Reference phase file now explains weights vs positions vs start block
#547 CI: publish-platforms pin bumped to the multipart-JSON fix

Also on this branch: a CI fix moving the build to JDK 25. BentoBox 3.18.0+ ships Java 25 class files, which a JDK 21 javac cannot read at all — the build failed against every BentoBox type until the runner moved to 25. The addon still targets Java 21 via <release>.

Verification

  • Full suite green on develop.
  • Boot-tested on two real servers: BentoBox 3.15.1 refuses to load the addon with the intended message and no linkage error; BentoBox 3.22.1-SNAPSHOT enables, runs, and disables cleanly.
  • Not verified in-game: a real block count surviving a restart, and hologram rendering. Both are covered by unit tests through the real code paths, but neither was watched on a live server with a player.

Release notes for the draft release are prepared separately.

🤖 Generated with Claude Code

https://claude.ai/code/session_014t1DSo2wMbTWZLcwXpwUmQ

tastybento and others added 10 commits July 29, 2026 09:00
The pinned SHA (ca2dcd16, 2026-07-03) predates BentoBoxWorld/.github#13,
which moved the CurseForge `metadata` and Hangar `versionUpload` JSON out of
inline `-F` values and into files. curl treats `;` in an inline -F value as
the start of a `type=`/`filename=` attribute, so a release body containing a
semicolon truncates the JSON: the 1.26.3 publish failed with CurseForge
"Error in field `metadata`: Invalid JSON" and Hangar "Failed to read request".
Earlier releases only passed because their notes happened to contain no
semicolons.

Pin moved to master HEAD 1f91a0e, which contains the fix.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SAQ3YQkcfRoCZEwa6SPJcp
ci: bump publish-platforms pin to the multipart-JSON fix
0_plains.yml is the reference file admins read first, but it never said
what the numbers after a Material or EntityType are. An admin asked, and
they were right to guess weighting: they are relative weights in a single
raffle - not counts and not percentages - and blocks, mobs and
custom-blocks all draw from that same pool, so a mob weight is directly
comparable to a block weight and pushes every block's share down.

The header now separates the three distinct kinds of number a phase file
contains, since that is the real source of the confusion:

  1. blocks/mobs/custom-blocks values are weights, one shared pool
  2. fixedBlocks and holograms keys are positions within the phase, from 0
  3. the top-level key is the section name - phases_index.yml has owned
     phase order and length since 1.26.0

Each section then gets its own explanation with the real Plains numbers
worked out (11450 block weights + 665 mob weights = 12115, so
GRASS_BLOCK: 2000 is 16.5% and COW: 150 is 1.2%), plus the CHEST
two-stage roll, the mob/custom-block types that were missing from the
list, and version gating.

Comments only - every block, mob and weight is unchanged.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017zwLryefnJ6wG76JmYNamx
docs: rewrite the phase 0 comments to explain what the numbers mean
A player breaking blocks and then sitting through a restart would come back
to their block count rolled back to the last checkpoint - up to 49 blocks of
progress gone, repeatedly, on every restart.

The shutdown save was queued, not written. onDisable() called saveCache(),
which uses saveObjectAsync(), and this addon is a Pladdon: the server disables
it before BentoBox, so the write landed in a queue that BentoBox had to drain
on its way out. BentoBox 3.22.0 added that drain (flushAll), but every earlier
version discarded it silently.

Write directly on shutdown instead, via a new saveCacheNow() using
saveObjectNow(). That removes the dependency on core behaviour entirely rather
than relying on a specific BentoBox version getting it right.

saveObjectNow() is BentoBox 3.22.0 API, so bump the dependency and raise
api-version to match. Without the api-version bump the addon would still load
on an older core and throw NoSuchMethodError at shutdown, which is worse than
the bug being fixed. It now refuses to load with "Please update BentoBox".

Also make the periodic save interval configurable as island.save-every,
defaulting to 10 rather than the hardcoded 50. Nothing helps if the server is
SIGKILLed, but this caps what an unclean kill can cost at 9 blocks.

Reported on Discord: progress reverting on every restart, BentoBox 3.15.0.

Test notes: the BentoBox bump broke 5 PhasesPanelTest tests, and fixing those
exposed 2 more. None were regressions - all 7 called
when(user.getTranslation(...)) on a real User rather than a mock, which stubs
nothing on the User and instead attaches to whichever mock the real method
last touched. 3.22.0's getTranslation(World, ...) calls getIWM().getAddon()
first, moving the target. Added a stubTranslation() helper that stubs the
LocalesManager these actually read from. The same pattern remains elsewhere in
that class and is worth a follow-up sweep.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014t1DSo2wMbTWZLcwXpwUmQ
An admin coloured a phase hologram with <green><bold>...</green> and got white
text with the tags shown literally.

Holograms deserialized with LegacyComponentSerializer.legacyAmpersand(), which
understands the 16 legacy & codes and nothing else - Adventure builds that
instance with hexColours=false, so even &#RRGGBB did not work. The action bar
used a second, separately configured serializer that did support hex but not
MiniMessage. Two display paths, two different answers to "what formatting can
I use here", neither documented where anyone would look.

Both now go through Util.parseMiniMessageOrLegacy, which accepts MiniMessage,
& and section codes, hex, and any mixture, and is cached on the BentoBox side.

This also fixes section codes being rendered as literal text. Translations come
back from User.getTranslation already converted to section codes, so anything
locale-sourced was being handed to a serializer bound to '&' - the starting
hologram (aoneblock.island.starting-hologram) and the action bar both took that
path. Phase file hologram lines never see the translation layer, which is why
the reported case showed raw MiniMessage tags rather than raw section codes.

The boss bar title is untouched: it uses the String-based Bukkit BossBar API
and BentoBox has already resolved its formatting by then.

Existing configs are unaffected. BentoBox's MiniMessage instance is the
non-strict one, so text containing stray angle brackets is left as literal
text rather than throwing.

Documented the accepted syntax in the phase file, next to the holograms
section where the admin was already looking.

Util.parseMiniMessageOrLegacy is BentoBox 3.2.0 API, so this needs no
dependency bump.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014t1DSo2wMbTWZLcwXpwUmQ
BentoBox 3.18.0 onwards is compiled for Java 25 (Minecraft 26.x), so its class
files are version 69. A JDK 21 javac cannot parse those at all, and the build
died with "class file has wrong version 69.0, should be 65.0" against every
BentoBox type before it reached any of our code.

This only surfaced once the dependency moved to 3.22.0. It did not show up
locally because the dev machine is already on JDK 25 - the compiler reads the
newer class files happily and <release>21</release> still emits Java 21
bytecode, which is what the addon ships.

The addon's own target is unchanged: still Java 21 via <release> in the pom.
Only the JDK doing the compiling moves.

Also moves setup-java to v4 and the 'adopt' distribution to 'temurin', since
neither v3 nor adopt offers a Java 25 build.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014t1DSo2wMbTWZLcwXpwUmQ
fix: do not lose island progress when the server restarts
feat: support MiniMessage and hex colours in phase text
@sonarqubecloud

sonarqubecloud Bot commented Aug 8, 2026

Copy link
Copy Markdown

@tastybento
tastybento merged commit 7339721 into master Aug 8, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant