Repository navigation
feat(seasons): rotate season worlds with per-season progress - #36
Merged
Merged
Conversation
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Contributor
Test results 249 files 249 suites 2m 30s ⏱️ Results for commit b060602. ♻️ This comment has been updated with latest results. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Challenge tiers and task completions are keyed by season, and task completions also by prestige step (always 0 for now). Existing rows migrate to season "legacy" at step 0. Progress services resolve the season through a CurrentSeason port, which returns "legacy" until the season lifecycle exists.
Adds the season run table in its own Flyway folder and history table, a SeasonRunRepository port with a SeasonRunConflictException, and the JPA adapter. A stale save is rejected through @Version. The switch from one active season to the next is one unit of work, and the partial unique index keeps a second ACTIVE row out of the table.
The effective end of the active season after a postponement or an advance and the notices already sent are stored on the season run, so a restart keeps the moved end and does not send a notice twice. Each decision reads them back before it runs, so building the service never reads the database.
Wires the season lifecycle into the plugin: a season service behind CurrentSeason and SeasonAdminUseCase, a Multibinder for transition listeners, Bukkit adapters for season worlds, the once per season reset and the announcements, a join listener that routes players into the active season world and sends the final week line, and a scheduler that ticks the season service every 600 ticks once the database warm-up is done. The season run repository joins the async warm-up. Without a seasons directory the plugin behaves as before: no season is loaded and no transition runs.
…ason A server that stopped between the switch and the player move restarts with the season state not yet read, so a joining player was left in the main world with no reset. The join now waits, checking every 10 ticks, until the active season and its world are known, then routes and resets the player once. Quitting while waiting cancels the check.
TheMeinerLP
force-pushed
the
feat/season-lifecycle
branch
from
October 28, 2026 20:59
26fdfb8 to
b060602
Compare
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.
Proposed changes
A SkyGrid world only stays exciting for so long. After a few weeks the early players have explored, built and finished every challenge, and someone who joins later lands in a world that is already used up. This change lets the server run in seasons, as proposed in
add-season-lifecycle(#28). Every season gets a fresh, seed-generated world. Challenge and task progress count per season, and the old world goes to an archive directory where an external map renderer can pick it up.An admin describes seasons as files under
seasons/, with a start, a duration, a preset and the active challenges. The plugin prepares the next world ahead of time and switches at the boundary. It moves players over and resets each one once on their first entry into the new season. Players hear about the end on fixed dates (7 days, 24 hours, 1 hour, 5 minutes) with the absolute date and a plain list of what is reset and what is kept. There is no countdown pressure in the sidebar.season advance confirmnever ends a season earlier than the configured minimum notice; ending at once needsseason advance now confirmand is logged with the actor. A postponed end and the notices already sent are stored, so a restart neither forgets a postponement nor repeats a notice.Every step of the switch is persisted before and after its side effect, so a crash or restart resumes where it stopped. A server without season files behaves exactly as before: one continuous
legacyworld, no world created and no transition. Existing progress is moved into seasonlegacyby the migrations, with no row lost. I checked that on the live SkyGrid server (in maintenance) with a jar built from this branch. All three database units migrated on the async warm-up afterDone,season listreports no seasons, and the tier reset still works.Known limits, also stated in
docs/ADMIN.md:season retryresumes it.Type of change
Checklist
docs/ADMIN.md, Seasons section)./gradlew build testpasses locally (all touched modules with--max-workers=2, plusshadowJar)