private async Task UpdatePlayerDetailsAsync(CancellationToken token)
        {
            if (!string.IsNullOrWhiteSpace(rconParams.InstallDirectory))
            {
                var           savedPath          = ServerProfile.GetProfileSavePath(rconParams.InstallDirectory, rconParams.AltSaveDirectoryName, rconParams.PGM_Enabled, rconParams.PGM_Name);
                DataContainer dataContainer      = null;
                DateTime      lastSteamUpdateUtc = DateTime.MinValue;

                try
                {
                    DataFileDetails.PlayerFileFolder = savedPath;
                    DataFileDetails.TribeFileFolder  = savedPath;
                    // load the player data from the files.
                    dataContainer = await DataContainer.CreateAsync();
                }
                catch (Exception ex)
                {
                    errorLogger.Error($"{nameof(UpdatePlayerDetailsAsync)} - Error: CreateAsync. {ex.Message}\r\n{ex.StackTrace}");
                    return;
                }

                token.ThrowIfCancellationRequested();
                await Task.Run(() =>
                {
                    // update the player data with the latest steam update value from the players collection
                    foreach (var playerData in dataContainer.Players)
                    {
                        if (!long.TryParse(playerData.SteamId, out long steamId))
                        {
                            continue;
                        }

                        this.players.TryGetValue(steamId, out PlayerInfo player);
                        player?.UpdateSteamData(playerData);
                    }
                }, token);

                try
                {
                    // load the player data from steam
                    lastSteamUpdateUtc = await dataContainer.LoadSteamAsync(SteamUtils.SteamWebApiKey, STEAM_UPDATE_INTERVAL);
                }
                catch (Exception ex)
                {
                    errorLogger.Error($"{nameof(UpdatePlayerDetailsAsync)} - Error: LoadSteamAsync. {ex.Message}\r\n{ex.StackTrace}");
                    return;
                }

                token.ThrowIfCancellationRequested();

                var totalPlayers = dataContainer.Players.Count;
                foreach (var playerData in dataContainer.Players)
                {
                    token.ThrowIfCancellationRequested();
                    await Task.Run(async() =>
                    {
                        if (long.TryParse(playerData.SteamId, out long steamId))
                        {
                            var validPlayer = new PlayerInfo(this.debugLogger)
                            {
                                SteamId   = steamId,
                                SteamName = playerData.SteamName,
                                IsValid   = true,
                            };

                            this.players.AddOrUpdate(steamId, validPlayer, (k, v) => { v.SteamName = playerData.SteamName; v.IsValid = true; return(v); });
                        }
                        else
                        {
                            var filename = Path.GetFileNameWithoutExtension(playerData.Filename);
                            if (long.TryParse(filename, out steamId))
                            {
                                var invalidPlayer = new PlayerInfo(this.debugLogger)
                                {
                                    SteamId   = steamId,
                                    SteamName = "< corrupted profile >",
                                    IsValid   = false,
                                };

                                this.players.AddOrUpdate(steamId, invalidPlayer, (k, v) => { v.SteamName = "< corrupted profile >"; v.IsValid = false; return(v); });
                            }
                            else
                            {
                                debugLogger.Debug($"{nameof(UpdatePlayerDetailsAsync)} - Error: corrupted profile.\r\n{playerData.Filename}.");
                            }
                        }

                        if (this.players.TryGetValue(steamId, out PlayerInfo player) && player != null)
                        {
                            player.UpdateData(playerData, lastSteamUpdateUtc);

                            await TaskUtils.RunOnUIThreadAsync(() =>
                            {
                                player.IsAdmin       = rconParams?.Server?.Profile?.ServerFilesAdmins?.Any(u => u.SteamId.Equals(player.SteamId.ToString(), StringComparison.OrdinalIgnoreCase)) ?? false;
                                player.IsWhitelisted = rconParams?.Server?.Profile?.ServerFilesWhitelisted?.Any(u => u.SteamId.Equals(player.SteamId.ToString(), StringComparison.OrdinalIgnoreCase)) ?? false;

                                if (totalPlayers <= Config.Default.RCON_MaximumPlayerAvatars && Config.Default.RCON_ShowPlayerAvatars)
                                {
                                    player.UpdateAvatarImageAsync(savedPath).DoNotWait();
                                }
                            });
                        }
                    }, token);
                }

                token.ThrowIfCancellationRequested();

                // remove any players that do not have a player file.
                var droppedPlayers = this.players.Values.Where(p => dataContainer.Players.FirstOrDefault(pd => pd.SteamId == p.SteamId.ToString()) == null).ToArray();
                foreach (var droppedPlayer in droppedPlayers)
                {
                    players.TryRemove(droppedPlayer.SteamId, out PlayerInfo player);
                }
            }
        }
 public static async Task WriteFormatThreadSafeAsync(string format, params object[] args)
 {
     await TaskUtils.RunOnUIThreadAsync(() => Debug.WriteLine(format, args));
 }