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 LethalCasinoTracker v1.1.0
LethalCasinoTracker.dll
Decompiled a month agousing System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using LethalCasinoTracker.Patches; using TMPro; using Unity.Collections; using Unity.Netcode; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyVersion("0.0.0.0")] namespace LethalCasinoTracker { public enum CasinoGameType { Unknown, Blackjack, Roulette, Slots, Wheel } public static class CasinoGameNames { public static string Display(CasinoGameType t) { return t switch { CasinoGameType.Blackjack => "Blackjack", CasinoGameType.Roulette => "Roulette", CasinoGameType.Slots => "Slots", CasinoGameType.Wheel => "The Wheel", _ => "Casino", }; } public static CasinoGameType FromTypeName(string typeName) { return typeName switch { "Blackjack" => CasinoGameType.Blackjack, "Roulette" => CasinoGameType.Roulette, "SlotMachine" => CasinoGameType.Slots, "TheWheel" => CasinoGameType.Wheel, _ => CasinoGameType.Unknown, }; } } public static class CasinoHooks { public struct ScrapCapture { public bool valid; public GrabbableObject grab; public int before; } public static readonly string[] GameTypeNames = new string[4] { "Blackjack", "Roulette", "SlotMachine", "TheWheel" }; private static readonly Dictionary<string, FieldInfo> _fieldCache = new Dictionary<string, FieldInfo>(); private static readonly Dictionary<GrabbableObject, int> _lastValue = new Dictionary<GrabbableObject, int>(); public static void ResetValueTracking() { _lastValue.Clear(); } public static void ScrapPrefix(NetworkBehaviourReference item, out ScrapCapture __state) { __state = default(ScrapCapture); try { GrabbableObject val = default(GrabbableObject); if (((NetworkBehaviourReference)(ref item)).TryGet<GrabbableObject>(ref val, (NetworkManager)null) && (Object)(object)val != (Object)null) { __state.valid = true; __state.grab = val; __state.before = val.scrapValue; } } catch { } } public static void ScrapPostfix(object __instance, int newValue, ScrapCapture __state) { if (!__state.valid || (Object)(object)__state.grab == (Object)null || !TrackerManager.IsServer()) { return; } try { GrabbableObject grab = __state.grab; int scrapValue = grab.scrapValue; if (!_lastValue.TryGetValue(grab, out var value)) { value = __state.before; } int num = scrapValue - value; _lastValue[grab] = scrapValue; string name = __instance.GetType().Name; if (Plugin.VerboseLogging) { Plugin.Log.LogInfo((object)("[bet] " + name + " baseline=" + value + " after=" + scrapValue + " newArg=" + newValue + " orig=" + ReadOriginal(grab) + " delta=" + num)); } if (num == 0) { return; } CasinoGameType game = CasinoGameNames.FromTypeName(name); PlayerControllerB val = ResolveOwner(__instance, name, grab); if ((Object)(object)val == (Object)null) { if (Plugin.VerboseLogging) { Plugin.Log.LogWarning((object)("Could not resolve owner for a " + name + " payout of " + num)); } return; } int num2 = 0; Object val2 = (Object)((__instance is Object) ? __instance : null); if (val2 != (Object)null) { num2 = val2.GetInstanceID(); } ulong playerClientId = val.playerClientId; string playerUsername = val.playerUsername; if ((Object)(object)TrackerManager.Instance != (Object)null) { TrackerManager.Instance.RecordResolution(playerClientId, playerUsername, num, game, num2); } NetworkSync.BroadcastDelta(playerClientId, playerUsername, num, game, num2); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Casino capture error: " + ex.Message)); } } private static PlayerControllerB ResolveOwner(object inst, string typeName, GrabbableObject grab) { Type type = inst.GetType(); switch (typeName) { case "Blackjack": { List<GrabbableObject>[] array = GetField(type, "gambledScrap").GetValue(inst) as List<GrabbableObject>[]; PlayerControllerB[] array2 = GetField(type, "gamblingPlayers").GetValue(inst) as PlayerControllerB[]; if (array == null || array2 == null) { return null; } int num = Math.Min(array.Length, array2.Length); for (int i = 0; i < num; i++) { if (array[i] != null && array[i].Contains(grab)) { return array2[i]; } } return null; } case "Roulette": { if (GetField(type, "gambledScrapOwners").GetValue(inst) is Dictionary<GrabbableObject, PlayerControllerB> dictionary && dictionary.TryGetValue(grab, out var value2)) { return value2; } return null; } case "SlotMachine": case "TheWheel": { FieldInfo field = GetField(type, "gamblingPlayer"); if (!(field == null)) { object? value = field.GetValue(inst); return (PlayerControllerB)((value is PlayerControllerB) ? value : null); } return null; } default: return null; } } private static int ReadOriginal(GrabbableObject grab) { try { Type type = AccessTools.TypeByName("LethalCasino.Custom.CustomScrapController"); if (type == null) { return -1; } Component component = ((Component)grab).GetComponent(type); if ((Object)(object)component == (Object)null) { return -1; } FieldInfo field = GetField(type, "originalScrapValue"); if (field == null) { return -1; } object value = field.GetValue(component); return (value is int) ? ((int)value) : (-1); } catch { return -1; } } private static FieldInfo GetField(Type t, string name) { string key = t.FullName + "." + name; if (!_fieldCache.TryGetValue(key, out var value)) { value = AccessTools.Field(t, name); _fieldCache[key] = value; } return value; } public static void ApplyPatches(Harmony h) { //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Expected O, but got Unknown //IL_00bb: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.Method(typeof(CasinoHooks), "ScrapPrefix", (Type[])null, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(CasinoHooks), "ScrapPostfix", (Type[])null, (Type[])null); for (int i = 0; i < GameTypeNames.Length; i++) { string text = "LethalCasino.Custom." + GameTypeNames[i]; Type type = AccessTools.TypeByName(text); if (type == null) { Plugin.Log.LogWarning((object)("Casino type not found: " + text)); continue; } MethodInfo methodInfo3 = AccessTools.Method(type, "UpdateScrapValueClientRpc", (Type[])null, (Type[])null); if (methodInfo3 == null) { Plugin.Log.LogWarning((object)("UpdateScrapValueClientRpc not found on " + text)); continue; } try { h.Patch((MethodBase)methodInfo3, new HarmonyMethod(methodInfo), new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Plugin.Log.LogInfo((object)("Patched " + GameTypeNames[i] + ".UpdateScrapValueClientRpc")); } catch (Exception ex) { Plugin.Log.LogError((object)("Failed to patch " + text + ": " + ex.Message)); } } } } public class ChalkboardController : MonoBehaviour { private Type _buildingType; private Component _building; private float _nextSearch; private GameObject _board; private TextMeshProUGUI _text; private bool _dirty = true; private void Start() { _buildingType = AccessTools.TypeByName("LethalCasino.Custom.CasinoBuilding"); if (_buildingType == null) { Plugin.Log.LogWarning((object)"CasinoBuilding type not found; chalkboard disabled."); } } private void Update() { //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.ChalkboardEnabled() || _buildingType == null) { return; } if ((Object)(object)_building == (Object)null && Time.realtimeSinceStartup >= _nextSearch) { _nextSearch = Time.realtimeSinceStartup + 1.5f; ref Component building = ref _building; Object obj = Object.FindObjectOfType(_buildingType); building = (Component)(object)((obj is Component) ? obj : null); if ((Object)(object)_building != (Object)null && (Object)(object)_board == (Object)null) { BuildBoard(); } } if ((Object)(object)_building == (Object)null) { if ((Object)(object)_board != (Object)null) { Object.Destroy((Object)(object)_board); _board = null; } } else if (!((Object)(object)_board == (Object)null)) { Transform transform = _building.transform; _board.transform.position = transform.position + transform.right * Plugin.ChalkOffsetX() + Vector3.up * Plugin.ChalkOffsetY() + transform.forward * Plugin.ChalkOffsetZ(); Vector3 forward = transform.forward; forward.y = 0f; if (((Vector3)(ref forward)).sqrMagnitude < 0.0001f) { forward = Vector3.forward; } _board.transform.rotation = Quaternion.AngleAxis(Plugin.ChalkYaw(), Vector3.up) * Quaternion.LookRotation(((Vector3)(ref forward)).normalized, Vector3.up); TrackerManager instance = TrackerManager.Instance; if ((Object)(object)instance != (Object)null && (instance.RecordsDirty || _dirty)) { RefreshText(instance); instance.RecordsDirty = false; _dirty = false; } } } private void OnDestroy() { if ((Object)(object)_board != (Object)null) { Object.Destroy((Object)(object)_board); } } private void BuildBoard() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) _board = new GameObject("LCCasinoChalkboard"); _board.transform.localScale = Vector3.one * Plugin.ChalkScale(); Canvas val = _board.AddComponent<Canvas>(); val.renderMode = (RenderMode)2; RectTransform component = ((Component)val).GetComponent<RectTransform>(); component.sizeDelta = new Vector2(520f, 360f); Image val2 = LCStyle.Panel(_board.transform, new Color(0.05f, 0.08f, 0.06f, 0.96f)); LCStyle.Stretch(((Graphic)val2).rectTransform, 0f, 0f); Image val3 = LCStyle.Panel(((Component)val2).transform, new Color(0.4f, 0.52f, 0.36f, 0.5f)); RectTransform rectTransform = ((Graphic)val3).rectTransform; rectTransform.anchorMin = new Vector2(0f, 1f); rectTransform.anchorMax = new Vector2(1f, 1f); rectTransform.pivot = new Vector2(0.5f, 1f); rectTransform.sizeDelta = new Vector2(0f, 3f); rectTransform.anchoredPosition = Vector2.zero; _text = LCStyle.Text(_board.transform, "Text", 22f, (TextAlignmentOptions)257, nativeGlow: false); ((Graphic)_text).color = new Color(0.88f, 0.93f, 0.83f); LCStyle.Stretch(((TMP_Text)_text).rectTransform, 26f, 22f); _dirty = true; ManualLogSource log = Plugin.Log; Vector3 position = _building.transform.position; log.LogInfo((object)("Chalkboard spawned at casino " + ((Vector3)(ref position)).ToString("F1"))); } private void RefreshText(TrackerManager tm) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_text == (Object)null)) { List<PlayerRunRecord> recordsSorted = tm.GetRecordsSorted(); string value = LCStyle.Tag("------------------------------", LCStyle.Rule); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append(LCStyle.Tag("ALL-TIME CASINO RECORDS", LCStyle.Header)).Append('\n'); stringBuilder.Append(value).Append('\n'); Color c = default(Color); ((Color)(ref c))..ctor(0.88f, 0.93f, 0.83f); FindExtremes(recordsSorted, out var biggestWin, out var biggestLoss); stringBuilder.Append(LCStyle.Tag("BIGGEST WIN", LCStyle.Dim)).Append("<pos=38%>"); if (biggestWin != null && biggestWin.biggestSingleWin > 0) { stringBuilder.Append(LCStyle.Tag(Trunc(biggestWin.username, 11), c)).Append("<pos=70%>").Append(LCStyle.Tag("+" + biggestWin.biggestSingleWin.ToString("N0"), LCStyle.Up)); } else { stringBuilder.Append(LCStyle.Tag("-", LCStyle.Dim)); } stringBuilder.Append('\n'); stringBuilder.Append(LCStyle.Tag("BIGGEST LOSS", LCStyle.Dim)).Append("<pos=38%>"); if (biggestLoss != null && biggestLoss.biggestSingleLoss > 0) { stringBuilder.Append(LCStyle.Tag(Trunc(biggestLoss.username, 11), c)).Append("<pos=70%>").Append(LCStyle.Tag("-" + biggestLoss.biggestSingleLoss.ToString("N0"), LCStyle.Down)); } else { stringBuilder.Append(LCStyle.Tag("-", LCStyle.Dim)); } stringBuilder.Append('\n'); stringBuilder.Append(value).Append('\n'); stringBuilder.Append(LCStyle.Tag("TOTAL GAMES", LCStyle.Dim)).Append("<pos=38%>").Append(tm.TotalGames()); ((TMP_Text)_text).text = stringBuilder.ToString(); } } private static void FindExtremes(List<PlayerRunRecord> recs, out PlayerRunRecord biggestWin, out PlayerRunRecord biggestLoss) { biggestWin = null; biggestLoss = null; for (int i = 0; i < recs.Count; i++) { PlayerRunRecord playerRunRecord = recs[i]; if (biggestWin == null || playerRunRecord.biggestSingleWin > biggestWin.biggestSingleWin) { biggestWin = playerRunRecord; } if (biggestLoss == null || playerRunRecord.biggestSingleLoss > biggestLoss.biggestSingleLoss) { biggestLoss = playerRunRecord; } } } private static string Trunc(string s, int max) { if (string.IsNullOrEmpty(s)) { return ""; } if (s.Length > max) { return s.Substring(0, max); } return s; } } public class HUDController : MonoBehaviour { private GameObject _root; private RectTransform _panel; private RawImage _scan; private TextMeshProUGUI _text; private bool _built; private void Build() { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) if (LCStyle.Ready) { Canvas val = LCStyle.OverlayCanvas("LCCT_HUD", 800); _root = ((Component)val).gameObject; Image val2 = LCStyle.SoftPanel(_root.transform, new Color(0.02f, 0.04f, 0.03f, 0.5f)); _panel = ((Graphic)val2).rectTransform; _panel.anchorMin = new Vector2(1f, 1f); _panel.anchorMax = new Vector2(1f, 1f); _panel.pivot = new Vector2(1f, 1f); _scan = LCStyle.Scanlines(((Component)val2).transform, new Color(0f, 0f, 0f, 0.18f)); LCStyle.Stretch(((Graphic)_scan).rectTransform, 3f, 3f); _text = LCStyle.Text(((Component)val2).transform, "Text", Plugin.HudFontSize(), (TextAlignmentOptions)257, nativeGlow: true); LCStyle.Stretch(((TMP_Text)_text).rectTransform, 16f, 12f); _built = true; } } private void Update() { //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) if (!_built) { Build(); if (!_built) { return; } } TrackerManager instance = TrackerManager.Instance; StartOfRound instance2 = StartOfRound.Instance; bool flag = Plugin.HudEnabled() && (Object)(object)instance != (Object)null && (Object)(object)instance2 != (Object)null && instance2.shipHasLanded && !instance2.shipIsLeaving && IsGordion(instance2); if (_root.activeSelf != flag) { _root.SetActive(flag); } if (flag) { List<PlayerControllerB> crew = GetCrew(instance2); float num = (float)Plugin.HudFontSize() * 1.34f; float num2 = (float)(crew.Count + 4) * num + 22f; _panel.sizeDelta = new Vector2((float)Plugin.HudWidth(), num2); _panel.anchoredPosition = new Vector2((float)(-Plugin.HudMarginX()), (float)(-Plugin.HudMarginY())); if ((Object)(object)_scan != (Object)null) { _scan.uvRect = new Rect(0f, 0f, 1f, num2 / 3f); } ((TMP_Text)_text).text = BuildText(instance, crew); } } private static string BuildText(TrackerManager tm, List<PlayerControllerB> crew) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) string value = LCStyle.Tag("------------------------", LCStyle.Rule); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append(LCStyle.Tag("SESSION", LCStyle.Header)).Append('\n'); stringBuilder.Append(value).Append('\n'); for (int i = 0; i < crew.Count; i++) { PlayerControllerB val = crew[i]; string s = (string.IsNullOrEmpty(val.playerUsername) ? ("Player " + val.playerClientId) : val.playerUsername); stringBuilder.Append(LCStyle.Tag(Trunc(s, 12), LCStyle.Ink)); if (tm.TryGetSessionDelta(val.playerClientId, out var delta) && delta != 0) { Color c = ((delta > 0) ? LCStyle.Up : LCStyle.Down); stringBuilder.Append("<pos=60%>").Append(LCStyle.Tag(LCStyle.Signed(delta), c)); } stringBuilder.Append('\n'); } stringBuilder.Append(value).Append('\n'); int num = tm.CrewNet(); Color c2 = ((num > 0) ? LCStyle.Up : ((num < 0) ? LCStyle.Down : LCStyle.Ink)); stringBuilder.Append(LCStyle.Tag("CREW", LCStyle.Dim)).Append("<pos=60%>").Append(LCStyle.Tag((num == 0) ? "0" : LCStyle.Signed(num), c2)); return stringBuilder.ToString(); } private static bool IsGordion(StartOfRound sor) { SelectableLevel currentLevel = sor.currentLevel; if ((Object)(object)currentLevel == (Object)null || string.IsNullOrEmpty(currentLevel.PlanetName)) { return false; } return currentLevel.PlanetName.IndexOf("Gordion", StringComparison.OrdinalIgnoreCase) >= 0; } private static List<PlayerControllerB> GetCrew(StartOfRound sor) { List<PlayerControllerB> list = new List<PlayerControllerB>(); PlayerControllerB[] allPlayerScripts = sor.allPlayerScripts; if (allPlayerScripts == null) { return list; } foreach (PlayerControllerB val in allPlayerScripts) { if (!((Object)(object)val == (Object)null) && (val.isPlayerControlled || val.isPlayerDead)) { list.Add(val); } } return list; } private static string Trunc(string s, int max) { if (string.IsNullOrEmpty(s)) { return ""; } if (s.Length > max) { return s.Substring(0, max); } return s; } private void OnDestroy() { if ((Object)(object)_root != (Object)null) { Object.Destroy((Object)(object)_root); } } } public static class LCStyle { public static readonly Color Ink = new Color(0.74f, 0.85f, 0.7f); public static readonly Color Dim = new Color(0.46f, 0.55f, 0.44f); public static readonly Color Up = new Color(0.56f, 0.96f, 0.52f); public static readonly Color Down = new Color(0.95f, 0.46f, 0.36f); public static readonly Color Header = new Color(0.72f, 0.88f, 0.6f); public static readonly Color Rule = new Color(0.55f, 0.66f, 0.45f, 0.5f); private static TMP_FontAsset _font; private static Material _mat; private static Sprite _softPanel; private static Texture2D _scan; private static Sprite _outline; public static bool Ready { get { EnsureRef(); if ((Object)(object)_font != (Object)null) { return (Object)(object)_mat != (Object)null; } return false; } } public static string Hex(Color c) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return ColorUtility.ToHtmlStringRGB(c); } public static string Tag(string s, Color c) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) return "<color=#" + Hex(c) + ">" + s + "</color>"; } public static string Signed(int v) { return ((v > 0) ? "+" : "") + v.ToString("N0"); } private static void EnsureRef() { //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Expected O, but got Unknown //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_font != (Object)null && (Object)(object)_mat != (Object)null) { return; } try { HUDManager instance = HUDManager.Instance; if ((Object)(object)instance == (Object)null) { return; } TextMeshProUGUI val = null; if ((Object)(object)instance.weightCounter != (Object)null) { val = instance.weightCounter; } else if (instance.controlTipLines != null && instance.controlTipLines.Length > 0) { val = instance.controlTipLines[0]; } else if ((Object)(object)instance.clockNumber != (Object)null) { val = instance.clockNumber; } if ((Object)(object)val == (Object)null) { return; } if ((Object)(object)((TMP_Text)val).font != (Object)null) { _font = ((TMP_Text)val).font; } if (!((Object)(object)((TMP_Text)val).fontSharedMaterial != (Object)null)) { return; } _mat = new Material(((TMP_Text)val).fontSharedMaterial); try { _mat.SetColor("_FaceColor", Color.white); _mat.EnableKeyword("GLOW_ON"); _mat.SetColor("_GlowColor", new Color(0.4f, 1f, 0.55f, 1f)); _mat.SetFloat("_GlowPower", 0.35f); _mat.SetFloat("_GlowOuter", 0.45f); _mat.SetFloat("_GlowInner", 0.05f); _mat.EnableKeyword("OUTLINE_ON"); _mat.SetColor("_OutlineColor", new Color(0f, 0.08f, 0.03f, 1f)); _mat.SetFloat("_OutlineWidth", 0.18f); } catch { } } catch { } } public static TMP_FontAsset Font() { EnsureRef(); if ((Object)(object)_font == (Object)null) { try { _font = TMP_Settings.defaultFontAsset; } catch { } } return _font; } public static Canvas OverlayCanvas(string name, int sortingOrder) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_003b: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name); Object.DontDestroyOnLoad((Object)(object)val); Canvas val2 = val.AddComponent<Canvas>(); val2.renderMode = (RenderMode)0; val2.sortingOrder = sortingOrder; CanvasScaler val3 = val.AddComponent<CanvasScaler>(); val3.uiScaleMode = (ScaleMode)1; val3.referenceResolution = new Vector2(1920f, 1080f); val3.screenMatchMode = (ScreenMatchMode)0; val3.matchWidthOrHeight = 0.5f; return val2; } public static Image Panel(Transform parent, Color color) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0020: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Panel"); val.transform.SetParent(parent, false); Image val2 = val.AddComponent<Image>(); ((Graphic)val2).color = color; ((Graphic)val2).raycastTarget = false; return val2; } public static Image SoftPanel(Transform parent, Color color) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0032: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Panel"); val.transform.SetParent(parent, false); Image val2 = val.AddComponent<Image>(); val2.sprite = SoftSprite(); val2.type = (Type)1; ((Graphic)val2).color = color; ((Graphic)val2).raycastTarget = false; return val2; } public static Image Box(Transform parent, Color color) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0032: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Box"); val.transform.SetParent(parent, false); Image val2 = val.AddComponent<Image>(); val2.sprite = OutlineSprite(); val2.type = (Type)1; ((Graphic)val2).color = color; ((Graphic)val2).raycastTarget = false; return val2; } private static Sprite OutlineSprite() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_outline != (Object)null) { return _outline; } int num = 16; int num2 = 4; int num3 = 2; Texture2D val = new Texture2D(num, num, (TextureFormat)4, false); ((Texture)val).wrapMode = (TextureWrapMode)1; for (int i = 0; i < num; i++) { for (int j = 0; j < num; j++) { bool flag = j < num3 || j >= num - num3 || i < num3 || i >= num - num3; val.SetPixel(j, i, new Color(1f, 1f, 1f, flag ? 1f : 0f)); } } val.Apply(); ((Object)val).hideFlags = (HideFlags)61; _outline = Sprite.Create(val, new Rect(0f, 0f, (float)num, (float)num), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0, new Vector4((float)num2, (float)num2, (float)num2, (float)num2)); return _outline; } public static RawImage Scanlines(Transform parent, Color color) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_002b: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Scanlines"); val.transform.SetParent(parent, false); RawImage val2 = val.AddComponent<RawImage>(); val2.texture = (Texture)(object)ScanTex(); ((Graphic)val2).color = color; ((Graphic)val2).raycastTarget = false; return val2; } public static TextMeshProUGUI Text(Transform parent, string name, float size, TextAlignmentOptions align, bool nativeGlow) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name); val.transform.SetParent(parent, false); TextMeshProUGUI val2 = val.AddComponent<TextMeshProUGUI>(); ((TMP_Text)val2).font = Font(); if (nativeGlow && (Object)(object)_mat != (Object)null) { ((TMP_Text)val2).fontSharedMaterial = _mat; } ((TMP_Text)val2).fontSize = size; ((Graphic)val2).color = Ink; ((TMP_Text)val2).alignment = align; ((TMP_Text)val2).richText = true; ((TMP_Text)val2).enableWordWrapping = false; ((TMP_Text)val2).overflowMode = (TextOverflowModes)0; ((Graphic)val2).raycastTarget = false; return val2; } public static void Stretch(RectTransform rt, float padX, float padY) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) rt.anchorMin = Vector2.zero; rt.anchorMax = Vector2.one; rt.offsetMin = new Vector2(padX, padY); rt.offsetMax = new Vector2(0f - padX, 0f - padY); } private static Sprite SoftSprite() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_softPanel != (Object)null) { return _softPanel; } int num = 32; int num2 = 12; Texture2D val = new Texture2D(num, num, (TextureFormat)4, false); ((Texture)val).wrapMode = (TextureWrapMode)1; for (int i = 0; i < num; i++) { for (int j = 0; j < num; j++) { int num3 = Mathf.Min(Mathf.Min(j, num - 1 - j), Mathf.Min(i, num - 1 - i)); float num4 = Mathf.Clamp01((float)num3 / (float)num2); num4 = num4 * num4 * (3f - 2f * num4); val.SetPixel(j, i, new Color(1f, 1f, 1f, num4)); } } val.Apply(); ((Object)val).hideFlags = (HideFlags)61; _softPanel = Sprite.Create(val, new Rect(0f, 0f, (float)num, (float)num), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0, new Vector4((float)num2, (float)num2, (float)num2, (float)num2)); return _softPanel; } private static Texture2D ScanTex() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_scan != (Object)null) { return _scan; } _scan = new Texture2D(1, 3, (TextureFormat)4, false); ((Texture)_scan).wrapMode = (TextureWrapMode)0; ((Texture)_scan).filterMode = (FilterMode)0; _scan.SetPixel(0, 0, new Color(0f, 0f, 0f, 0f)); _scan.SetPixel(0, 1, new Color(0f, 0f, 0f, 0f)); _scan.SetPixel(0, 2, new Color(0f, 0f, 0f, 1f)); _scan.Apply(); ((Object)_scan).hideFlags = (HideFlags)61; return _scan; } } [Serializable] public class DeltaMsg { public long id; public int delta; public int game; public int inst; public string name = ""; } public static class NetworkSync { private const string MsgDelta = "LCCT_Delta"; private const string MsgRequest = "LCCT_Req"; private const string MsgState = "LCCT_State"; private static bool _registered; private static NetworkManager _registeredOn; private static bool _requested; public static void Tick() { try { NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.IsListening) { _registered = false; _registeredOn = null; _requested = false; return; } if (!_registered || (Object)(object)_registeredOn != (Object)(object)singleton) { Register(singleton); } if (!singleton.IsServer && singleton.IsConnectedClient && !_requested) { Send("LCCT_Req", 0uL, "1"); _requested = true; } } catch (Exception ex) { Plugin.Log.LogWarning((object)("NetworkSync.Tick: " + ex.Message)); } } public static void RequestResync() { _requested = false; } private static void Register(NetworkManager nm) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown CustomMessagingManager customMessagingManager = nm.CustomMessagingManager; if (customMessagingManager != null) { customMessagingManager.RegisterNamedMessageHandler("LCCT_Delta", new HandleNamedMessageDelegate(OnDelta)); customMessagingManager.RegisterNamedMessageHandler("LCCT_Req", new HandleNamedMessageDelegate(OnRequest)); customMessagingManager.RegisterNamedMessageHandler("LCCT_State", new HandleNamedMessageDelegate(OnState)); _registered = true; _registeredOn = nm; Plugin.Log.LogInfo((object)("NetworkSync handlers registered (server=" + nm.IsServer + ").")); } } public static void BroadcastDelta(ulong id, string username, int delta, CasinoGameType game, int instId) { try { NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.IsServer || singleton.CustomMessagingManager == null) { return; } DeltaMsg deltaMsg = new DeltaMsg(); deltaMsg.id = (long)id; deltaMsg.delta = delta; deltaMsg.game = (int)game; deltaMsg.inst = instId; deltaMsg.name = ((username == null) ? "" : username); string payload = JsonUtility.ToJson((object)deltaMsg); foreach (ulong connectedClientsId in singleton.ConnectedClientsIds) { if (connectedClientsId != 0) { Send("LCCT_Delta", connectedClientsId, payload); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("BroadcastDelta: " + ex.Message)); } } private static void Send(string msg, ulong clientId, string payload) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(Encoding.UTF8.GetByteCount(payload) + 64, (Allocator)2, 524288); try { ((FastBufferWriter)(ref val)).WriteValueSafe(payload, false); NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage(msg, clientId, val, (NetworkDelivery)2); } finally { ((FastBufferWriter)(ref val)).Dispose(); } } private static void OnDelta(ulong sender, FastBufferReader reader) { try { if (!TrackerManager.IsServer()) { string text = default(string); ((FastBufferReader)(ref reader)).ReadValueSafe(ref text, false); DeltaMsg deltaMsg = JsonUtility.FromJson<DeltaMsg>(text); if (deltaMsg != null && (Object)(object)TrackerManager.Instance != (Object)null) { TrackerManager.Instance.RecordResolution((ulong)deltaMsg.id, deltaMsg.name, deltaMsg.delta, (CasinoGameType)deltaMsg.game, deltaMsg.inst); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("OnDelta: " + ex.Message)); } } private static void OnRequest(ulong sender, FastBufferReader reader) { try { if (TrackerManager.IsServer() && !((Object)(object)TrackerManager.Instance == (Object)null)) { SyncBlob syncBlob = TrackerManager.Instance.BuildSyncBlob(); Send("LCCT_State", sender, JsonUtility.ToJson((object)syncBlob)); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("OnRequest: " + ex.Message)); } } private static void OnState(ulong sender, FastBufferReader reader) { try { if (!TrackerManager.IsServer()) { string text = default(string); ((FastBufferReader)(ref reader)).ReadValueSafe(ref text, false); SyncBlob b = JsonUtility.FromJson<SyncBlob>(text); if ((Object)(object)TrackerManager.Instance != (Object)null) { TrackerManager.Instance.ApplySyncBlob(b); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("OnState: " + ex.Message)); } } } [Serializable] public class PlayerRunRecord { public long clientId; public string username = ""; public int totalWon; public int totalLost; public int biggestSingleWin; public int biggestSingleLoss; public string biggestWinGame = ""; public string biggestLossGame = ""; public int gamesPlayed; public int Net => totalWon - totalLost; } [Serializable] public class RunSaveBlob { public List<PlayerRunRecord> records = new List<PlayerRunRecord>(); } [Serializable] public class SessionEntry { public long clientId; public string username = ""; public int delta; } [Serializable] public class SyncBlob { public List<PlayerRunRecord> records = new List<PlayerRunRecord>(); public List<SessionEntry> session = new List<SessionEntry>(); } [BepInPlugin("jaredfreedman.LethalCasinoTracker", "LethalCasinoTracker", "1.1.0")] [BepInDependency("mrgrm7.LethalCasino", "1.1.0")] public class Plugin : BaseUnityPlugin { public const string Guid = "jaredfreedman.LethalCasinoTracker"; public static ManualLogSource Log; public static bool VerboseLogging; private static bool _initialized; private static ConfigEntry<bool> _verbose; private static ConfigEntry<bool> _hudEnabled; private static ConfigEntry<int> _hudMarginX; private static ConfigEntry<int> _hudMarginY; private static ConfigEntry<int> _hudWidth; private static ConfigEntry<int> _hudFont; private static ConfigEntry<bool> _summaryEnabled; private static ConfigEntry<float> _summaryDuration; private static ConfigEntry<bool> _sfxEnabled; private static ConfigEntry<float> _sfxVolume; private static ConfigEntry<bool> _chalkEnabled; private static ConfigEntry<float> _chalkX; private static ConfigEntry<float> _chalkY; private static ConfigEntry<float> _chalkZ; private static ConfigEntry<float> _chalkScale; private static ConfigEntry<float> _chalkYaw; private void Awake() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; BindConfig(); if (!_initialized) { _initialized = true; try { Harmony h = new Harmony("jaredfreedman.LethalCasinoTracker"); GameOverPatch.ApplyPatches(h); CasinoHooks.ApplyPatches(h); } catch (Exception ex) { Log.LogError((object)("Failed to apply Harmony patches: " + ex.Message)); } ((Component)this).gameObject.AddComponent<TrackerManager>(); ((Component)this).gameObject.AddComponent<SummaryScreenController>(); ((Component)this).gameObject.AddComponent<HUDController>(); ((Component)this).gameObject.AddComponent<ChalkboardController>(); Log.LogInfo((object)"LethalCasinoTracker 1.1.0 loaded."); } } private void BindConfig() { _verbose = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "VerboseLogging", false, "Log every tracked bet result (debugging)."); _hudEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("HUD", "Enabled", true, "Show the top-right session scoreboard while on a moon."); _hudMarginX = ((BaseUnityPlugin)this).Config.Bind<int>("HUD", "MarginX", 12, "Distance from the right edge of the screen, in pixels."); _hudMarginY = ((BaseUnityPlugin)this).Config.Bind<int>("HUD", "MarginY", 70, "Distance from the top edge of the screen, in pixels."); _hudWidth = ((BaseUnityPlugin)this).Config.Bind<int>("HUD", "Width", 270, "Panel width (reference px at 1080p)."); _hudFont = ((BaseUnityPlugin)this).Config.Bind<int>("HUD", "FontSize", 19, "Font size for HUD rows."); _summaryEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Summary", "Enabled", true, "Show the centered session recap on takeoff."); _summaryDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Summary", "HoldSeconds", 7f, "How long the recap stays fully visible (matches the vanilla performance report)."); _sfxEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Summary", "Sound", true, "Play a win/loss jingle with the recap."); _sfxVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Summary", "Volume", 0.5f, "Recap jingle volume (0-1)."); _chalkEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Chalkboard", "Enabled", true, "Spawn the physical casino records board near the casino."); _chalkX = ((BaseUnityPlugin)this).Config.Bind<float>("Chalkboard", "OffsetRight", 0f, "Board placement offset along the casino's right axis (m)."); _chalkY = ((BaseUnityPlugin)this).Config.Bind<float>("Chalkboard", "OffsetUp", 2.6f, "Board placement offset upward from the casino (m)."); _chalkZ = ((BaseUnityPlugin)this).Config.Bind<float>("Chalkboard", "OffsetForward", 4.5f, "Board placement offset in front of the casino (m)."); _chalkScale = ((BaseUnityPlugin)this).Config.Bind<float>("Chalkboard", "Scale", 0.0075f, "World scale of the board."); _chalkYaw = ((BaseUnityPlugin)this).Config.Bind<float>("Chalkboard", "Yaw", 180f, "Rotate the board to face the right way (degrees: try 0/90/180/270)."); VerboseLogging = _verbose.Value; } public static bool HudEnabled() { if (_hudEnabled != null) { return _hudEnabled.Value; } return true; } public static int HudMarginX() { if (_hudMarginX != null) { return _hudMarginX.Value; } return 12; } public static int HudMarginY() { if (_hudMarginY != null) { return _hudMarginY.Value; } return 70; } public static int HudWidth() { if (_hudWidth != null) { return _hudWidth.Value; } return 270; } public static int HudFontSize() { if (_hudFont != null) { return _hudFont.Value; } return 19; } public static bool SummaryEnabled() { if (_summaryEnabled != null) { return _summaryEnabled.Value; } return true; } public static float SummaryDuration() { if (_summaryDuration != null) { return _summaryDuration.Value; } return 7f; } public static bool SfxEnabled() { if (_sfxEnabled != null) { return _sfxEnabled.Value; } return true; } public static float SfxVolume() { if (_sfxVolume != null) { return _sfxVolume.Value; } return 0.5f; } public static bool ChalkboardEnabled() { if (_chalkEnabled != null) { return _chalkEnabled.Value; } return true; } public static float ChalkOffsetX() { if (_chalkX != null) { return _chalkX.Value; } return 0f; } public static float ChalkOffsetY() { if (_chalkY != null) { return _chalkY.Value; } return 2.6f; } public static float ChalkOffsetZ() { if (_chalkZ != null) { return _chalkZ.Value; } return 4.5f; } public static float ChalkScale() { if (_chalkScale != null) { return _chalkScale.Value; } return 0.0075f; } public static float ChalkYaw() { if (_chalkYaw != null) { return _chalkYaw.Value; } return 180f; } } public class SummaryScreenController : MonoBehaviour { private class Row { public string name; public bool has; public int delta; } private const float W = 700f; private const float Pad = 26f; private const float RowH = 40f; private static readonly Color RInk = new Color(0.95f, 0.5f, 0.36f); private static readonly Color RHead = new Color(1f, 0.36f, 0.24f); private static readonly Color RDim = new Color(0.74f, 0.34f, 0.27f); private static readonly Color RBg = new Color(0.11f, 0.015f, 0.015f, 0.94f); private static readonly Color RBorder = new Color(0.92f, 0.26f, 0.17f, 0.95f); private static readonly Color Up = new Color(0.55f, 0.95f, 0.5f); private static readonly Color Down = new Color(1f, 0.42f, 0.35f); private GameObject _root; private CanvasGroup _group; private RectTransform _panel; private RectTransform _inner; private TextMeshProUGUI _title; private TextMeshProUGUI _notes; private TextMeshProUGUI _collected; private TextMeshProUGUI _grade; private readonly List<GameObject> _rowBoxes = new List<GameObject>(); private bool _built; private Coroutine _co; private AudioSource _audio; private AudioClip _winClip; private AudioClip _loseClip; private AudioClip _neutralClip; public static SummaryScreenController Instance { get; private set; } private void Awake() { Instance = this; _audio = ((Component)this).gameObject.AddComponent<AudioSource>(); _audio.playOnAwake = false; _audio.spatialBlend = 0f; _audio.ignoreListenerPause = true; try { _winClip = MakeJingle("win", new float[4] { 523.25f, 659.25f, 783.99f, 1046.5f }, 0.13f, 0f); _loseClip = MakeJingle("lose", new float[4] { 440f, 392f, 349.23f, 293.66f }, 0.2f, -28f); _neutralClip = MakeJingle("neutral", new float[1] { 660f }, 0.09f, 0f); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Could not build recap audio: " + ex.Message)); } } private void OnDestroy() { if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } if ((Object)(object)_root != (Object)null) { Object.Destroy((Object)(object)_root); } } private static string Tag(string s, Color c) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) return "<color=#" + ColorUtility.ToHtmlStringRGB(c) + ">" + s + "</color>"; } private static string Signed(int v) { return ((v > 0) ? "+" : "") + v.ToString("N0"); } private TextMeshProUGUI Label(string name, float x, float y, float w, float h, float size, TextAlignmentOptions align, Color col) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) TextMeshProUGUI val = LCStyle.Text(((Component)_inner).transform, name, size, align, nativeGlow: false); RectTransform rectTransform = ((TMP_Text)val).rectTransform; rectTransform.anchorMin = new Vector2(0f, 1f); rectTransform.anchorMax = new Vector2(0f, 1f); rectTransform.pivot = new Vector2(0f, 1f); rectTransform.anchoredPosition = new Vector2(x, 0f - y); rectTransform.sizeDelta = new Vector2(w, h); ((Graphic)val).color = col; return val; } private void BuildUI() { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_0261: Unknown result type (might be due to invalid IL or missing references) //IL_02a5: Unknown result type (might be due to invalid IL or missing references) //IL_02d8: Unknown result type (might be due to invalid IL or missing references) //IL_02f9: Unknown result type (might be due to invalid IL or missing references) //IL_030f: Unknown result type (might be due to invalid IL or missing references) //IL_0325: Unknown result type (might be due to invalid IL or missing references) //IL_0338: Unknown result type (might be due to invalid IL or missing references) //IL_034b: Unknown result type (might be due to invalid IL or missing references) //IL_0394: Unknown result type (might be due to invalid IL or missing references) //IL_03aa: Unknown result type (might be due to invalid IL or missing references) //IL_03c0: Unknown result type (might be due to invalid IL or missing references) //IL_03d9: Unknown result type (might be due to invalid IL or missing references) //IL_03f2: Unknown result type (might be due to invalid IL or missing references) //IL_0402: Unknown result type (might be due to invalid IL or missing references) //IL_0417: Unknown result type (might be due to invalid IL or missing references) //IL_0438: Unknown result type (might be due to invalid IL or missing references) //IL_044e: Unknown result type (might be due to invalid IL or missing references) //IL_0464: Unknown result type (might be due to invalid IL or missing references) //IL_047a: Unknown result type (might be due to invalid IL or missing references) //IL_0493: Unknown result type (might be due to invalid IL or missing references) //IL_04dc: Unknown result type (might be due to invalid IL or missing references) //IL_04f2: Unknown result type (might be due to invalid IL or missing references) //IL_0508: Unknown result type (might be due to invalid IL or missing references) //IL_051e: Unknown result type (might be due to invalid IL or missing references) //IL_053d: Unknown result type (might be due to invalid IL or missing references) //IL_0586: Unknown result type (might be due to invalid IL or missing references) //IL_059c: Unknown result type (might be due to invalid IL or missing references) //IL_05b2: Unknown result type (might be due to invalid IL or missing references) //IL_05c8: Unknown result type (might be due to invalid IL or missing references) //IL_05de: Unknown result type (might be due to invalid IL or missing references) Canvas val = LCStyle.OverlayCanvas("LCCT_Recap", 950); _root = ((Component)val).gameObject; _group = _root.AddComponent<CanvasGroup>(); _group.alpha = 0f; Image val2 = LCStyle.Panel(_root.transform, new Color(0f, 0f, 0f, 0.6f)); LCStyle.Stretch(((Graphic)val2).rectTransform, 0f, 0f); Image val3 = LCStyle.Panel(_root.transform, RBorder); _panel = ((Graphic)val3).rectTransform; RectTransform panel = _panel; Vector2 anchorMin = (_panel.anchorMax = new Vector2(0.5f, 0.5f)); panel.anchorMin = anchorMin; _panel.pivot = new Vector2(0.5f, 0.5f); Image val5 = LCStyle.Panel(((Component)val3).transform, RBg); _inner = ((Graphic)val5).rectTransform; LCStyle.Stretch(_inner, 4f, 4f); RawImage val6 = LCStyle.Scanlines(((Component)_inner).transform, new Color(0.3f, 0f, 0f, 0.22f)); LCStyle.Stretch(((Graphic)val6).rectTransform, 0f, 0f); _title = Label("Title", 26f, 14f, 648f, 40f, 30f, (TextAlignmentOptions)258, RHead); ((TMP_Text)_title).fontStyle = (FontStyles)1; ((TMP_Text)_title).text = "CASINO PERFORMANCE REPORT"; Image val7 = LCStyle.Panel(((Component)_inner).transform, RBorder); RectTransform rectTransform = ((Graphic)val7).rectTransform; rectTransform.anchorMin = new Vector2(0f, 1f); rectTransform.anchorMax = new Vector2(0f, 1f); rectTransform.pivot = new Vector2(0f, 1f); rectTransform.anchoredPosition = new Vector2(26f, -58f); rectTransform.sizeDelta = new Vector2(648f, 3f); float num = 406f; ((TMP_Text)Label("EmpHead", 26f, 70f, num - 26f, 24f, 18f, (TextAlignmentOptions)257, RDim)).text = "EMPLOYEE"; ((TMP_Text)Label("NotesHead", num + 6f, 70f, 674f - num - 6f, 24f, 18f, (TextAlignmentOptions)257, RDim)).text = "NOTES"; float num2 = num + 6f; float num3 = 674f - num2; Image val8 = LCStyle.Box(((Component)_inner).transform, RBorder); RectTransform rectTransform2 = ((Graphic)val8).rectTransform; rectTransform2.anchorMin = new Vector2(0f, 1f); rectTransform2.anchorMax = new Vector2(0f, 1f); rectTransform2.pivot = new Vector2(0f, 1f); rectTransform2.anchoredPosition = new Vector2(num2, -98f); rectTransform2.sizeDelta = new Vector2(num3, 160f); _notes = LCStyle.Text(((Component)_inner).transform, "Notes", 17f, (TextAlignmentOptions)257, nativeGlow: false); RectTransform rectTransform3 = ((TMP_Text)_notes).rectTransform; rectTransform3.anchorMin = new Vector2(0f, 1f); rectTransform3.anchorMax = new Vector2(0f, 1f); rectTransform3.pivot = new Vector2(0f, 1f); rectTransform3.anchoredPosition = new Vector2(num2 + 12f, -110f); rectTransform3.sizeDelta = new Vector2(num3 - 24f, 160f); ((Graphic)_notes).color = RInk; Image val9 = LCStyle.Box(((Component)_inner).transform, RBorder); RectTransform rectTransform4 = ((Graphic)val9).rectTransform; rectTransform4.anchorMin = new Vector2(0f, 0f); rectTransform4.anchorMax = new Vector2(0f, 0f); rectTransform4.pivot = new Vector2(0f, 0f); rectTransform4.anchoredPosition = new Vector2(26f, 16f); rectTransform4.sizeDelta = new Vector2(num - 26f, 44f); _collected = LCStyle.Text(((Component)_inner).transform, "Collected", 20f, (TextAlignmentOptions)513, nativeGlow: false); RectTransform rectTransform5 = ((TMP_Text)_collected).rectTransform; rectTransform5.anchorMin = new Vector2(0f, 0f); rectTransform5.anchorMax = new Vector2(0f, 0f); rectTransform5.pivot = new Vector2(0f, 0f); rectTransform5.anchoredPosition = new Vector2(40f, 16f); rectTransform5.sizeDelta = new Vector2(num - 26f - 20f, 44f); _grade = LCStyle.Text(((Component)_inner).transform, "Grade", 30f, (TextAlignmentOptions)516, nativeGlow: false); RectTransform rectTransform6 = ((TMP_Text)_grade).rectTransform; rectTransform6.anchorMin = new Vector2(1f, 0f); rectTransform6.anchorMax = new Vector2(1f, 0f); rectTransform6.pivot = new Vector2(1f, 0f); rectTransform6.anchoredPosition = new Vector2(-26f, 16f); rectTransform6.sizeDelta = new Vector2(294f, 44f); ((TMP_Text)_grade).fontStyle = (FontStyles)1; _built = true; } public void Show(Dictionary<ulong, int> sessionSnapshot, int crewNet) { //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_022b: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_026e: Unknown result type (might be due to invalid IL or missing references) //IL_027e: Unknown result type (might be due to invalid IL or missing references) //IL_02bc: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.SummaryEnabled()) { if ((Object)(object)TrackerManager.Instance != (Object)null) { TrackerManager.Instance.EndSessionWipe(); } return; } if (!_built) { BuildUI(); } List<Row> list = BuildRows(sessionSnapshot); for (int i = 0; i < _rowBoxes.Count; i++) { if ((Object)(object)_rowBoxes[i] != (Object)null) { Object.Destroy((Object)(object)_rowBoxes[i]); } } _rowBoxes.Clear(); float num = 406f; float num2 = num - 26f; int num3 = Mathf.Min(list.Count, 6); for (int j = 0; j < num3; j++) { Row row = list[j]; Image val = LCStyle.Box(((Component)_inner).transform, RBorder); RectTransform rectTransform = ((Graphic)val).rectTransform; rectTransform.anchorMin = new Vector2(0f, 1f); rectTransform.anchorMax = new Vector2(0f, 1f); rectTransform.pivot = new Vector2(0f, 1f); rectTransform.anchoredPosition = new Vector2(26f, 0f - (98f + (float)j * 40f)); rectTransform.sizeDelta = new Vector2(num2, 34f); TextMeshProUGUI val2 = LCStyle.Text(((Component)val).transform, "Row", 19f, (TextAlignmentOptions)513, nativeGlow: false); LCStyle.Stretch(((TMP_Text)val2).rectTransform, 12f, 0f); string text = (row.has ? Tag(Signed(row.delta), (row.delta > 0) ? Up : Down) : Tag("--", RDim)); ((TMP_Text)val2).text = Tag(Trunc(row.name, 12), RInk) + "<pos=72%>" + text; _rowBoxes.Add(((Component)val).gameObject); } ((TMP_Text)_notes).text = BuildNotes(); Color c = ((crewNet > 0) ? Up : ((crewNet < 0) ? Down : RInk)); ((TMP_Text)_collected).text = Tag("COLLECTED: ", RDim) + Tag((crewNet == 0) ? "0" : Signed(crewNet), c); ((TMP_Text)_grade).text = Tag("GRADE ", RDim) + Tag(Grade(crewNet), RHead); float num4 = 98f + (float)Mathf.Max(num3, 3) * 40f + 76f; _panel.sizeDelta = new Vector2(700f, num4); PlayResultSound(crewNet); _root.SetActive(true); if (_co != null) { ((MonoBehaviour)this).StopCoroutine(_co); } _co = ((MonoBehaviour)this).StartCoroutine(Run()); } private static string BuildNotes() { //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) TrackerManager instance = TrackerManager.Instance; if ((Object)(object)instance == (Object)null) { return ""; } List<PlayerRunRecord> recordsSorted = instance.GetRecordsSorted(); PlayerRunRecord playerRunRecord = null; PlayerRunRecord playerRunRecord2 = null; for (int i = 0; i < recordsSorted.Count; i++) { if (playerRunRecord == null || recordsSorted[i].biggestSingleWin > playerRunRecord.biggestSingleWin) { playerRunRecord = recordsSorted[i]; } if (playerRunRecord2 == null || recordsSorted[i].biggestSingleLoss > playerRunRecord2.biggestSingleLoss) { playerRunRecord2 = recordsSorted[i]; } } StringBuilder stringBuilder = new StringBuilder(); if (playerRunRecord != null && playerRunRecord.biggestSingleWin > 0) { stringBuilder.Append(Tag("Top win: ", RDim)).Append(Tag(Trunc(playerRunRecord.username, 9) + " " + Signed(playerRunRecord.biggestSingleWin), Up)).Append('\n'); } else { stringBuilder.Append(Tag("Top win: --", RDim)).Append('\n'); } if (playerRunRecord2 != null && playerRunRecord2.biggestSingleLoss > 0) { stringBuilder.Append(Tag("Top loss: ", RDim)).Append(Tag(Trunc(playerRunRecord2.username, 9) + " -" + playerRunRecord2.biggestSingleLoss.ToString("N0"), Down)).Append('\n'); } else { stringBuilder.Append(Tag("Top loss: --", RDim)).Append('\n'); } stringBuilder.Append(Tag("Games: " + instance.TotalGames(), RDim)); return stringBuilder.ToString(); } private static string Grade(int crewNet) { if (crewNet >= 1500) { return "S"; } if (crewNet >= 400) { return "A"; } if (crewNet > 0) { return "B"; } if (crewNet == 0) { return "C"; } if (crewNet > -400) { return "D"; } return "F"; } private static List<Row> BuildRows(Dictionary<ulong, int> snap) { List<Row> list = new List<Row>(); StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance != (Object)null && instance.allPlayerScripts != null) { PlayerControllerB[] allPlayerScripts = instance.allPlayerScripts; foreach (PlayerControllerB val in allPlayerScripts) { if (!((Object)(object)val == (Object)null) && (val.isPlayerControlled || val.isPlayerDead)) { Row row = new Row(); row.name = (string.IsNullOrEmpty(val.playerUsername) ? ("Player " + val.playerClientId) : val.playerUsername); row.has = snap != null && snap.TryGetValue(val.playerClientId, out var value) && value != 0; row.delta = (row.has ? snap[val.playerClientId] : 0); list.Add(row); } } } return list; } private IEnumerator Run() { float fadeIn = 0.45f; float hold = Plugin.SummaryDuration(); float fadeOut = 0.8f; float t = 0f; while (t < fadeIn) { t += Time.unscaledDeltaTime; _group.alpha = Mathf.Clamp01(t / fadeIn); yield return null; } _group.alpha = 1f; yield return (object)new WaitForSecondsRealtime(hold); t = 0f; while (t < fadeOut) { t += Time.unscaledDeltaTime; _group.alpha = 1f - Mathf.Clamp01(t / fadeOut); yield return null; } _group.alpha = 0f; _root.SetActive(false); _co = null; if ((Object)(object)TrackerManager.Instance != (Object)null) { TrackerManager.Instance.EndSessionWipe(); } } private void PlayResultSound(int crewNet) { if (Plugin.SfxEnabled() && !((Object)(object)_audio == (Object)null)) { AudioClip val = ((crewNet > 0) ? _winClip : ((crewNet < 0) ? _loseClip : _neutralClip)); if ((Object)(object)val != (Object)null) { _audio.PlayOneShot(val, Plugin.SfxVolume()); } } } private static string Trunc(string s, int max) { if (string.IsNullOrEmpty(s)) { return ""; } if (s.Length > max) { return s.Substring(0, max); } return s; } private static AudioClip MakeJingle(string name, float[] freqs, float noteDur, float noteGlideHz) { int num = 44100; int num2 = Mathf.Max(1, (int)(noteDur * (float)num)); int num3 = num2 * freqs.Length; float[] array = new float[num3]; for (int i = 0; i < freqs.Length; i++) { float num4 = freqs[i]; for (int j = 0; j < num2; j++) { float num5 = (float)j / (float)num; float num6 = (float)j / (float)num2; float num7 = num4 + noteGlideHz * num6; float num8 = Mathf.Exp(-4f * num6); float num9 = Mathf.Clamp01(num6 * 40f); array[i * num2 + j] = Mathf.Sin((float)Math.PI * 2f * num7 * num5) * num8 * num9 * 0.28f; } } AudioClip val = AudioClip.Create("LCCT_" + name, num3, 1, num, false); val.SetData(array, 0); return val; } } public class TrackerManager : MonoBehaviour { private class Pending { public ulong id; public string name; public int delta; public CasinoGameType game; public float lastTouch; } public const string Es3File = "LethalCasinoTracker.es3"; private const string Es3KeyPrefix = "CasinoTracker_RunRecords_"; private const float FlushDelay = 0.85f; private readonly Dictionary<ulong, int> _sessionDeltas = new Dictionary<ulong, int>(); private readonly Dictionary<ulong, PlayerRunRecord> _runRecords = new Dictionary<ulong, PlayerRunRecord>(); private readonly Dictionary<string, Pending> _pending = new Dictionary<string, Pending>(); private bool _recordsLoaded; private bool _wasLanded; private bool _wasListening; public static TrackerManager Instance { get; private set; } public bool SessionActive { get; private set; } public bool RecordsDirty { get; set; } private void Awake() { Instance = this; } private void OnDestroy() { if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } public void RecordResolution(ulong id, string username, int delta, CasinoGameType game, int gameInstanceId) { if (delta != 0) { string text = (string.IsNullOrEmpty(username) ? ("Player " + id) : username); _sessionDeltas.TryGetValue(id, out var value); _sessionDeltas[id] = value + delta; string key = gameInstanceId + ":" + id; if (!_pending.TryGetValue(key, out var value2)) { value2 = new Pending(); value2.id = id; value2.name = text; value2.game = game; _pending[key] = value2; } value2.delta += delta; value2.game = game; value2.name = text; value2.lastTouch = Time.realtimeSinceStartup; if (Plugin.VerboseLogging) { Plugin.Log.LogInfo((object)("Delta " + delta + " -> " + text + " (" + CasinoGameNames.Display(game) + "), session net now " + _sessionDeltas[id])); } } } private void Update() { bool flag = (Object)(object)NetworkManager.Singleton != (Object)null && NetworkManager.Singleton.IsListening; if (_wasListening && !flag) { SoftResetForMenu(); } _wasListening = flag; StartOfRound instance = StartOfRound.Instance; bool flag2 = (Object)(object)instance != (Object)null && instance.shipHasLanded && !instance.shipIsLeaving; if (flag2 && !_wasLanded) { OnShipLanded(); } else if (!flag2 && _wasLanded) { OnShipLeaving(); } _wasLanded = flag2; if (_pending.Count > 0) { float realtimeSinceStartup = Time.realtimeSinceStartup; List<string> list = null; foreach (KeyValuePair<string, Pending> item in _pending) { if (realtimeSinceStartup - item.Value.lastTouch >= 0.85f) { if (list == null) { list = new List<string>(); } list.Add(item.Key); } } if (list != null) { for (int i = 0; i < list.Count; i++) { Pending p = _pending[list[i]]; _pending.Remove(list[i]); FinalizeRound(p); } } } NetworkSync.Tick(); } private void FinalizeRound(Pending p) { PlayerRunRecord orCreateRecord = GetOrCreateRecord(p.id, p.name); orCreateRecord.gamesPlayed++; if (p.delta > 0) { orCreateRecord.totalWon += p.delta; if (p.delta > orCreateRecord.biggestSingleWin) { orCreateRecord.biggestSingleWin = p.delta; orCreateRecord.biggestWinGame = CasinoGameNames.Display(p.game); } } else if (p.delta < 0) { int num = -p.delta; orCreateRecord.totalLost += num; if (num > orCreateRecord.biggestSingleLoss) { orCreateRecord.biggestSingleLoss = num; orCreateRecord.biggestLossGame = CasinoGameNames.Display(p.game); } } RecordsDirty = true; } private void FlushAllPendingNow() { if (_pending.Count != 0) { List<Pending> list = new List<Pending>(_pending.Values); _pending.Clear(); for (int i = 0; i < list.Count; i++) { FinalizeRound(list[i]); } } } private PlayerRunRecord GetOrCreateRecord(ulong id, string name) { if (!_runRecords.TryGetValue(id, out var value)) { value = new PlayerRunRecord(); value.clientId = (long)id; value.username = name; _runRecords[id] = value; } else if (!string.IsNullOrEmpty(name)) { value.username = name; } return value; } public void OnShipLanded() { SessionActive = true; if (IsServer()) { if (!_recordsLoaded) { LoadRecords(); } _recordsLoaded = true; } else { NetworkSync.RequestResync(); } RecordsDirty = true; } public void OnShipLeaving() { FlushAllPendingNow(); if (IsServer()) { SaveRecords(); } bool flag = IsGordion(); Dictionary<ulong, int> sessionSnapshot = new Dictionary<ulong, int>(_sessionDeltas); SessionActive = false; SummaryScreenController instance = SummaryScreenController.Instance; if (flag && (Object)(object)instance != (Object)null) { instance.Show(sessionSnapshot, CrewNet()); } else { EndSessionWipe(); } } public static bool IsGordion() { StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance.currentLevel == (Object)null || string.IsNullOrEmpty(instance.currentLevel.PlanetName)) { return false; } return instance.currentLevel.PlanetName.IndexOf("Gordion", StringComparison.OrdinalIgnoreCase) >= 0; } public void EndSessionWipe() { _sessionDeltas.Clear(); CasinoHooks.ResetValueTracking(); RecordsDirty = true; } private void SoftResetForMenu() { _sessionDeltas.Clear(); _runRecords.Clear(); _pending.Clear(); SessionActive = false; _wasLanded = false; _recordsLoaded = false; RecordsDirty = true; } public void EliminateRun() { _sessionDeltas.Clear(); _runRecords.Clear(); _pending.Clear(); CasinoHooks.ResetValueTracking(); SessionActive = false; RecordsDirty = true; if (IsServer()) { DeleteRecordsForSlot(SlotId()); } Plugin.Log.LogInfo((object)"Casino records wiped (crew eliminated)."); } public void OnSaveFileDeleted(string filePath) { string text = "default"; try { if (!string.IsNullOrEmpty(filePath)) { text = Path.GetFileNameWithoutExtension(filePath); } } catch { } DeleteRecordsForSlot(text); if (text == SlotId()) { _sessionDeltas.Clear(); _runRecords.Clear(); _pending.Clear(); CasinoHooks.ResetValueTracking(); _recordsLoaded = false; RecordsDirty = true; } Plugin.Log.LogInfo((object)("Casino records wiped for deleted save '" + text + "'.")); } private static string SlotId() { try { if ((Object)(object)GameNetworkManager.Instance != (Object)null && !string.IsNullOrEmpty(GameNetworkManager.Instance.currentSaveFileName)) { return Path.GetFileNameWithoutExtension(GameNetworkManager.Instance.currentSaveFileName); } } catch { } return "default"; } private static string KeyFor(string slot) { return "CasinoTracker_RunRecords_" + slot; } private void DeleteRecordsForSlot(string slot) { try { string text = KeyFor(slot); if (ES3.KeyExists(text, "LethalCasinoTracker.es3")) { ES3.DeleteKey(text, "LethalCasinoTracker.es3"); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("ES3 delete failed: " + ex.Message)); } } public void SaveRecords() { try { RunSaveBlob runSaveBlob = new RunSaveBlob(); foreach (PlayerRunRecord value in _runRecords.Values) { runSaveBlob.records.Add(value); } string text = JsonUtility.ToJson((object)runSaveBlob); ES3.Save<string>(KeyFor(SlotId()), text, "LethalCasinoTracker.es3"); if (Plugin.VerboseLogging) { Plugin.Log.LogInfo((object)("Saved " + runSaveBlob.records.Count + " run records for slot '" + SlotId() + "'.")); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Failed to save run records: " + ex.Message)); } } public void LoadRecords() { try { _runRecords.Clear(); string text = KeyFor(SlotId()); if (!ES3.KeyExists(text, "LethalCasinoTracker.es3")) { Plugin.Log.LogInfo((object)("No casino records for slot '" + SlotId() + "'.")); RecordsDirty = true; return; } string text2 = ES3.Load<string>(text, "LethalCasinoTracker.es3", ""); if (string.IsNullOrEmpty(text2)) { RecordsDirty = true; return; } RunSaveBlob runSaveBlob = JsonUtility.FromJson<RunSaveBlob>(text2); if (runSaveBlob != null && runSaveBlob.records != null) { for (int i = 0; i < runSaveBlob.records.Count; i++) { PlayerRunRecord playerRunRecord = runSaveBlob.records[i]; if (playerRunRecord != null) { _runRecords[(ulong)playerRunRecord.clientId] = playerRunRecord; } } } Plugin.Log.LogInfo((object)("Loaded " + _runRecords.Count + " run records for slot '" + SlotId() + "'.")); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Failed to load run records: " + ex.Message)); } RecordsDirty = true; } public SyncBlob BuildSyncBlob() { SyncBlob syncBlob = new SyncBlob(); foreach (PlayerRunRecord value2 in _runRecords.Values) { syncBlob.records.Add(value2); } foreach (KeyValuePair<ulong, int> sessionDelta in _sessionDeltas) { SessionEntry sessionEntry = new SessionEntry(); sessionEntry.clientId = (long)sessionDelta.Key; sessionEntry.delta = sessionDelta.Value; sessionEntry.username = (_runRecords.TryGetValue(sessionDelta.Key, out var value) ? value.username : ""); syncBlob.session.Add(sessionEntry); } return syncBlob; } public void ApplySyncBlob(SyncBlob b) { if (b == null) { return; } _runRecords.Clear(); if (b.records != null) { for (int i = 0; i < b.records.Count; i++) { PlayerRunRecord playerRunRecord = b.records[i]; if (playerRunRecord != null) { _runRecords[(ulong)playerRunRecord.clientId] = playerRunRecord; } } } _sessionDeltas.Clear(); if (b.session != null) { for (int j = 0; j < b.session.Count; j++) { SessionEntry sessionEntry = b.session[j]; if (sessionEntry != null) { _sessionDeltas[(ulong)sessionEntry.clientId] = sessionEntry.delta; } } } _recordsLoaded = true; RecordsDirty = true; Plugin.Log.LogInfo((object)("Applied tracker state from host (" + _runRecords.Count + " records).")); } public bool TryGetSessionDelta(ulong id, out int delta) { return _sessionDeltas.TryGetValue(id, out delta); } public int CrewNet() { int num = 0; foreach (int value in _sessionDeltas.Values) { num += value; } return num; } public List<PlayerRunRecord> GetRecordsSorted() { List<PlayerRunRecord> list = new List<PlayerRunRecord>(_runRecords.Values); list.Sort((PlayerRunRecord a, PlayerRunRecord b) => b.Net.CompareTo(a.Net)); return list; } public int TotalGames() { int num = 0; foreach (PlayerRunRecord value in _runRecords.Values) { num += value.gamesPlayed; } return num; } public static bool IsServer() { if ((Object)(object)NetworkManager.Singleton != (Object)null) { return NetworkManager.Singleton.IsServer; } return false; } } } namespace LethalCasinoTracker.Patches { public static class GameOverPatch { public static void OnPlayersFired() { if ((Object)(object)TrackerManager.Instance != (Object)null) { Plugin.Log.LogInfo((object)"Crew eliminated by the company — wiping casino records."); TrackerManager.Instance.EliminateRun(); } } public static void OnSaveFileDeleted(string filePath) { if ((Object)(object)TrackerManager.Instance != (Object)null) { TrackerManager.Instance.OnSaveFileDeleted(filePath); } } public static void ApplyPatches(Harmony h) { //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Expected O, but got Unknown Patch(h, AccessTools.Method(typeof(StartOfRound), "FirePlayersAfterDeadlineClientRpc", (Type[])null, (Type[])null), AccessTools.Method(typeof(GameOverPatch), "OnPlayersFired", (Type[])null, (Type[])null), "StartOfRound.FirePlayersAfterDeadlineClientRpc"); MethodInfo methodInfo = AccessTools.Method(typeof(GameOverPatch), "OnSaveFileDeleted", (Type[])null, (Type[])null); try { MethodInfo[] methods = typeof(ES3).GetMethods(BindingFlags.Static | BindingFlags.Public); int num = 0; for (int i = 0; i < methods.Length; i++) { if (methods[i].Name != "DeleteFile") { continue; } ParameterInfo[] parameters = methods[i].GetParameters(); if (parameters.Length >= 1 && parameters[0].ParameterType == typeof(string)) { try { h.Patch((MethodBase)methods[i], (HarmonyMethod)null, new HarmonyMethod(methodInfo), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); num++; } catch (Exception ex) { Plugin.Log.LogWarning((object)("ES3.DeleteFile patch failed: " + ex.Message)); } } } Plugin.Log.LogInfo((object)("Patched ES3.DeleteFile (" + num + " overloads).")); } catch (Exception ex2) { Plugin.Log.LogError((object)("Could not patch ES3.DeleteFile: " + ex2.Message)); } } private static void Patch(Harmony h, MethodInfo orig, MethodInfo postfix, string label) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown try { if (orig == null) { Plugin.Log.LogWarning((object)("Patch target not found: " + label)); return; } h.Patch((MethodBase)orig, (HarmonyMethod)null, new HarmonyMethod(postfix), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Plugin.Log.LogInfo((object)("Patched " + label)); } catch (Exception ex) { Plugin.Log.LogError((object)("Failed to patch " + label + ": " + ex.Message)); } } } }