Skip to content

Fix SSC login deadlock when players are crowd controlled before auth#3218

Open
Xekep wants to merge 2 commits intoPryaxis:general-develfrom
TerraZ-Team:pr/micro-fix-ssc-login-cc-lock
Open

Fix SSC login deadlock when players are crowd controlled before auth#3218
Xekep wants to merge 2 commits intoPryaxis:general-develfrom
TerraZ-Team:pr/micro-fix-ssc-login-cc-lock

Conversation

@Xekep
Copy link
Contributor

@Xekep Xekep commented Feb 27, 2026

Summary

  • allow /login while CCed only when player is in SSC pre-login disabled state (IsDisabledForSSC)
  • prevents login deadlock where server-applied webbed state blocks authentication

Scope

  • focused change in Commands.AttemptLogin only
  • no unrelated file changes

@hakusaro
Copy link
Member

@greptile review?

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 27, 2026

Greptile Summary

This PR fixes a deadlock where players cannot authenticate when server-applied crowd control (Webbed buff) from SSC/RequireLogin auth gates blocks the /login command.

Key Changes:

  • Modified AttemptLogin to allow login while CCed if player is in pre-auth disabled state
  • Checks both IsDisabledForSSC (SSC mode) and RequireLogin config setting
  • Maintains existing CC restrictions for legitimately crowd-controlled players

How It Works:
When SSC or RequireLogin is enabled, unauthenticated players are continuously disabled via Disable() which applies the Webbed buff. The original code rejected login attempts while CCed, creating a deadlock. The fix detects when CC is from auth gates and allows login to proceed, breaking the cycle.

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk
  • The logic correctly addresses a critical authentication deadlock without introducing new issues. The change is focused, well-commented, and follows existing code patterns. Edge cases are acceptable trade-offs.
  • No files require special attention

Important Files Changed

Filename Overview
TShockAPI/Commands.cs Adds logic to allow login when CCed by auth gates (SSC/RequireLogin), preventing deadlock

Last reviewed commit: caea4e7

@hakusaro
Copy link
Member

@greptile i have my doubts as to whether or not this is reachable in practice?

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses an SSC authentication deadlock where the server’s pre-login “disabled” state can apply crowd control (e.g., Webbed), preventing /login and leaving players unable to authenticate.

Changes:

  • Adds a pre-login “auth gate” condition to allow /login while CCed in certain disabled states.
  • Updates the CCed login guard to exempt players disabled by SSC (and currently also RequireLogin).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +851 to +853
var disabledForAuthGate = args.Player.IsDisabledForSSC
|| (!args.Player.IsLoggedIn && TShock.Config.Settings.RequireLogin);
if (args.TPlayer.CCed && Main.ServerSideCharacter && !disabledForAuthGate)
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description says /login should be allowed while CCed only for the SSC pre-login disabled state (IsDisabledForSSC), but disabledForAuthGate also treats RequireLogin as an auth-gate condition. If the intent is strictly SSC-only, drop the RequireLogin clause; if RequireLogin is also intended here, please update the PR description to match (and clarify why this remains gated behind Main.ServerSideCharacter).

Copilot uses AI. Check for mistakes.
// Pre-login auth gates can disable movement (SSC/RequireLogin), which may mark the player as CCed.
// Allow login in that temporary state to avoid an auth deadlock.
var disabledForAuthGate = args.Player.IsDisabledForSSC
|| (!args.Player.IsLoggedIn && TShock.Config.Settings.RequireLogin);
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

disabledForAuthGate includes !args.Player.IsLoggedIn, but this method already returns early when IsLoggedIn is true. Removing the redundant check would make the intent clearer and avoid implying that disabledForAuthGate could ever be evaluated in a logged-in state.

Suggested change
|| (!args.Player.IsLoggedIn && TShock.Config.Settings.RequireLogin);
|| TShock.Config.Settings.RequireLogin;

Copilot uses AI. Check for mistakes.
// Pre-login auth gates can disable movement (SSC/RequireLogin), which may mark the player as CCed.
// Allow login in that temporary state to avoid an auth deadlock.
var disabledForAuthGate = args.Player.IsDisabledForSSC
|| (!args.Player.IsLoggedIn && TShock.Config.Settings.RequireLogin);
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change allows /login to proceed while args.TPlayer.CCed when disabledForAuthGate is true, but the login flow still calls PlayerData.RestoreCharacter(...) (when SSC is enabled) which sends a SyncLoadout packet. Earlier in this method you note CC prevents loadout switching and can cause catastrophic desync; if the player is CCed due to the server-applied Webbed disable buff, the client may still reject the loadout sync even though login is now permitted. Consider explicitly clearing the server-applied disable CC (e.g., Webbed) before restoring/syncing character data, or otherwise ensuring the client is not CCed at the point the loadout index is synced.

Suggested change
|| (!args.Player.IsLoggedIn && TShock.Config.Settings.RequireLogin);
|| (!args.Player.IsLoggedIn && TShock.Config.Settings.RequireLogin);
// If the player is only CCed because of a server-side auth gate (e.g., Webbed to disable movement
// before login), clear that CC before we proceed into SSC restore/loadout sync. Otherwise the client
// may reject the SyncLoadout packet while still CCed, causing desync.
if (disabledForAuthGate && args.TPlayer.CCed)
{
for (int i = 0; i < args.TPlayer.buffType.Length; i++)
{
if (args.TPlayer.buffType[i] == Terraria.ID.BuffID.Webbed)
{
args.TPlayer.DelBuff(i);
i--;
}
}
// Ensure the auth-gate CC flag is cleared on the server-side Player instance.
args.TPlayer.webbed = false;
}

Copilot uses AI. Check for mistakes.
@Xekep
Copy link
Contributor Author

Xekep commented Feb 27, 2026

@greptile i have my doubts as to whether or not this is reachable in practice?

This is reachable in practice; I reproduced it on a survival server with SSC enabled.

Steps:

  1. Join without being logged in.
  2. Player is SSC-disabled and gets Webbed (CC).
  3. Run /login <password>.

Before this fix, login is rejected with “You cannot login whilst crowd controlled.”, causing an auth lock loop.
The fix only bypasses this check when CC comes from SSC disable (IsDisabledForSSC), so normal CC behavior remains unchanged.

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 27, 2026

Thanks for the clear reproduction steps. The scenario makes sense - SSC disable applies Webbed status, which then blocks /login, creating the deadlock.

The fix is appropriately scoped since it only bypasses the CC check when IsDisabledForSSC is true. This means:

  • Players who are legitimately CCed during normal gameplay still can't login (correct behavior)
  • Only SSC-disabled players can login through the server-applied Webbed state (fixes the deadlock)

Good catch and clean solution.

@hakusaro
Copy link
Member

hakusaro commented Mar 5, 2026

I think we've effectively fixed the hole causing this, can you check if this patch is still necessary?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants