Skip to content

v0.5.0

Choose a tag to compare

@aaldersondev aaldersondev released this 07 Aug 13:30
· 7 commits to main since this release

A server that reads no standard input can now be stopped cleanly, and talked to.

v0.3.1 said this was coming and why it could not come then:

RCON as a stop transport — for games that do not read stdin — needs a change to the stop contract and comes separately.

Rust, ARK, Palworld and most Source servers read nothing from standard input. Until now the only clean stop Hopper had was a string written to a pipe nobody holds, and the alternative was a signal — which for a game that writes its save on shutdown is a save that does not get written.

Stopping over RCON

A template declares the command, which port to use, and the name of the variable holding the password — never the password, which the daemon resolves against the server's environment at the moment it connects.

Delivery is what counts, not an answer. That distinction is the whole feature. A server that has just executed quit closes its socket or says nothing at all, and reading that as "the command never arrived" would have Hopper refuse a stop it had already delivered — then never wait for the exit, never arm the timeout, while the game went down regardless. Restart would not restart, and a reinstall would mark a running server as failed. So the stop settles when the bytes leave, after a successful authentication. The readiness check keeps waiting for a real answer, because a server that hangs up has proved nothing about being ready.

The console takes the same rule. A command that runs and answers nothing was being reported as one that never arrived — which would have a scheduled task record a failure for work the server did, and an operator run it twice.

What is still refused, all of it before the command leaves: a port name that matches nothing, an unset password variable, a refused password, a connection that never opens. A refusal leaves the server exactly as it was — the game has been told nothing, and killing it would lose the session the refusal exists to protect.

A stop is allowed to take its time

stopTimeoutSeconds existed with a default of 30 that no template could raise, so every server inherited a figure sized for a Bukkit shutdown — and a world that takes longer than that to serialise was killed mid-write. A template declares it now. Factorio asks for 240.

Transfers follow that figure too, instead of giving up after a hardcoded two minutes — thirty seconds before a large world would have finished saving.

Refusals are visible

A refused stop used to be a console line at four in the morning and nothing else: the scheduled task recorded no failure and the server list still said the server was running. It now reaches the panel, lands in the Activity tab, and says it was refused rather than reporting the stop that never happened.

Upgrading

From the panel: Settings → Update now. Nothing changes for an existing server. A template that declares none of this keeps its stop command, its 30 seconds, and sends a byte-identical configuration; the shipped catalogue is unchanged apart from Factorio's longer stop.

A node running an older daemon cannot honour an RCON stop, and the panel refuses to save one for it rather than letting the daemon fall back to a signal without saying so.

Not yet

Palworld is the proof this was built for: anonymous Steam install, no standard input at all, RCON on its own port, and a save that a signal does not write. It needs an install pipeline that can survive downloading tens of gigabytes, which comes separately.