private void ParseInfolog(string text, bool isCrash) { if (string.IsNullOrEmpty(text)) { Trace.TraceWarning("Infolog is empty"); return; } try { var hasError = false; var modName = battleResult.Mod; var mapName = battleResult.Map; var isCheating = false; int? score = null; int scoreFrame = 0; string gameId = null; string demoFileName = null; string missionVars = ""; foreach (var cycleline in text.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries)) { var line = cycleline; var gameframe = 0; if (line.StartsWith("[DedicatedServer]")) { line = line.Replace("[DedicatedServer] ", ""); } if (line.StartsWith("[")) { var idx = line.IndexOf("] "); if (idx > 0) { int.TryParse(line.Substring(1, idx - 1), out gameframe); if (idx >= 0) { line = line.Substring(idx + 2); } } } // FIXME: why are these even null in the first place? if (mapName == null && line.StartsWith("Using map")) { mapName = line.Substring(10).Trim(); } if (modName == null && line.StartsWith("Using game")) { modName = line.Substring(11).Trim(); } if (line.StartsWith("recording demo")) { demoFileName = Path.GetFileName(line.Substring(15).Trim()); // 91.0 } else if (line.StartsWith("[DedicatedServer] recording demo")) { demoFileName = Path.GetFileName(line.Substring(33).Trim()); // 95.0 and later } if (line.StartsWith("Using demofile")) { return; // do nothing if its demo } if (line.StartsWith("GameID: ") && gameId == null) { gameId = line.Substring(8).Trim(); } if (line.StartsWith("STATS:")) { statsData.Add(line.Substring(6)); } if (line.Contains("SCORE: ") && !isCheating && battleResult.IsMission) { var match = Regex.Match(line, "SCORE: ([^ ]+)"); if (match.Success) { // game score var data = match.Groups[1].Value; //Trace.TraceInformation("Score data (raw) : " + data); data = Encoding.ASCII.GetString(Convert.FromBase64String(match.Groups[1].Value)); //Trace.TraceInformation("Score data (decoded) : " + data); var parts = data.Split('/'); score = 0; if (parts.Length > 1) { score = Convert.ToInt32(parts[1]); gameframe = Convert.ToInt32(parts[0]); } else { score = Convert.ToInt32(data); } scoreFrame = gameframe; } } if (line.Contains("MISSIONVARS:") && battleResult.IsMission) { var match = Regex.Match(line, "MISSIONVARS: ([^ ]+)"); missionVars = match.Groups[1].Value.Trim(); Trace.TraceInformation(string.Format("Mission variables: {0} (original line: {1})", missionVars, line)); } // obsolete, hanlded by pm messages //if (line.StartsWith("STATS:")) statsData.Add(line.Substring(6)); if (line.StartsWith("Cheating!") || line.StartsWith("Cheating is enabled!")) { isCheating = true; } if (line.StartsWith("Error") || line.StartsWith("LuaRules") || line.StartsWith("Internal error") || line.StartsWith("LuaCOB") || (line.StartsWith("Failed to load") && !line.Contains("duplicate name"))) { hasError = true; } } if (score != null || !String.IsNullOrEmpty(missionVars)) { Trace.TraceInformation("Submitting score for mission " + modName); try { using (var service = new ContentService { Proxy = null }) { service.SubmitMissionScoreCompleted += (s, e) => { if (e.Error != null) { if (e.Error is WebException) { Trace.TraceWarning("Error sending score: {0}", e.Error); } else { Trace.TraceError("Error sending score: {0}", e.Error); } } }; service.SubmitMissionScoreAsync(lobbyUserName, Utils.HashLobbyPassword(lobbyPassword), modName, score ?? 0, scoreFrame / 30, missionVars); } } catch (Exception ex) { Trace.TraceError(string.Format("Error sending mission score: {0}", ex)); } } var modOk = GlobalConst.IsZkMod(modName); // submit main stats if (!isCheating && !isCrash && modOk && gameEndedOk) { if (isHosting) { var service = new SpringieService() { Proxy = null }; var mis = new ContentService() { Proxy = null }; try { battleResult.EngineBattleID = gameId; battleResult.ReplayName = demoFileName; // set victory team for all allied with currently alive foreach (var p in statsPlayers.Values.Where(x => !x.IsSpectator && x.LoseTime == null)) { foreach (var q in statsPlayers.Values.Where(x => !x.IsSpectator && x.AllyNumber == p.AllyNumber)) { q.IsVictoryTeam = true; } } if (StartContext != null) { var result = service.SubmitSpringBattleResult(StartContext, lobbyPassword, battleResult, Enumerable.ToArray(statsPlayers.Values), statsData.ToArray()); if (result != null) { foreach (var line in result.Split('\n')) { client.Say(TasClient.SayPlace.Battle, "", line, true); } } } } catch (Exception ex) { Trace.TraceError("Error sending game result: {0}", ex); } } if (statsData.Count > 1) { // must be more than 1 line - 1 is player list var statsService = new StatsCollector { Proxy = null }; try { statsService.SubmitGameEx(gameId, modName, mapName, statsData.ToArray()); } catch (Exception ex) { Trace.TraceError("Error sending game stats: {0}", ex); } } } } catch (Exception ex) { Trace.TraceError("Error processing spring log: {0}", ex); } }