public override void OnListPlayers(List<CPlayerInfo> players, CPlayerSubset subset)
{
if (!fIsEnabled) return;
DebugWrite("^9^bGot OnListPlayers^n", 8);
try {
if (subset.Subset != CPlayerSubset.PlayerSubsetType.All) return;
lock (fListPlayersQ) {
fListPlayersTimestamp = DateTime.Now;
Monitor.Pulse(fListPlayersQ);
}
/*
Check if server crashed or Blaze dumped players or model invalid for too long.
Detected by: last recorded server uptime is greater than zero and less than new uptime,
or a player model timed out while still being on the all players list,
or got an OnLogin callback, which is used in connection initialization for Procon,
or the refresh command was used,
or the current list of players is more than CRASH_COUNT_HEURISTIC players less than the last
recorded count, or the last known player count is greater than the maximum server size
(adjusted for BF4 and BFH, to allow for 2 commanders above max player count),
or more than 3 minutes have elapsed since a move/reassign was started.
Since these detections are not completely reliable, do a minimal amount of recovery,
don't do a full reset
*/
int adjMaxSize = (fGameVersion == GameVersion.BF3) ? MaximumServerSize : (MaximumServerSize+2); // for commanders
int totalPlayers = TotalPlayerCount();
if (fServerCrashed
|| fGotLogin
|| fRefreshCommand
|| (fServerCrashed = (totalPlayers >= 16
&& totalPlayers > players.Count
&& (totalPlayers - players.Count) >= Math.Min(CRASH_COUNT_HEURISTIC, totalPlayers)))
|| totalPlayers > adjMaxSize
|| (fTimeOutOfJoint > 0 && GetTimeInRoundMinutes() - fTimeOutOfJoint > 3.0)) {
String revWhy = String.Empty;
if (fServerCrashed) revWhy += "Crash ";
if (fGotLogin) revWhy += "Login ";
if (fRefreshCommand) revWhy += "Refresh ";
if (totalPlayers > adjMaxSize) revWhy += "MaximumServerSize(" + totalPlayers + ">" + MaximumServerSize + ") ";
if (fTimeOutOfJoint > 0 && (GetTimeInRoundMinutes() - fTimeOutOfJoint) > 3.0) revWhy += "MoveTimeTooLong";
ValidateModel(players, revWhy);
fServerCrashed = false;
fGotLogin = false;
fRefreshCommand = false;
fTimeOutOfJoint = 0;
} else {
fUnassigned.Clear();
foreach (CPlayerInfo p in players) {
try {
int bf4Type = (fGameVersion != GameVersion.BF3) ? p.Type : ROLE_PLAYER;
UpdatePlayerModel(p.SoldierName, p.TeamID, p.SquadID, p.GUID, p.Score, p.Kills, p.Deaths, p.Rank, bf4Type);
} catch (Exception e) {
ConsoleException(e);
continue;
}
}
}
GarbageCollectKnownPlayers(); // also resets LastMoveTo
UpdateTeams();
fLastFastMoveTimestamp = DateTime.MinValue; // reset fast move gap timer
LogStatus(false, DebugLevel);
/* Special handling for JustEnabled state */
if (fPluginState == PluginState.JustEnabled) {
fPluginState = PluginState.Active;
fRoundStartTimestamp = DateTime.Now;
DebugWrite("^b^3State = " + fPluginState, 6);
}
// Use updated player list, one-time updates
if (fNeedPlayerListUpdate) {
try { AssignGroups(); } catch (Exception e) { ConsoleException(e); }
try { RememberTeams(); } catch (Exception e) { ConsoleException(e); }
fNeedPlayerListUpdate = false;
}
//CommandToLog("whitelist");
foreach (CPlayerInfo p in players) {
try {
PlayerModel player = GetPlayer(p.SoldierName);
if (player == null) continue;
String guid = (String.IsNullOrEmpty(player.EAGUID)) ? INVALID_NAME_TAG_GUID : player.EAGUID;
String xt = ExtractTag(player);
if (String.IsNullOrEmpty(xt)) xt = INVALID_NAME_TAG_GUID;
foreach (String item in fSettingWhitelist) {
List<String> tokens = new List<String>(Regex.Split(item, @"\s+"));
if (tokens.Count < 1) {
continue;
}
if (tokens[0] == player.Name || tokens[0] == xt || tokens[0] == guid) {
if (player.Whitelist == 0) {
DebugWrite("^8^bWARNING^n^0: (^b" + player.Name + ", " + xt + ", ^n" + guid + ") matches (" + String.Join(", ", tokens.ToArray()) + ") ^8^bBUT NO WHITELIST FLAGS SET!", 7);
}
}
}
} catch (Exception e) {
ConsoleException(e);
}
}
} catch (Exception e) {
ConsoleException(e);
}
}