internal void Leave(ClientSession session, MatchListingLeaveReason reason) { if (this._Clients.Remove(session)) { this.Leave0(session, reason); } }
internal void Leave0(ClientSession session, MatchListingLeaveReason reason) { session.LobbySession.MatchListing = null; //Concurrency complexity Interlocked.Decrement(ref this.UsersReady); //We can freely decrement this here without having issues while (true) { int spotsLeft = this._SpotsLeft; if (spotsLeft != MatchListing.SPOTS_LEFT_GAME_STARTED) //Match has not been started or it is in progress of starting { if (Interlocked.CompareExchange(ref this._SpotsLeft, spotsLeft + 1, spotsLeft) == spotsLeft) { break; //Match has not been started } } } foreach (ClientSession other in this._Clients.Values) { other.UntrackUserInRoom(this.Name, session.SocketId); } foreach (ClientSession other in this.LobbyClients.Values) { other.UntrackUserInRoom(this.Name, session.SocketId); } session.UntrackUsersInRoom(this.Name); if (reason == MatchListingLeaveReason.Kicked) { session.SendPacket(new UserLeaveRoomOutgoingMessage(this.Name, session.SocketId)); } if (Interlocked.CompareExchange(ref this._SpotsLeft, (int)this.MaxMembers, MatchListing.SPOTS_LEFT_DIED) != (int)this.MaxMembers) { uint currentHost = this._HostSocketId; if (currentHost == session.SocketId) //Time to pick new host { //TODO: How should we handle friends only? while (this._Clients.Count > 0) { ClientSession other = this._Clients.Values.FirstOrDefault(); if (other != null) { if (InterlockedExtansions.CompareExchange(ref this._HostSocketId, other.SocketId, currentHost) == currentHost) { if (this._Clients.Contains(other)) { other.SendPacket(new MatchOwnerOutgoingMessage(this.Name, true, true, true)); break; } else { currentHost = other.SocketId; } } else { break; } } else { break; } } } } else { foreach (ClientSession other in this.LobbyClients.Values) { other.LobbySession.RemoveMatch(this); } PlatformRacing3Server.MatchListingManager.Die(this); } }