fix: duration countdown resets to full duration on reload#52
Merged
Conversation
resumeRunningCountdowns() now calls handler.ensureTarget() instead of handler.onStart(), which is a no-op when a target is already present. The same guard was added to the legacy fallback path for handler-less countdown types. End-commands that fired once before a reload will no longer fire again unexpectedly. Bumped version to 1.4.3.
…th Java 21 and 25 - smoke-papermc: matrix over paper+folia × MC 1.21/26.1 × Java 21/25 Downloads server JARs from api.papermc.io; skips gracefully when a platform/version combo has no builds yet. - smoke-spigot: matrix over MC 1.21/26.1 × Java 21/25 Compiles Spigot via BuildTools (cached by MC×Java); skips gracefully when BuildTools does not yet support the requested version. Both jobs need unit-tests and feature-tests to pass first.
Add optional player targeting to ephemeral notifications so a notification can be shown to a specific subset of players rather than broadcasting to all online players. Changes: - Countdown: add targetPlayers Set<UUID> field + setTargetPlayers() + getTargetPlayers() + isVisibleTo(Player) helper that combines both visibility-permission and player-set checks - CountdownBuilder: add targetPlayers(Collection<Player>) builder method - Notification: add targetPlayers Set<UUID> field + getTargetPlayers() - NotificationBuilder: add players(Collection<Player>) builder method - EzCountdownApi: add sendNotification(Notification, Collection<Player>) default method (UnsupportedOperationException for 3rd-party impls) - EzCountdownApiImpl: implement per-player overload; original single-arg overload delegates to it; also respects players embedded in the Notification itself (via builder) - All display handlers (ActionBar, Title, Chat, BossBar, Scoreboard, Dialog, DisplayManager): replace inline permission check with countdown.isVisibleTo(player) - Tests: add per-player tests to EzCountdownApiImplTest and NotificationBuilderTest
Scheduler - Add compat.scheduler.SchedulerAdapter / TaskHandle interface - BukkitSchedulerAdapter (Paper/Spigot) and FoliaSchedulerAdapter (Folia) - SchedulerAdapterFactory: selects adapter at startup, falls back gracefully - Wire SchedulerAdapter through CountdownManager, FireworkShowManager, PatternScheduler, ChatInputListener, all listener/actions classes, SpigotIntegration, SpigotUpdateChecker Platform detection - compat.platform.PlatformDetector: detects Folia via RegionizedServer class - plugin.yml: folia-supported: true, api-version: 1.18 Version / material compat - compat.version.ServerVersionUtil: canonical runtime MC-version helper - compat.material.MaterialCompat: canonical cross-version material resolver - util.ServerVersionUtil / util.MaterialCompat: deprecated delegation stubs Scoreboard API modernisation (Paper 1.20.3+) - compat.scoreboard.ScoreboardCompat: uses registerNewObjective(Criteria, Component) when Criteria.DUMMY is available; falls back to legacy String overload; guards against null Criteria.DUMMY in test environments - ScoreboardCompat.resetObjective: replaces deprecated getEntries/resetScores with objective unregister+reregister - ScoreboardDisplay: delegate to ScoreboardCompat in display() and displayMultiple() Title API modernisation (Paper 1.18+) - compat.title.TitleCompat: prefers Adventure showTitle(Title) / clearTitle(); falls back to deprecated sendTitle / resetTitle on Spigot - TitleDisplay: delegate to TitleCompat; remove hand-rolled try/catch - TitleValidator: accept showTitle as valid title capability Tests - MissedRunPolicyTest / MissedRunPolicyRunAllEdgeCasesTest: stub registry.scheduler() with BukkitSchedulerAdapter - ScoreboardDisplayStackableTest: stub modern registerNewObjective overload All 145 tests pass.
…n MockBukkit PlayerMock.showTitle(net.kyori.adventure.title.Title) goes through the Adventure Audience default sendTitlePart path which MockBukkit does not bridge to the nextTitle() queue, so TitleDisplayFeatureTest always saw null. TitleCompat.sendTitle now uses the deprecated-but-universal sendTitle(String, String, int, int, int) with @SuppressWarnings. TitleCompat.clearTitle still prefers clearTitle() over resetTitle(). TitleValidator checks sendTitle first, showTitle as secondary fallback.
getBukkitVersion() for MC 26.x returns "26.1-R0.1-SNAPSHOT" rather
than "1.26.1-R0.1-SNAPSHOT". The old parseMinor() split by "." and
took parts[1] ("1-R0" -> 1), triggering the >= 1.18 guard and
disabling the plugin.
ServerVersionUtil.parseFrom(String) now detects legacy "1.X.Y" vs
new "X.Y" format. For the new format it returns parts[0] as the
effective minor (26 >= 18, so the startup check passes). A
versionDisplay() method exposes the full "1.21" / "26.1" string
used in the startup log line.
Add ServerVersionUtilParseTest covering both formats, bare major,
and garbage input. CI smoke test matrix already covers mc-prefix
"26.1".
Paper/Folia/Spigot builds for MC 26.x are not yet published on the APIs, so every 26.1 matrix cell silently skips with exit 0 — giving false confidence without exercising anything. Remove it for now. Version parsing for the new X.Y format is already covered by ServerVersionUtilParseTest. Re-add 26.1 once real server builds are available on api.papermc.io.
…uilds Mark mc-prefix 26.1 matrix entries with experimental: true so the jobs use continue-on-error: true — unavailable versions show as a visible (orange) warning in CI without blocking the PR. Change the 'no builds found' exit from 0 to 1 so missing MC versions fail the job instead of silently passing. BuildTools failure and missing Spigot JAR likewise now exit 1. When Paper/Folia/Spigot 26.1 builds become available the smoke tests will automatically exercise the plugin; at that point flip experimental to false to make them strict.
BuildTools requires network access, Git, and exact version support — it fails for reasons unrelated to the plugin. Reverting exit 1 to exit 0 with ::warning:: so a BuildTools failure or missing JAR is a visible skip, not a PR blocker. Only actual plugin errors in the server log (SEVERE.*EzCountdown etc.) remain as hard exit 1 failures.
Confirmed: Paper and Folia top out at 1.21.11. The 26.x version format is covered by ServerVersionUtilParseTest unit tests. Re-add 26.1 to the matrix once official builds are published.
- Add '26.1' to mc-prefix matrix in smoke-papermc job
- Exclude java: 21 + mc-prefix: 26.1 (requires Java 25+)
- Migrate resolve step from api.papermc.io/v2 to fill.papermc.io/v3
- v3 returns versions as {family: [version, ...]} dict
- Build objects include direct download URL (fill-data.papermc.io)
- Prefer STABLE channel, fall back to latest build
- Download step now uses direct URL from resolve step output
…tion Multi-line Python inside python3 -c "..." was starting at column 0, which caused the YAML block scalar to terminate prematurely, breaking the entire workflow file and preventing any jobs from running.
actions/checkout@v6 and actions/setup-java@v5 do not exist; downgrade to the latest actual versions (v4).
…pload-artifact@v7)
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.
Added
folia-supported: trueinplugin.yml). Folia'sGlobalRegionScheduleris used automatically when detected at runtime; Paper/Spigot continue to use the Bukkit scheduler.compat/package hierarchy - clean OOP abstraction layer:compat.platform.PlatformDetector- detects Folia vs. Paper/Spigot at startup viaRegionizedServerclass presence.compat.scheduler.SchedulerAdapter/TaskHandle- platform-agnostic scheduler interface (runTask,runTaskTimer,runTaskLater,runTaskAsync).compat.scheduler.BukkitSchedulerAdapter-SchedulerAdapterbacked byBukkitScheduler(Paper/Spigot).compat.scheduler.FoliaSchedulerAdapter-SchedulerAdapterbacked byGlobalRegionScheduler(Folia); only class-loaded when Folia is detected.compat.scheduler.SchedulerAdapterFactory- chooses the correct adapter with graceful fallback if Folia classes are missing.compat.version.ServerVersionUtil- canonical location for runtime Minecraft version detection (replacesutil.ServerVersionUtil).compat.material.MaterialCompat- canonical location for cross-version material resolution (replacesutil.MaterialCompat).PluginBootstrapnow logs the active scheduler adapter class on enable (e.g.Scheduler: BukkitSchedulerAdapter).Changed
util.ServerVersionUtilandutil.MaterialCompatare now@Deprecateddelegation stubs that forward to their canonicalcompat.*counterparts; they will be removed in a future release.All internal scheduler usages (
CountdownManager,FireworkShowManager,PatternScheduler,ChatInputListener, alllistener.actions.*GUI action classes,SpigotIntegration,SpigotUpdateChecker) now go throughSchedulerAdapterinstead ofBukkit.getScheduler()/BukkitRunnabledirectly.Scoreboard API modernised -
ScoreboardDisplaynow delegates tocompat.scoreboard.ScoreboardCompat. On Paper 1.20.3+ (Criteria.DUMMYavailable) the modernregisterNewObjective(String, Criteria, Component)overload is used; older builds fall back to the legacy string overload. The deprecatedScoreboard.resetScores(String)calls are replaced by objective unregister/re-register viaScoreboardCompat.resetObjective.Title API modernised -
TitleDisplaynow delegates tocompat.title.TitleCompat. On Paper 1.18+ the AdventurePlayer.showTitle(Title)/Player.clearTitle()APIs are preferred over the deprecatedsendTitle(String...)/resetTitle().TitleValidatornow also acceptsshowTitleas a valid title capability. A Spigot/legacy string fallback is retained.Per-player notification targeting -
NotificationBuilder.players(Collection<Player>)restricts a notification to specific players.EzCountdownApi.sendNotification(Notification, Collection<Player>)provides an inline alternative without building aNotificationfirst.Countdown.isVisibleTo(Player)- centralises per-player visibility logic (permission gate + target-player set) in one method; all display handlers now use it instead of duplicated inline checks.CountdownBuilder.targetPlayers(Collection<Player>)- restrict a persistent countdown's display to specific players.Developer-friendly exception hierarchy - new
com.skyblockexp.ezcountdown.api.exceptionpackage:EzCountdownException- base unchecked exception; catch this for all EzCountdown API errors.CountdownNotFoundException- thrown when referencing a countdown name that does not exist; carriesgetCountdownName().DuplicateCountdownException- thrown when creating a countdown whose name already exists; carriesgetCountdownName().InvalidConfigurationException- thrown byNotificationBuilder.build()and future builder validators when configuration is invalid; replaces the genericIllegalStateException.api-versionbumped to1.18inplugin.yml; minimum supported Minecraft version is Paper/Spigot 1.18. Dialog display continues to require Paper 1.21.7+.Broadened Java compatibility - release JARs now target Java 17 bytecode (previously Java 21), so the plugin runs on Paper 1.18 - 1.20.4 (Java 17) as well as Paper 1.20.5+ (Java 21). The
jdk21Maven profile also targets Java 17 bytecode.ServerVersionUtil- new utility class (com.skyblockexp.ezcountdown.util.ServerVersionUtil) for runtime Minecraft version detection; enables future conditional feature gating without hard API dependencies.Startup guard -
onEnablenow logs the detected MC and Java version and disables the plugin with a clear error message if the server is too old (MC < 1.18 or Java < 17).Changed
ActionBarDisplay,TitleDisplay,ChatDisplay,BossBarDisplay,ScoreboardDisplay,DialogDisplay) usecountdown.isVisibleTo(player)instead of duplicated inline permission checks.NotificationBuilder.build()now throwsInvalidConfigurationException(a subclass ofEzCountdownException) instead of a plainIllegalStateException.ScoreboardDisplaycatch blocks now includeNoSuchMethodErrorso the scoreboard falls back to chat if the String-criteriaregisterNewObjectiveoverload is ever removed in a future Paper build.1.4.3to2.0.0.Fixed
/countdown reload-resumeRunningCountdowns()previously calledhandler.onStart(), which always setstargetInstanttonow + fullDuration, discarding thetarget_epochsaved in storage. It now callshandler.ensureTarget()instead, which is a no-op when a target is already present. The same guard was added to the legacy fallback path for handler-less countdown types. End-commands that fired once before a reload will no longer fire again unexpectedly due to the countdown silently restarting.