Repository navigation
✨ feat(minestom): add server lifecycle, surf player and runtime plugin downloads - #448
Conversation
twisti-dev
commented
Oct 17, 2026
- enable features and plugins synchronously in surfMinestomServer, before the server accepts players; a failing enable fails the start and rolls back
- refuse a shutdown from the starting thread and fail the start when another thread requests one
- add SurfMinestomServer.stop(), which stops Minestom, the api and then the onShutdown actions once, lets concurrent callers wait and refuses tick threads
- add builder onShutdown actions and a JVM shutdown hook installed after a successful start
- set minestom.shutdown-on-signal=false in the bootstrap unless it is given with -D
- add SurfMinestomPlayer with the Adventure permission pointer, vanilla-like game mode switches, signed chat sessions in player list entries and shared viewable rules
- add builder playerFactory; ConnectionManagerMixin rejects other player providers while the api runs, and a provider set before the start fails it outside of tests
- add PlayerVisibility.isManaged and Provider.manages for the viewable rule of managed players
- add withPlugins { requireAll }, which also counts unreadable plugin descriptions, and create plugins/ before a plugin is constructed
- start the console reader on the first tick and stop the server from its default onShutdown
- add downloadSurfModules and the shaded configuration to the minestom-server Gradle plugin
- let SurfMixinAgent read the server jar reported by the bootstrap, so it works when surf-api modules are downloaded
- use stop() in the example server and log from an onShutdown action
- bump version to 3.49.0 and the Gradle plugin to 2.5.0
…n downloads
- enable features and plugins synchronously in surfMinestomServer, before the server accepts
players; a failing enable fails the start and rolls back
- refuse a shutdown from the starting thread and fail the start when another thread requests one
- add SurfMinestomServer.stop(), which stops Minestom, the api and then the onShutdown actions
once, lets concurrent callers wait and refuses tick threads
- add builder onShutdown actions and a JVM shutdown hook installed after a successful start
- set minestom.shutdown-on-signal=false in the bootstrap unless it is given with -D
- add SurfMinestomPlayer with the Adventure permission pointer, vanilla-like game mode switches,
signed chat sessions in player list entries and shared viewable rules
- add builder playerFactory; ConnectionManagerMixin rejects other player providers while the api
runs, and a provider set before the start fails it outside of tests
- add PlayerVisibility.isManaged and Provider.manages for the viewable rule of managed players
- add withPlugins { requireAll }, which also counts unreadable plugin descriptions, and create
plugins/<id> before a plugin is constructed
- start the console reader on the first tick and stop the server from its default onShutdown
- add downloadSurfModules and the shaded configuration to the minestom-server Gradle plugin
- let SurfMixinAgent read the server jar reported by the bootstrap, so it works when surf-api
modules are downloaded
- use stop() in the example server and log from an onShutdown action
- bump version to 3.49.0 and the Gradle plugin to 2.5.0
There was a problem hiding this comment.
Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.
An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 217ef7d820
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| for (action in builder.shutdownActions) { | ||
| try { | ||
| action() |
There was a problem hiding this comment.
Invoke shutdown actions for every Minestom stop
These callbacks run only when callers use SurfMinestomServer.stop(). If existing server code calls MinecraftServer.stopCleanly() directly, Minestom invokes the registered ::shutdown task and disables the API, but this loop is never reached, so documented shutdown work such as flushing databases is silently skipped. Register an idempotent action runner in the Minestom shutdown path as well.
Useful? React with 👍 / 👎.
| start() | ||
| } | ||
|
|
||
| SchedulerManager.scheduleNextTick(console::start) |
There was a problem hiding this comment.
Cancel the pending console start when disabling
If a later feature fails during synchronous enable, or the API is shut down before the first tick, teardown calls ConsoleFeature.disable() but leaves this scheduled task active. A subsequent retry followed by the first server tick starts the stale console alongside the new one, causing multiple threads to read the same terminal and allowing the stale shutdown handler to stop the replacement runtime. Retain the scheduled task and cancel it during disable, or guard the callback against a disabled feature.
Useful? React with 👍 / 👎.
|
|
||
| // Requested by another thread, which waits for the lock and then finds the api | ||
| // torn down | ||
| check(!runtime.shutdownRequested.get()) { "The surf api was shut down while it started" } |
There was a problem hiding this comment.
Close the shutdown-request race at startup completion
If another thread enters shutdown() immediately after this final flag read but before surfMinestomServer returns, it sets shutdownRequested, waits for the lifecycle lock, and tears the runtime down; the starting thread never observes that request and returns normally with an already-disabled API. This contradicts the documented guarantee that a shutdown requested while startup is in progress fails the start, so the transition to the started state and the request check need to be linearized with shutdown().
Useful? React with 👍 / 👎.
| ) | ||
| } | ||
|
|
||
| Runtime.getRuntime().addShutdownHook(Thread(::stop, "surf-minestom-shutdown")) |
There was a problem hiding this comment.
Avoid retaining one shutdown hook per restarted runtime
In production, shutdown() clears current and permits a new runtime to start, but this hook is never removed or shared. After such a restart, JVM shutdown launches both hooks concurrently; their independent stopping flags allow both runtimes to call MinecraftServer.stopCleanly() at the same time, recreating the concurrent-stop condition warned about above and also retaining every old runtime and its shutdown actions until process exit. Use one process-wide hook or unregister the old runtime's hook when it is replaced.
Useful? React with 👍 / 👎.