space-wizards / space-station-14

A multiplayer game about paranoia and chaos on a space station. Remake of the cult-classic Space Station 13.
https://spacestation14.io
MIT License
2.68k stars 3.37k forks source link

Lobby player count is not updated correctly when a player leaves #32926

Open youtissoum opened 1 week ago

youtissoum commented 1 week ago

Description

When a player leaves the server, the player count gets updated to the value from before the player disconnected.

Reproduction

  1. Start a server and two clients
  2. Join the server with both clients and go to the lobby
  3. Disconnect one of the clients
  4. Player count still shows 2 players online

Screenshots

https://github.com/user-attachments/assets/a18e24c1-a6c0-4073-8aa4-f1e99a2e0374

Additional context

benev0 commented 1 week ago

Further findings with more clients I was able to find that the lobby count does update on DC, but lags behind by one count.

benev0 commented 1 week ago

RT:SharedPlayerManager:PlayerStatusChanged is invoked before RT:SharedPlayerManager:RemoveSession is called

From RT-Server:PlayerManager:

/// <summary>
///     Ends a clients session, and disconnects them.
/// </summary>
internal void EndSession(NetUserId user)
{
    if (!TryGetSessionById(user, out var session))
        return;

    SetStatus(session, SessionStatus.Disconnected); // invokes PlayerStatusChanged
    SetAttachedEntity(session, null, out _, true);

    var viewSys = EntManager.System<ViewSubscriberSystem>();
    foreach (var eye in session.ViewSubscriptions.ToArray())
    {
        viewSys.RemoveViewSubscriber(eye, session);
    }

    RemoveSession(session.UserId); // session is removed causing change in variable used
    PlayerCountMetric.Set(PlayerCount); // not relevant
    Dirty();
}

PlayerStatusChanged is the event (CS) which formats and updates the serverInfo message by calling the function UpdateInfoText() which fires the networked event (RT) TickerLobbyInfoEvent to clients.

the content of server info (player count) is defined by InternalSessions which is altered by SharedPlayerManager:RemoveSession which as seen here is updated after the player count is used thus lagging the count by 1.