Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of LethalStats v1.0.1
LethalStats.dll
Decompiled a year agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Net.Http; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using System.Threading.Tasks; using BepInEx; using BepInEx.Bootstrap; using Coroner; using GameNetcodeStuff; using HarmonyLib; using LethalStats.Models; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("LethalStats")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyDescription("A mod that collects your stats so you can view them at https://splitstats.io")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+d78ce17398a6ea541ce02d5e69161d689d6c138e")] [assembly: AssemblyProduct("LethalStats")] [assembly: AssemblyTitle("LethalStats")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace LethalStats { public class PluginInfo { public const string PLUGIN_GUID = "com.danos.lethalstats"; public const string PLUGIN_NAME = "LethalStats"; public const string PLUGIN_VERSION = "1.0.1"; } [BepInPlugin("com.danos.lethalstats", "LethalStats", "1.0.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class LethalStats : BaseUnityPlugin { private readonly Harmony harmony = new Harmony("com.danos.lethalstats"); private static LethalStats Instance; private void Awake() { if ((Object)(object)Instance == (Object)null) { Instance = this; } harmony.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin LethalStats is loaded!"); ((BaseUnityPlugin)this).Logger.LogInfo((object)"LethalStats will upload stats when you see your post-game summary screen!"); } } public static class MyPluginInfo { public const string PLUGIN_GUID = "LethalStats"; public const string PLUGIN_NAME = "LethalStats"; public const string PLUGIN_VERSION = "1.0.0"; } } namespace LethalStats.Patches { [HarmonyPatch(typeof(DepositItemsDesk), "CheckAllPlayersSoldItemsServerRpc")] public class DepositItemsDeskPatch { private static bool Prefix(DepositItemsDesk __instance) { try { long num = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); if (DanosLastSent.unixTime > 0 && DanosLastSent.unixTime + 10 > num) { return true; } if ((Object)(object)__instance == (Object)null) { return true; } if (__instance.itemsOnCounter == null) { return true; } if (__instance.itemsOnCounter.Count == 0) { return true; } if ((Object)(object)GameNetworkManager.Instance == (Object)null || (Object)(object)GameNetworkManager.Instance.localPlayerController == (Object)null) { return true; } if ((Object)(object)StartOfRound.Instance == (Object)null) { return true; } StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance.localPlayerController == (Object)null) { return true; } ulong playerClientId = instance.localPlayerController.playerClientId; ulong playerSteamId = instance.localPlayerController.playerSteamId; ulong playerClientId2 = instance.allPlayerScripts[0].playerClientId; ulong playerSteamId2 = instance.allPlayerScripts[playerClientId2].playerSteamId; if (playerSteamId2 == 0) { return true; } Console.WriteLine($"[LethalStats] [DepositItemsDeskPatch]: Host Steam ID: {playerSteamId2}"); List<DanosGlobalContributions> list = new List<DanosGlobalContributions>(); foreach (GrabbableObject item2 in __instance.itemsOnCounter) { if (!((Object)(object)item2 == (Object)null) && !((Object)(object)item2.itemProperties == (Object)null) && item2.itemProperties.isScrap && !string.IsNullOrEmpty(item2.itemProperties.itemName)) { DanosGlobalContributions item = new DanosGlobalContributions { itemName = item2.itemProperties.itemName, scrapValueAverage = item2.scrapValue }; list.Add(item); } } list = (from x in list group x by x.itemName into x select new DanosGlobalContributions { itemName = x.Key, count = x.Count(), scrapValueAverage = (int)x.Average((DanosGlobalContributions y) => y.scrapValueAverage) }).ToList(); var anon = new { MySteamID = playerSteamId, HostSteamID = playerSteamId2, SoldAt = num, ItemsSold = list }; string content = JsonConvert.SerializeObject((object)anon); HttpClient httpClient = new HttpClient(); httpClient.BaseAddress = new Uri("https://lethalstatsservertasks.azurewebsites.net"); StringContent content2 = new StringContent(content, Encoding.UTF8, "application/json"); httpClient.PostAsync("/api/PostGlobalContribution", content2); DanosLastSent.unixTime = num; } catch (Exception ex) { Console.WriteLine("[LethalStats] [DepositItemsDeskPatch]: Error in Prefix: " + ex.Message); } try { Terminal terminal = TerminalPatches.Terminal; if ((Object)(object)terminal != (Object)null) { ((MonoBehaviour)terminal).StartCoroutine(TerminalPatches.GatherGlobalStatsCoroutine(terminal)); } } catch (Exception ex2) { Console.WriteLine("[LethalStats] [DepositItemsDeskPatch]: Error in updating global challenges: " + ex2.Message); } return true; } } public static class DanosLastSent { public static long unixTime { get; set; } } [HarmonyPatch(typeof(HUDManager))] [HarmonyPatch("FillEndGameStats")] internal class HUDManagerFillEndGameStatsPatch { public static string DebugPrefix = "[LethalStatsMod] [HUDManagerFillEndGameStatsPatch]: "; public static void ShowResult(bool successful) { try { Debug.Log((object)(DebugPrefix + "ShowResult called")); if ((Object)(object)GameNetworkManager.Instance.localPlayerController == (Object)null) { Debug.Log((object)(DebugPrefix + "localPlayerController is null")); return; } Debug.Log((object)(DebugPrefix + "localPlayerController is not null")); HUDManager instance = HUDManager.Instance; if ((Object)(object)instance == (Object)null) { Debug.Log((object)(DebugPrefix + "hudManager is null")); } else { ((MonoBehaviour)instance).StartCoroutine(ShowPostResultsCoroutine(successful, instance)); } } catch (Exception ex) { Debug.Log((object)(DebugPrefix + ex.Message)); } } public static void Prefix() { try { bool flag = true; StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance == (Object)null) { return; } if (DanosPlayerStats.HostSteamID == 0 || DanosPlayerStats.RoundID == null) { ulong playerClientId = instance.allPlayerScripts[0].playerClientId; ulong playerSteamId = instance.allPlayerScripts[playerClientId].playerSteamId; if (playerSteamId == 0) { return; } bool flag2 = playerSteamId != DanosPlayerStats.HostSteamID; DanosPlayerStats.HostSteamID = playerSteamId; if (flag2) { Debug.Log((object)(DebugPrefix + "Host changed, reset the values")); } else { Debug.Log((object)(DebugPrefix + "Host is the same, do nothing")); } DanosPlayerStats.RoundID = GenerateRoundID(instance); DanosPlayerStats.RoundInitialized = true; if (DanosPlayerStats.RoundStart == 0) { flag = false; } } UpdatePlayerStats(instance); UpdateTimeOfDayStats(); UpdateScrapOnShip(); UpdateRoundEnd(); UpdateCreditsAtEnd(); UpdateTotalScrap(instance); UpdateNetworkPlayerStats(instance); UpdateTeamStats(instance); UpdateFired(); if (!flag) { DanosPlayerStats.RoundStart = DanosPlayerStats.RoundEnd; } DanosPlayerStats.RoundID = GenerateRoundID(instance); Debug.Log((object)(DebugPrefix + "Posting results")); bool flag3 = DanosPlayerStats.PostResults(); Debug.Log((object)(DebugPrefix + $"ShowResult called {flag3}")); DanosPlayerStats.ResetValues(); } catch (Exception ex) { Debug.Log((object)ex.Message); } } private static string GenerateRoundID(StartOfRound instance) { try { ulong playerClientId = instance.allPlayerScripts[0].playerClientId; ulong playerSteamId = instance.allPlayerScripts[playerClientId].playerSteamId; if (playerSteamId == 0) { return null; } bool flag = playerSteamId != DanosPlayerStats.HostSteamID; DanosPlayerStats.HostSteamID = playerSteamId; if (flag) { Debug.Log((object)(DebugPrefix + "Host changed, reset the values")); } else { Debug.Log((object)(DebugPrefix + "Host is the same, do nothing")); } List<ulong> values = (from x in instance.allPlayerScripts select x.playerSteamId into x orderby x descending select x).ToList(); string text = string.Join(",", values); string roundString = playerSteamId + "," + text; return DanosPlayerStats.GetSHA256(roundString); } catch (Exception ex) { Debug.Log((object)(DebugPrefix + ex.Message)); return null; } } private static IEnumerator ShowPostResultsCoroutine(bool Success, HUDManager __instance) { yield return (object)new WaitForSeconds(22f); if (Success) { __instance.DisplayTip("Sent Stats!", "Stats successfully sent to SplitStats.io!", false, false, "LC_Tip1"); } else { __instance.DisplayTip("Stats not sent!", "Failed to send stats to SplitStats.io. Try again later.", true, false, "LC_Tip1"); } } private static void UpdateTeamStats(StartOfRound instance) { try { EndOfGameStats gameStats = instance.gameStats; if (gameStats == null) { return; } DanosPlayerStats.DaysOnTheJob = gameStats.daysSpent; DanosPlayerStats.TeamDeaths = gameStats.deaths; PlayerStats[] allPlayerStats = gameStats.allPlayerStats; if (allPlayerStats == null) { return; } PlayerStats[] array = allPlayerStats; foreach (PlayerStats val in array) { if (val.isActivePlayer) { DanosPlayerStats.TeamStepsTaken += val.stepsTaken; } } } catch (Exception ex) { Debug.Log((object)(DebugPrefix + ex.Message)); } } private static void UpdateFired() { try { TimeOfDay instance = TimeOfDay.Instance; if (!((Object)(object)instance == (Object)null)) { bool flag = (float)instance.daysUntilDeadline <= 0f; Debug.Log((object)(DebugPrefix + "TimeUntilDeadline: " + instance.daysUntilDeadline)); if (!flag) { DanosPlayerStats.Fired = false; } else if (DanosPlayerStats.QuotaStringA >= DanosPlayerStats.QuotaStringB) { DanosPlayerStats.Fired = false; } else { DanosPlayerStats.Fired = true; } } } catch (Exception ex) { Debug.Log((object)(DebugPrefix + ex.Message)); } } private static float CalculateLootValue() { try { GameObject val = GameObject.Find("/Environment/HangarShip"); List<GrabbableObject> source = (from obj in val.GetComponentsInChildren<GrabbableObject>() where ((Object)obj).name != "ClipboardManual" && ((Object)obj).name != "StickyNoteItem" select obj).ToList(); return source.Sum((GrabbableObject scrap) => scrap.scrapValue); } catch (Exception ex) { Debug.Log((object)(DebugPrefix + ex.Message)); return 0f; } } private static void UpdatePlayerStats(StartOfRound instance) { try { ulong playerClientId = instance.localPlayerController.playerClientId; PlayerStats val = instance.gameStats.allPlayerStats[playerClientId]; DanosPlayerStats.StepsTaken = val.stepsTaken; UpdatePlayerDeathStats(instance); } catch (Exception ex) { Debug.Log((object)(DebugPrefix + ex.Message)); } } private static void UpdatePlayerDeathStats(StartOfRound instance) { try { if (instance.localPlayerController.isPlayerDead) { AdvancedCauseOfDeath? causeOfDeath = API.GetCauseOfDeath(instance.localPlayerController); if (causeOfDeath.HasValue) { DanosPlayerStats.IncrementDeathCount(causeOfDeath); } } } catch (Exception ex) { Debug.Log((object)(DebugPrefix + ex.Message)); } } private static void UpdateTimeOfDayStats() { try { TimeOfDay instance = TimeOfDay.Instance; if ((Object)(object)instance != (Object)null) { DanosPlayerStats.QuotaStringA = instance.quotaFulfilled; DanosPlayerStats.QuotaStringB = instance.profitQuota; DanosPlayerStats.QuotaStringC = instance.timesFulfilledQuota; } } catch (Exception ex) { Debug.Log((object)(DebugPrefix + ex.Message)); } } private static void UpdateScrapOnShip() { try { DanosPlayerStats.ScrapOnShip = CalculateLootValue(); } catch (Exception ex) { Debug.Log((object)(DebugPrefix + ex.Message)); } } private static void UpdateRoundEnd() { try { DanosPlayerStats.RoundEnd = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); } catch (Exception ex) { Debug.Log((object)(DebugPrefix + ex.Message)); } } private static void UpdateCreditsAtEnd() { try { Terminal val = Object.FindObjectOfType<Terminal>(); if ((Object)(object)val != (Object)null) { DanosPlayerStats.CreditsAtEnd = val.groupCredits; } } catch (Exception ex) { Debug.Log((object)(DebugPrefix + ex.Message)); } } private static void UpdateTotalScrap(StartOfRound instance) { try { RoundManager instance2 = RoundManager.Instance; if ((Object)(object)instance2 != (Object)null) { DanosPlayerStats.TotalScrapOnMap = instance2.totalScrapValueInLevel; DanosPlayerStats.TotalScrapCollectedThisRound = instance2.scrapCollectedInLevel; } } catch (Exception ex) { Debug.Log((object)(DebugPrefix + ex.Message)); } } private static void UpdateNetworkPlayerStats(StartOfRound instance) { try { if ((Object)(object)GameNetworkManager.Instance == (Object)null || (Object)(object)GameNetworkManager.Instance.localPlayerController == (Object)null) { return; } ulong playerClientId = instance.localPlayerController.playerClientId; ulong playerSteamId = instance.localPlayerController.playerSteamId; string playerUsername = instance.localPlayerController.playerUsername; DanosPlayerStats.MySteamID = playerSteamId; DanosPlayerStats.MyUsername = playerUsername; if (instance.gameStats.allPlayerStats.Count() > (int)playerClientId) { PlayerStats val = instance.gameStats.allPlayerStats[playerClientId]; DanosPlayerStats.StepsTaken = val.stepsTaken; } try { List<PlayerControllerB> list = instance.allPlayerScripts.Where((PlayerControllerB x) => x.playerSteamId != 0).ToList(); DanosPlayerStats.PlayersInLobby = list.Count; DanosPlayerStats.PlayersDead = list.Count((PlayerControllerB x) => x.isPlayerDead); } catch (Exception ex) { Debug.Log((object)(DebugPrefix + ex.Message)); } } catch (Exception ex2) { Debug.Log((object)(DebugPrefix + ex2.Message)); } } } [HarmonyPatch(typeof(PlayerControllerB), "SetItemInElevator")] public class SetItemInElevator_Prefix { private static bool Prefix(PlayerControllerB __instance, bool droppedInShipRoom, bool droppedInElevator, GrabbableObject gObject) { try { if ((Object)(object)gObject == (Object)null) { return true; } if ((Object)(object)gObject.itemProperties == (Object)null) { return true; } if (!gObject.itemProperties.isScrap) { return true; } if (string.IsNullOrEmpty(gObject.itemProperties.itemName)) { return true; } if (gObject.isInShipRoom == droppedInShipRoom) { return true; } if (gObject.scrapPersistedThroughRounds) { return true; } if (!droppedInShipRoom) { if (DanosPlayerStats.PlayerItems.Exists((DanosPlayerItem x) => x.Id == gObject.itemProperties.itemId && x.ItemName == gObject.itemProperties.itemName)) { DanosPlayerStats.PlayerItems.Remove(DanosPlayerStats.PlayerItems.Find((DanosPlayerItem x) => x.Id == gObject.itemProperties.itemId && x.ItemName == gObject.itemProperties.itemName)); } return true; } DanosPlayerItem item = new DanosPlayerItem { Id = gObject.itemProperties.itemId, ItemName = gObject.itemProperties.itemName, ItemValue = gObject.scrapValue, CreditsWorth = gObject.itemProperties.creditsWorth, CollectedAt = DateTimeOffset.UtcNow.ToUnixTimeSeconds() }; DanosPlayerStats.PlayerItems.Add(item); } catch (Exception ex) { Console.WriteLine("[LethalStats] [SetItemInElevator_Prefix]: Error in Prefix: " + ex.Message); } return true; } } [HarmonyPatch(typeof(StartMatchLever), "PullLeverAnim")] public static class PullLeverAnimPatch { public static string DebugPrefix = "[LethalStats] [PullLeverAnimPatch]: "; private static void Postfix() { try { StartOfRound instance = StartOfRound.Instance; if (!((Object)(object)instance == (Object)null)) { if (instance.inShipPhase) { Debug.Log((object)(DebugPrefix + "In ship phase, reset the values")); DanosPlayerStats.ResetValues(); UpdateHostInfo(); UpdateLevelName(); UpdateRoundStartTime(); } else { Debug.Log((object)(DebugPrefix + "Not in ship phase, do nothing")); } } } catch (Exception ex) { Debug.Log((object)(DebugPrefix + "Error in Postfix: " + ex.Message)); } } private static void UpdateHostInfo() { try { StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance == (Object)null) { return; } ulong playerClientId = instance.allPlayerScripts[0].playerClientId; ulong playerSteamId = instance.allPlayerScripts[playerClientId].playerSteamId; if (playerSteamId != 0) { bool flag = playerSteamId != DanosPlayerStats.HostSteamID; DanosPlayerStats.HostSteamID = playerSteamId; if (flag) { Debug.Log((object)(DebugPrefix + "Host changed, reset the values")); } else { Debug.Log((object)(DebugPrefix + "Host is the same, do nothing")); } DanosPlayerStats.RoundID = $"{DanosPlayerStats.HostSteamID}&&{instance.randomMapSeed}"; DanosPlayerStats.RoundInitialized = true; } } catch (Exception ex) { Debug.Log((object)(DebugPrefix + ex.Message)); } } private static void UpdateLevelName() { try { StartOfRound instance = StartOfRound.Instance; if (!((Object)(object)instance == (Object)null)) { SelectableLevel currentLevel = instance.currentLevel; if ((Object)(object)currentLevel != (Object)null) { DanosPlayerStats.LevelName = currentLevel.sceneName; } } } catch (Exception ex) { Debug.Log((object)(DebugPrefix + ex.Message)); } } private static void UpdateRoundStartTime() { try { DanosPlayerStats.RoundStart = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); } catch (Exception ex) { Debug.Log((object)(DebugPrefix + ex.Message)); } } } [HarmonyPatch(typeof(Terminal))] public static class Events { [HarmonyPatch("Awake")] [HarmonyPostfix] public static void Awake(ref Terminal __instance) { TerminalPatches.Terminal = __instance; } } [HarmonyPatch(typeof(Terminal), "Start")] public static class TerminalPatches { public static Terminal Terminal { get; internal set; } private static void Postfix(Terminal __instance) { ((MonoBehaviour)__instance).StartCoroutine(GatherGlobalStatsCoroutine(__instance)); } public static IEnumerator GatherGlobalStatsCoroutine(Terminal a_term) { Task task = GatherGlobalStats(a_term); yield return (object)new WaitUntil((Func<bool>)(() => task.IsCompleted)); if (task.Exception != null) { Debug.LogError((object)("[LethalStats] [TerminalPatches]: Error in GatherGlobalStats: " + task.Exception.Message)); } } private static IEnumerator ShowChallengeAvailableCoroutine() { yield return (object)new WaitForSeconds(5f); try { if (!DanosGlobalChallenges.ShownMessageThisSession) { HUDManager hUDManager = HUDManager.Instance; if ((Object)(object)hUDManager != (Object)null) { hUDManager.DisplayTip("LethalStats", "New Orders available, use command \"global\" in the terminal.", false, false, "LC_Tip1"); DanosGlobalChallenges.ShownMessageThisSession = true; } } } catch (Exception ex) { Debug.LogError((object)("[LethalStats] [TerminalPatches]: Error in ShowChallengeAvailableCoroutine: " + ex.Message)); } } public static async Task GatherGlobalStats(Terminal a_term) { string DisplayText2 = "We are gathering the latest global challenge information. Please wait..."; string terminalWord = "global"; TerminalNode terminalNode = ScriptableObject.CreateInstance<TerminalNode>(); terminalNode.displayText = DisplayText2; terminalNode.clearPreviousText = true; terminalNode.terminalEvent = ""; TerminalKeyword terminalKeyword = ScriptableObject.CreateInstance<TerminalKeyword>(); terminalKeyword.word = terminalWord; terminalKeyword.isVerb = false; terminalKeyword.specialKeywordResult = terminalNode; Terminal terminal = Terminal; if ((Object)(object)terminal != (Object)null) { if ((Object)(object)terminal.terminalNodes != (Object)null) { if ((Object)(object)((IEnumerable<TerminalKeyword>)terminal.terminalNodes.allKeywords).FirstOrDefault((Func<TerminalKeyword, bool>)((TerminalKeyword x) => x.word == terminalWord)) == (Object)null) { terminal.terminalNodes.allKeywords = CollectionExtensions.AddItem<TerminalKeyword>((IEnumerable<TerminalKeyword>)terminal.terminalNodes.allKeywords, terminalKeyword).ToArray(); Console.WriteLine("[LethalStats] [TerminalPatches]: Terminal object has terminalKeyword"); } else { Console.WriteLine("[LethalStats] [TerminalPatches]: Terminal object already has terminalKeyword"); } } else { Console.WriteLine("[LethalStats] [TerminalPatches]: Terminal object does not have terminalNodes"); } } else { Console.WriteLine("[LethalStats] [TerminalPatches]: Terminal object is null"); } bool giveNotification = false; try { using HttpClient client = new HttpClient(); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "https://lethalstatsservertasks.azurewebsites.net/api/GetCurrentGlobalChallenges"); HttpResponseMessage response = await client.SendAsync(request); if (response.IsSuccessStatusCode) { string content = await response.Content.ReadAsStringAsync(); Debug.Log((object)content); DanosGlobalChallenge[] globalChallenges = JsonConvert.DeserializeObject<DanosGlobalChallenge[]>(content); if (globalChallenges == null) { Console.WriteLine("[LethalStats] [TerminalPatches]: GlobalChallenges is null"); return; } DanosGlobalChallenge first = globalChallenges.FirstOrDefault(); if (first == null) { return; } DanosGlobalChallenges.GlobalChallenge = first; Console.WriteLine("[LethalStats] [TerminalPatches]: GlobalChallenge: " + first.Title); giveNotification = true; } } catch (Exception ex2) { Debug.LogError((object)("[LethalStats] [TerminalPatches]: Error in GatherGlobalStats: " + ex2.Message)); } DisplayText2 = "No global challenge available at this time. Please check back later."; if (DanosGlobalChallenges.GlobalChallenge != null) { terminalWord = "global"; DisplayText2 = DanosGlobalChallenges.GlobalChallenge.TerminalText ?? ""; } try { terminalNode.displayText = DisplayText2; terminalNode.clearPreviousText = true; terminalKeyword.word = terminalWord; for (int i = 0; i < terminal.terminalNodes.allKeywords.Length; i++) { if (terminal.terminalNodes.allKeywords[i].word == terminalWord) { terminal.terminalNodes.allKeywords[i] = terminalKeyword; } } if (giveNotification) { ((MonoBehaviour)a_term).StartCoroutine(ShowChallengeAvailableCoroutine()); } } catch (Exception ex) { Debug.LogError((object)("[LethalStats] [TerminalPatches]: Error in GatherGlobalStats: " + ex.Message)); } } } } namespace LethalStats.Models { public static class DanosGlobalChallenges { public static bool ShownMessageThisSession { get; set; } public static DanosGlobalChallenge GlobalChallenge { get; set; } } public class GlobalChallengeList { public DanosGlobalChallenge[] Property1 { get; set; } } public class DanosGlobalChallenge { public int ID { get; set; } public string Title { get; set; } public string TerminalText { get; set; } public string ChallengeType { get; set; } public int Target { get; set; } public int CurrentProgress { get; set; } public int StartDateUTC { get; set; } public int EndDateUTC { get; set; } public string Criteria { get; set; } } public class DanosGlobalContributions { public string itemName { get; set; } = ""; public int count { get; set; } = 0; public int scrapValueAverage { get; set; } = 0; } public class DanosPlayerEvent { public string EventName { get; set; } public DateTime Timestamp { get; set; } public Dictionary<string, string> AdditionalDetails { get; set; } public DanosPlayerEvent(string eventName, Dictionary<string, string> additionalDetails = null) { EventName = eventName; Timestamp = DateTime.UtcNow; AdditionalDetails = additionalDetails ?? new Dictionary<string, string>(); } } public class DanosPlayerItem { public int Id { get; set; } = 0; public string ItemName { get; set; } = ""; public int ItemValue { get; set; } = 0; public int CreditsWorth { get; set; } = 0; public long CollectedAt { get; set; } = 0L; } public class DanosPlayerMods { public string ModGUID { get; set; } = ""; public string ModName { get; set; } = ""; public string ModVersion { get; set; } = ""; public static List<DanosPlayerMods> CollectMods() { List<DanosPlayerMods> list = new List<DanosPlayerMods>(); try { Dictionary<string, PluginInfo> pluginInfos = Chainloader.PluginInfos; foreach (PluginInfo value in pluginInfos.Values) { list.Add(new DanosPlayerMods { ModGUID = value.Metadata.GUID, ModName = value.Metadata.Name, ModVersion = value.Metadata.Version.ToString() }); } } catch (Exception ex) { Console.WriteLine("Error in CollectMods: " + ex.Message); list = new List<DanosPlayerMods>(); } return list; } } public class DanosPlayerStats { public static string RoundID = ""; public static DateTime LastSentResults = DateTime.MinValue; public static List<DanosPlayerEvent> PlayerEvents = new List<DanosPlayerEvent>(); public static List<DanosPlayerItem> PlayerItems = new List<DanosPlayerItem>(); public static bool HasSentResults = false; public static bool RoundInitialized = false; public static long RoundStart = 0L; public static long RoundEnd = 0L; public static long QuotaStringA = 0L; public static long QuotaStringB = 0L; public static long QuotaStringC = 0L; public static Dictionary<AdvancedCauseOfDeath?, int> deathCounts = new Dictionary<AdvancedCauseOfDeath?, int>(); public static string LevelName { get; set; } = "Unknown"; public static double RoundDuration => (double)(RoundEnd - RoundStart) / 60.0; public static int TotalScrapCollectedThisRound { get; set; } public static float TotalScrapOnMap { get; set; } public static int DaysOnTheJob { get; set; } public static float ScrapOnShip { get; set; } public static int ScrapValueCollected { get; set; } public static int TeamDeaths { get; set; } public static int TeamStepsTaken { get; set; } public static int CreditsAtEnd { get; set; } public static int PlayersInLobby { get; set; } public static int PlayersDead { get; set; } public static int StepsTaken { get; set; } public static ulong MySteamID { get; set; } public static string MyUsername { get; set; } public static ulong HostSteamID { get; set; } public static bool Fired { get; set; } = false; public static int Deaths { get; set; } public static void IncrementDeathCount(AdvancedCauseOfDeath? cause) { if (!deathCounts.ContainsKey(cause)) { deathCounts[cause] = 0; } deathCounts[cause]++; Deaths++; } public static int GetDeathCount(AdvancedCauseOfDeath? cause) { return deathCounts.ContainsKey(cause) ? deathCounts[cause] : 0; } public static void ResetDeathCounts() { deathCounts.Clear(); } public static bool PostResults() { try { if ((DateTime.Now - LastSentResults).TotalSeconds < 30.0) { Debug.Log((object)"Results were sent in the last 30 seconds, skipping"); return true; } string causeOfDeath = ""; if (Deaths > 0) { causeOfDeath = deathCounts.FirstOrDefault().Key.ToString(); } int gameVersion = 49; try { GameNetworkManager instance = GameNetworkManager.Instance; if ((Object)(object)instance != (Object)null) { gameVersion = instance.gameVersionNum; } } catch (Exception ex) { Debug.Log((object)ex.Message); } List<DanosPlayerMods> list = new List<DanosPlayerMods>(); try { list = DanosPlayerMods.CollectMods(); } catch (Exception ex2) { Debug.Log((object)ex2.Message); list = new List<DanosPlayerMods>(); } var anon = new { RoundID = RoundID, HostSteamID = HostSteamID, DaysOnTheJob = DaysOnTheJob, ScrapValueCollected = ScrapValueCollected, TeamDeaths = TeamDeaths, TeamStepsTaken = TeamStepsTaken, Deaths = Deaths, StepsTaken = StepsTaken, MySteamID = MySteamID, MyUsername = MyUsername, QuotaStringA = QuotaStringA, QuotaStringB = QuotaStringB, QuotaStringC = QuotaStringC, ScrapOnShip = ScrapOnShip, LevelName = LevelName, PlayerDied = (Deaths > 0), CauseOfDeath = causeOfDeath, RoundStart = RoundStart, RoundEnd = RoundEnd, RoundDuration = RoundDuration, CreditsAtEnd = CreditsAtEnd, PlayersInLobby = PlayersInLobby, PlayersDead = PlayersDead, TotalScrapCollectedThisRound = TotalScrapCollectedThisRound, TotalScrapOnMap = TotalScrapOnMap, Fired = Fired, GameVersion = gameVersion, Events = new List<DanosPlayerEvent>(), Mods = list, Items = PlayerItems }; string content = JsonConvert.SerializeObject((object)anon); HttpClient httpClient = new HttpClient(); httpClient.BaseAddress = new Uri("https://lethal.api.splitstats.io"); StringContent content2 = new StringContent(content, Encoding.UTF8, "application/json"); httpClient.PostAsync("/api/match/results?", content2); LastSentResults = DateTime.Now; } catch (Exception ex3) { Debug.Log((object)ex3.Message); return false; } return true; } public static void ResetValues() { RoundID = ""; PlayerEvents = new List<DanosPlayerEvent>(); PlayerItems = new List<DanosPlayerItem>(); HasSentResults = false; DaysOnTheJob = 0; ScrapValueCollected = 0; TeamDeaths = 0; TeamStepsTaken = 0; Deaths = 0; StepsTaken = 0; MySteamID = 0uL; MyUsername = ""; QuotaStringA = 0L; QuotaStringB = 0L; QuotaStringC = 0L; ScrapOnShip = 0f; LevelName = "Unknown"; RoundStart = 0L; RoundEnd = 0L; CreditsAtEnd = 0; PlayersInLobby = 0; PlayersDead = 0; TotalScrapCollectedThisRound = 0; TotalScrapOnMap = 0f; Fired = false; ResetDeathCounts(); } internal static string GetSHA256(string roundString) { using SHA256 sHA = SHA256.Create(); byte[] array = sHA.ComputeHash(Encoding.UTF8.GetBytes(roundString)); return BitConverter.ToString(array).Replace("-", "").ToLower(); } } }