Skip to content

Release 1.26.1#542

Merged
tastybento merged 7 commits into
masterfrom
develop
Jul 21, 2026
Merged

Release 1.26.1#542
tastybento merged 7 commits into
masterfrom
develop

Conversation

@tastybento

Copy link
Copy Markdown
Member

Bug-fix release for the 1.26.0 phase index.

Draft release notes: see the 1.26.1 draft release.

🤖 Generated with Claude Code

https://claude.ai/code/session_013C4BPNygFKjoQenDwTyMNY

tastybento and others added 7 commits July 20, 2026 18:14
The 1.26.0 phase index shipped as a preset: upgrading servers got the
stock phases_index.yml, which references the current jar's file names.
Servers with older or custom phase layouts silently lost every phase
whose file name differed, never received Sulfur Caves (phase files are
only copied on fresh installs), and the admin phases GUI showed the
preset instead of the server's reality.

The index is now reconciled with the phases folder on every load - the
folder is the source of truth for which phases exist:

- An entry whose file and section exist on disk keeps its place.
- An entry whose file is missing is re-pointed at a folder file holding
  a phase with the same name (follows shipped file renames), failing
  that its file is restored from the addon jar (recovers phases added
  by an upgrade), failing that it is removed.
- Folder files not in the index are added. Numeric section keys give a
  position and length from the legacy start-block layout; non-numeric
  keys - now fully supported for custom phases, chests pair by file
  name so they work too - go to the end with the default length for
  the admin to arrange in the GUI.
- When repair was needed, or the index was freshly copied over an
  existing folder, lengths are refreshed from the gaps between the
  files' legacy keys, preserving the layout the server actually ran.

The admin phases GUI also gains shift-left-click to set a phase's
length via a chat prompt that shows the current value. The first such
edit writes adminLengths: true to the index, which permanently stops
reconciliation from recomputing lengths, so admin values survive later
file additions or renames.

GUI polish from feedback: phase icons fall back to the phase's first
block instead of stone, the how-to-use book wraps onto four lines, and
the lore lines are shortened for small screens.

Verified end-to-end on a real 26.2 server with a recreated legacy
phases folder plus the stock index: all renames re-pointed, Sulfur
Caves restored, lengths matched the server's true layout, and a second
boot reconciled nothing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013C4BPNygFKjoQenDwTyMNY
- Replace the Bukkit conversation API (deprecated for removal in Paper)
  with a direct AsyncChatEvent listener for the phase length prompt.
  Same behaviour: prompt shows the current length, whole numbers above
  zero apply, invalid input re-prompts, the cancel word or a 60 second
  timeout keeps the length. Input is applied on the main thread.
- Cut cognitive complexity: loadPhases delegates to setUpNewFolder and
  loadUsingIndex; scanPhaseFolder delegates per file and per section;
  reconcileIndex is decomposed into reconcileEntry, matchOnDisk,
  addKeyedDiscoveries, addUnkeyedDiscoveries, and
  refreshLengthsFromFolder around a small Reconciliation state object.
  No behaviour change - all 552 tests pass unchanged.
- Use static imports for Mockito times in tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013C4BPNygFKjoQenDwTyMNY
fix: reconcile the phase index with the phases folder on load
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013C4BPNygFKjoQenDwTyMNY
- Use possessive quantifiers in the version pattern so pathological
  inputs cannot recurse deeply in the regex engine (S5998).
- getPhaseSectionKey never returns null - the block number can be null
  when a phase came from the database via GSON, and it flows into
  createSection which requires a non-null path (S2637).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013C4BPNygFKjoQenDwTyMNY
Sonar's flow engine cannot assume repeated getter calls return the
same value, so the null check on getSection() did not protect the
returned value. Use locals with explicit null checks (S2637).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013C4BPNygFKjoQenDwTyMNY
@sonarqubecloud

Copy link
Copy Markdown

@tastybento
tastybento merged commit bb1f834 into master Jul 21, 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