Skip to content

fix(dialog): keep the pre-join dialog open when the timeout is 0 - #3164

Merged
Xephi merged 1 commit into
AuthMe:masterfrom
rishabhvenu:fix/dialog-timeout-zero
Oct 11, 2026
Merged

Xephi merged 1 commit into
AuthMe:masterfrom
rishabhvenu:fix/dialog-timeout-zero

Conversation

@rishabhvenu

Copy link
Copy Markdown
Contributor

loginTimeout: 0 and registerTimeout: 0 are documented as "Set to 0 to disable", and LimboPlayerTaskManager honours that for the post-join flow. The pre-join dialog does Math.max(timeout, 1) before completeOnTimeout, so 0 becomes one second: the dialog closes a second after it opens and the player is kicked with "Login timeout exceeded" (#3122). The clamp has been there since the dialog was added; I could not find a reason for it other than keeping completeOnTimeout from firing immediately.

With this change the timeout is only scheduled when the setting is positive. The server itself does not limit how long a client stays in the configuration phase as long as it answers keep-alives (the 30 second limit is in the login phase only), so the dialog can stay open. Two other places assumed the timeout always fires, and needed a change for that to be safe:

  • The handler blocks a "Configuration Thread" in join() until the dialog is answered. When the player disconnected, retireSession dropped the future without completing it, which was fine while the timeout woke the thread up a moment later. Without a timeout the thread stayed parked forever, so retireSession now completes the pending future.
  • PaperLoginValidationListener.getClaimTtlMillis() returns the timeout plus 60 seconds, so with 0 the name claim went stale 60 seconds into the dialog. A second connection with the same name then got its own dialog, and the first player was refused as "already online" once they answered. When either timeout is disabled the claim is now held for a day; it still ends as soon as the connection closes. I picked a day so the claim still cannot lock a name out forever. Happy to change the value or the approach.

One thing to be aware of: with the timeouts disabled, each waiting connection keeps one configuration thread until it answers or disconnects, and those connections do not count against max-players. That is what the setting asks for, but it is new for the pre-join phase.

Testing:

  • PaperDialogFlowListenerTest: the dialog is not ended after one second with a timeout of 0 (login and register), a timeout of 1 still kicks, and closing the connection completes its pending future. PaperLoginValidationListenerTest: the claim lifetime with a disabled timeout. The new assertions fail on master.
  • mvn -V -B clean package on JDK 21: build passes.
  • Paper 1.21.11 with a 1.21.11 protocol client that receives the dialog and answers it with custom_click_action, timeouts set to 0:
    • master: dialog closes after 1.0 s and the client is kicked with the timeout message, for both dialogs.
    • with the change: both dialogs stay open; submitting after 5 s registers / logs in. A client left in the login dialog for 139 s was still connected and logged in after submitting.
    • disconnecting with the dialog open: the thread dump shows no configuration thread left in PaperDialogFlowListener (one stayed parked when I only removed the clamp).
    • a second connection with the same name 70 s into the dialog is refused with "The same username is already playing on the server!" and the first one logs in (with only the clamp removed, the second got a dialog and the first was kicked).
  • With loginTimeout: 3 / registerTimeout: 3 the player is still kicked after 3 s.
  • Folia 1.21.11: same before/after for both dialogs and the disconnect case.

Not tested: a real client clicking the dialog (the test client speaks the protocol directly), proxy setups, email registration.

Fixes #3122

loginTimeout and registerTimeout are documented as "Set to 0 to disable"
and the post-join timeout task honours that. The pre-join dialog clamped
the value to at least one second instead, so with 0 the dialog closed
after one second and the player was kicked with the timeout message.

Only schedule the timeout when the setting is positive. Two things that
relied on the timeout always firing are adjusted for the unlimited wait:

- the configuration thread waiting for the answer is released when the
  connection closes, otherwise it would stay parked for good
- the pending name claim no longer expires 60 seconds into the dialog,
  which let a second connection take over the name and got the first
  one refused as already online once it answered

Fixes AuthMe#3122
@Xephi
Xephi merged commit 4520e29 into AuthMe:master Oct 11, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

"registerTimeout: 0" — breaks registration

2 participants