internal bool Join(ClientSession session)
    {
        session.Connection.OnDisconnected -= this.OnCreatorDisconnectEarly;

        MatchListingJoinStatus canJoinStatus = this.CanJoin(session);

        if (canJoinStatus != MatchListingJoinStatus.Success)
        {
            return(false);
        }

        if (!this._Clients.TryAdd(session))
        {
            return(false);
        }

        session.LobbySession.MatchListing = this;
        session.LobbySession.RemoveMatch(this);

        //Send the other clients
        foreach (ClientSession other in this._Clients.Sessions.OrderBy((c) => c == session))
        {
            session.TrackUserInRoom(this.Name, other.SocketId, other.UserData.Id, other.UserData.Username, other.GetVars("userName", "rank", "hat", "head", "body", "feet", "hatColor", "headColor", "bodyColor", "feetColor", "socketID", "ping"));
            other.TrackUserInRoom(this.Name, session.SocketId, session.UserData.Id, session.UserData.Username, session.GetVars("userName", "rank", "hat", "head", "body", "feet", "hatColor", "headColor", "bodyColor", "feetColor", "socketID", "ping"));
        }

        foreach (ClientSession other in this.LobbyClients.Sessions)
        {
            other.TrackUserInRoom(this.Name, session.SocketId, session.UserData.Id, session.UserData.Username, session.GetVars("userName", "rank", "hat", "head", "body", "feet", "hatColor", "headColor", "bodyColor", "feetColor", "socketID", "ping"));
        }

        uint currentHost = this._HostSocketId;

        if (this.Type == MatchListingType.Normal && (currentHost == session.SocketId || (currentHost == 0 && Interlocked.CompareExchange(ref this._HostSocketId, session.SocketId, currentHost) == currentHost)))
        {
            session.SendPacket(new MatchOwnerOutgoingMessage(this.Name, true, true, true));
        }
        else if (!session.IsGuest)
        {
            bool play = session.HasPermissions(Permissions.ACCESS_FORCE_START_ANY_MATCH_LISTING);
            bool kick = session.HasPermissions(Permissions.ACCESS_KICK_ANY_MATCH_LISTING);
            bool ban  = session.HasPermissions(Permissions.ACCESS_BAN_ANY_MATCH_LISTING);

            if (play || kick || ban)
            {
                session.SendPacket(new MatchOwnerOutgoingMessage(this.Name, play, kick, ban));
            }
        }

        this.TryStartFull();

        return(true);
    }
示例#2
0
        internal MatchListing Join(ClientSession session, string roomName, out MatchListingJoinStatus status)
        {
            status = MatchListingJoinStatus.Failed;

            if (this.MatchListings.TryGetValue(roomName, out MatchListing matchListing))
            {
                if (session.LobbySession.MatchListing == null)
                {
                    status = matchListing.Join(session);
                    if (status == MatchListingJoinStatus.Success)
                    {
                        return(matchListing);
                    }
                }
                else if (session.LobbySession.MatchListing == matchListing)
                {
                    status = MatchListingJoinStatus.Success;

                    return(matchListing);
                }
            }

            return(null);
        }
示例#3
0
        internal MatchListingJoinStatus Join(ClientSession session)
        {
            if (!this._Clients.Contains(session))
            {
                MatchListingJoinStatus canJoinStatus = this.CanJoin(session);
                if (canJoinStatus != MatchListingJoinStatus.Success)
                {
                    return canJoinStatus;
                }

                while (true) //Concurrency complexity
                {
                    int spotsLeft = this._SpotsLeft;
                    if (spotsLeft > 0)
                    {
                        if (Interlocked.CompareExchange(ref this._SpotsLeft, spotsLeft - 1, spotsLeft) == spotsLeft)
                        {
                            break;
                        }
                    }
                    else
                    {
                        //We are assuming if spotsLeft is int.MinValue it means the match has been started or is in progress of starting
                        return spotsLeft == MatchListing.SPOTS_LEFT_GAME_STARTED ? MatchListingJoinStatus.Started : MatchListingJoinStatus.Full;
                    }
                }

                if (this._Clients.Add(session))
                {
                    session.OnDisconnect -= this.OnCreatorDisconnectEarly;

                    session.LobbySession.MatchListing = this;
                    session.LobbySession.RemoveMatch(this);

                    //Send the other clients
                    foreach (ClientSession other in this._Clients.Values.OrderBy((c) => c == session))
                    {
                        session.TrackUserInRoom(this.Name, other.SocketId, other.UserData.Id, other.UserData.Username, other.GetVars("userName", "rank", "hat", "head", "body", "feet", "hatColor", "headColor", "bodyColor", "feetColor", "socketID", "ping"));
                        other.TrackUserInRoom(this.Name, session.SocketId, session.UserData.Id, session.UserData.Username, session.GetVars("userName", "rank", "hat", "head", "body", "feet", "hatColor", "headColor", "bodyColor", "feetColor", "socketID", "ping"));
                    }

                    foreach (ClientSession other in this.LobbyClients.Values)
                    {
                        other.TrackUserInRoom(this.Name, session.SocketId, session.UserData.Id, session.UserData.Username, session.GetVars("userName", "rank", "hat", "head", "body", "feet", "hatColor", "headColor", "bodyColor", "feetColor", "socketID", "ping"));
                    }

                    uint currentHost = this._HostSocketId;
                    if (currentHost == session.SocketId || (currentHost == 0 && InterlockedExtansions.CompareExchange(ref this._HostSocketId, session.SocketId, currentHost) == currentHost))
                    {
                        session.SendPacket(new MatchOwnerOutgoingMessage(this.Name, true, true, true));
                    }
                    else if (!session.IsGuest)
                    {
                        bool play = session.HasPermissions(Permissions.ACCESS_FORCE_START_ANY_MATCH_LISTING);
                        bool kick = session.HasPermissions(Permissions.ACCESS_KICK_ANY_MATCH_LISTING);
                        bool ban = session.HasPermissions(Permissions.ACCESS_BAN_ANY_MATCH_LISTING);

                        if (play || kick || ban)
                        {
                            session.SendPacket(new MatchOwnerOutgoingMessage(this.Name, play, kick, ban));
                        }
                    }

                    //Concurrency complexity
                    if (Interlocked.Increment(ref this.UsersReady) == this.MaxMembers) //Ensures that there is no race condition while the SpotsLeft check is passed and user is being added to the clients list and ensuring safe start
                    {
                        if (Interlocked.CompareExchange(ref this._SpotsLeft, MatchListing.SPOTS_LEFT_GAME_STARTED, 0) == 0) //If no spots are left set the value to int.MinValue and start the match, starting should be thread-safe
                        {
                            this.Start();
                        }
                    }

                    return MatchListingJoinStatus.Success;
                }
                else
                {
                    while (true) //Concurrency complexity
                    {
                        int spotsLeft = this._SpotsLeft;
                        if (spotsLeft >= 0)
                        {
                            if (Interlocked.CompareExchange(ref this._SpotsLeft, spotsLeft + 1, spotsLeft) == spotsLeft)
                            {
                                break;
                            }
                        }
                    }

                    return MatchListingJoinStatus.Success; //We are gonna assume its failed due to dublication?
                }
            }
            else
            {
                return MatchListingJoinStatus.Success;
            }
        }