Пример #1
0
        public void RemovePlayersSafe()
        {
            object _lock = new object();

            lock (_lock)
            {
                RemovePlayers.ForEach(o => Game.Players.Remove(o));
                RemovePlayers.Clear();
            }
        }
Пример #2
0
        public void Update(ServerState newState, Connection connection)
        {
            lock (ServerStateLock)
            {
                if (Status != newState.Status)
                {
                    connection.RecordMatchResults(this);
                }
                if (connection.ServerHookEnabled && Teams != newState.Teams)
                {
                    Scoreboard.RegenerateScoreboardImage = true;
                }

                Name                   = newState.Name;
                Port                   = newState.Port;
                HostPlayer             = newState.HostPlayer;
                SprintEnabled          = newState.SprintEnabled;
                SprintUnlimitedEnabled = newState.SprintUnlimitedEnabled;
                DualWielding           = newState.DualWielding;
                AssassinationEnabled   = newState.AssassinationEnabled;
                VotingEnabled          = newState.VotingEnabled;
                Teams                  = newState.Teams;
                Map              = newState.Map;
                MapFile          = newState.MapFile;
                Variant          = newState.Variant;
                VariantType      = newState.VariantType;
                NumPlayers       = newState.NumPlayers;
                MaxPlayers       = newState.MaxPlayers;
                TeamScores       = newState.TeamScores;
                Passworded       = newState.Passworded;
                Xnkid            = newState.Xnkid;
                Xnaddr           = newState.Xnaddr;
                IsDedicated      = newState.IsDedicated;
                GameVersion      = newState.GameVersion;
                EldewritoVersion = newState.EldewritoVersion;

                PreviousStatus = Status;
                Status         = newState.Status;

                inLobby   = Status == "InLobby";
                isLoading = Status == "Loading";

                GameVariantType = GameVariant.GetBaseGameID(VariantType);
            }

            //string date = System.DateTime.Now.ToString("[MM-dd-yyyy HH:mm:ss] ");
            string date = $"[{DateTimeUTC()}] ";

            // Detect Match Start and End
            if (Status != PreviousStatus)
            {
                // Game Started
                if (Status == Connection.StatusStringInGame)
                {
                    connection.InvokeMatchBeganOrEnded(new Connection.MatchBeginEndArgs(true, connection));
                    //connection.OnMatchBeginOrEnd(this, new Connection.MatchBeginEndArgs(true, connection));
                    connection.PrintToConsole("Game Started: " + newState.Variant + " ON " + newState.Map);
                }
                // Game Ended
                else if (Status == Connection.StatusStringInLobby && PreviousStatus == Connection.StatusStringInGame)
                {
                    connection.InvokeMatchBeganOrEnded(new Connection.MatchBeginEndArgs(false, connection));
                    //connection.OnMatchBeginOrEnd(this, new Connection.MatchBeginEndArgs(false, connection));
                    connection.PrintToConsole("Game Ended");
                    PlayerStatsRecord match;
                    foreach (PlayerInfo player in Players)
                    {
                        match = App.PlayerStatsRecords.Value.Find(x => x.Uid == player.Uid);
                        if (match != null)
                        {
                            match.Kills += player.Kills; match.Deaths += player.Deaths;
                        }
                        else
                        {
                            match = new PlayerStatsRecord(player);
                            if (match.IsValid)
                            {
                                App.PlayerStatsRecords.Value.Add(match);
                            }
                        }
                    }
                    App.PlayerStatsRecords.Save();
                }
            }

            // For each player in the new server state's player list
            foreach (PlayerInfo player in newState.Players)
            {
                if (player.Name.Length == 0)
                {
                    continue;
                }

                if (!Teams)
                {
                    player.Team = -1;
                }
                else if (Status == Connection.StatusStringInLobby)
                {
                    player.Team = -1;
                }
                else if (Status == Connection.StatusStringLoading)
                {
                    player.Team = -1;
                }

                // If the player list does not contain this player, this player has just joined the game
                PlayerInfo match = Players.Find(x => x.Uid == player.Uid);
                if (match == null)
                {
                    connection.PrintToPlayerLog(player.Name + " - " + player.ServiceTag + " : " + player.Uid + " has Joined.");
                    connection.OnPlayerJoined(new Connection.PlayerJoinLeaveEventArgs(player, true, newState.Players.Count, date, connection));
                    lock (ServerStateLock)
                    {
                        // add new player to the player list
                        Players.Add(player);
                    }
                }
            }

            // For each player in the player list
            foreach (PlayerInfo player in Players)
            {
                // If the new server state's player list does not contain this player, this player has just left the game
                //NOTE added '&& x.Name == player.Name', so if any bugs crop up check here
                PlayerInfo match = newState.Players.Find(x => x.Uid == player.Uid && x.Name == player.Name);
                if (match == null)
                {
                    connection.PrintToPlayerLog(player.Name + " - " + player.ServiceTag + " : " + player.Uid + " has Left.");
                    connection.OnPlayerLeft(new Connection.PlayerJoinLeaveEventArgs(player, false, newState.Players.Count, date, connection));
                    // Mark player for removal from players list
                    RemovePlayers.Add(player);
                }
                else
                {
                    if (player.Team != match.Team && player.Team != -1 && match.Team != -1)
                    {
                        // Player has switched teams
                        connection.OnPlayerTeamChanged(this, new Connection.PlayerTeamChangeEventArgs(match, player, connection));
                    }
                    lock (ServerStateLock)
                    {
                        // Update the player's stats
                        player.Update(match);
                    }
                }
            }

            lock (ServerStateLock)
            {
                // Remove players that left from the player list
                foreach (PlayerInfo removePlayer in RemovePlayers)
                {
                    Players.Remove(removePlayer);
                }
                RemovePlayers.Clear();


                // Sort by team and then by score
                List <IGrouping <int, PlayerInfo> > teams = Players.GroupBy(x => x.Team).OrderBy(x => x.Key).ToList();
                Players.Clear();
                foreach (IGrouping <int, PlayerInfo> team in teams)
                {
                    Players.AddRange(team.OrderByDescending(x => x.Score));
                }

                OrderedTeamScores.Clear();
                OrderedTeams.Clear();
                RankedPlayers.Clear();

                // Sort team scores for scoreboard display
                if (Teams)
                {
                    OrderedTeamScores = TeamScores.Select(
                        (x, i) =>
                        (Players.Any(p => p.Team == i))
                                ? new Tuple <int, int>(i, x)
                                : new Tuple <int, int>(-1, x)
                        )                                                          // Mark all empty teams with -1
                                        .Where(x => x.Item1 > -1)                  // Grab all non-empty teams
                                        .OrderByDescending(x => x.Item2).ToList(); // Order teams by score (descending)

                    connection.PopulatedTeams = OrderedTeamScores?.Count ?? 1;

                    for (int i = 0; i < OrderedTeamScores.Count; i++)
                    {
                        OrderedTeams.Add(
                            new Tuple <Tuple <int, int>, List <PlayerInfo> >(
                                OrderedTeamScores[i],
                                Players.Where(x => x.Team == OrderedTeamScores[i].Item1).ToList()
                                )
                            );
                    }
                }
            }
        }