/// <summary> /// Read all process files /// Check if any characters have changed /// </summary> private void PerformReadProcessFiles() { foreach (var gameSession in _map.GetAllGameSessions()) { string heartbeatFile = gameSession.ProcessStatusFilepath; if (string.IsNullOrEmpty(heartbeatFile)) { // This occurs when launching game session continue; } var response = SteelFilter.LaunchControl.GetHeartbeatStatus(heartbeatFile); if (!response.IsValid) { Logger.WriteError(string.Format("Invalid contents in heartbeat file: {0}", heartbeatFile)); continue; } var status = GetStatusFromHeartbeatFileTime(gameSession); if (!response.Status.IsOnline) { int gameInteractionTimeoutSeconds = ConfigSettings.GetConfigInt("GameInteractionTimeoutSeconds", 10); // SteelFilter reports !IsOnline if server dispatch quits firing // but that isn't reliable, as it doesn't fire when not logged in to a character if (response.Status.LastServerDispatchSecondsAgo > gameInteractionTimeoutSeconds) { status = ServerAccountStatusEnum.None; Logger.WriteInfo("Killing offline/character screen game"); } } else { _lastOnlineTimeUtc = DateTime.UtcNow; } if (status == ServerAccountStatusEnum.None) { Process p = TryGetProcessFromId(response.Status.ProcessId); if (p != null) { p.Kill(); File.Delete(heartbeatFile); _map.RemoveGameSessionByProcessId(p.Id); Logger.WriteDebug("Killing process: " + p.Id.ToString()); OnGameDied(new EventArgs()); } } bool newGame = false; bool changedGame = false; bool changedStatus = false; if (gameSession.AccountName == null) { newGame = true; } else if (gameSession.AccountName != response.Status.AccountName || gameSession.ServerName != response.Status.ServerName) { // This doesn't make sense and shouldn't happen // Account & Server should be fixed for the life of a game session Logger.WriteError(string.Format("Account/Server change in heartbeat file!: {0}", heartbeatFile)); changedGame = true; } else if (gameSession.CharacterName != response.Status.CharacterName) { changedGame = true; } else if (gameSession.Status != status) { changedStatus = true; gameSession.Status = status; } UpdateGameSessionFromHeartbeatStatus(gameSession, heartbeatFile, response); if (newGame) { NotifyGameChange(gameSession, GameChangeType.StartGame); } else if (changedGame) { NotifyGameChange(gameSession, GameChangeType.ChangeGame); } else if (changedStatus) { NotifyGameChange(gameSession, GameChangeType.ChangeStatus); } } _lastReadProcesFilesUtc = DateTime.UtcNow; }