using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using Extensions;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Mirror;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyVersion("0.0.0.0")]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
}
namespace VapuStats
{
internal static class DayStatsCalculator
{
public static List<PlayerDaySummary> CalculateAllPlayersStats(PayoutTracker tracker, List<PlayerProfile> players)
{
//IL_016d: Unknown result type (might be due to invalid IL or missing references)
//IL_018a: Unknown result type (might be due to invalid IL or missing references)
List<PlayerDaySummary> list = new List<PlayerDaySummary>();
foreach (PlayerProfile player in players)
{
List<PayoutRecord> playerRecords = tracker.GetPlayerRecords(player);
PlayerDaySummary playerDaySummary = new PlayerDaySummary
{
playerName = player.playerName
};
int num = 0;
int num2 = 0;
foreach (PayoutRecord item in playerRecords.OrderBy((PayoutRecord r) => r.timestamp))
{
if (item.bet == 0L && item.payout == 0L)
{
continue;
}
playerDaySummary.totalBet += item.bet;
playerDaySummary.totalPayout += item.payout;
playerDaySummary.totalGames++;
if (item.isWin)
{
playerDaySummary.wins++;
}
if (item.isLoss)
{
playerDaySummary.losses++;
}
if (!item.isWin && !item.isLoss)
{
playerDaySummary.pushes++;
}
if (item.isWin)
{
num++;
num2 = 0;
if (num > playerDaySummary.longestWinStreak)
{
playerDaySummary.longestWinStreak = num;
}
}
else if (item.isLoss)
{
num2++;
num = 0;
if (num2 > playerDaySummary.longestLossStreak)
{
playerDaySummary.longestLossStreak = num2;
}
}
if (!playerDaySummary.byGameType.TryGetValue(item.gameType, out GameTypeStats value))
{
value = new GameTypeStats();
playerDaySummary.byGameType[item.gameType] = value;
}
value.totalBet += item.bet;
value.totalPayout += item.payout;
value.gameCount++;
if (item.isWin)
{
value.winCount++;
long num3 = item.payout - item.bet;
if (num3 > value.biggestWin)
{
value.biggestWin = num3;
}
}
}
list.Add(playerDaySummary);
}
return list.OrderByDescending((PlayerDaySummary s) => s.NetProfit).ToList();
}
public static List<PlayerDaySummary> CalculateFromRecords(IEnumerable<RunRecord> records)
{
//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
Dictionary<string, PlayerDaySummary> dictionary = new Dictionary<string, PlayerDaySummary>();
Dictionary<string, (int, int)> dictionary2 = new Dictionary<string, (int, int)>();
foreach (RunRecord item in records.OrderBy((RunRecord r) => r.timestamp))
{
if (item.bet == 0L && item.payout == 0L)
{
continue;
}
string text = item.playerName ?? "";
if (!dictionary.TryGetValue(text, out var value))
{
value = (dictionary[text] = new PlayerDaySummary
{
playerName = text
});
dictionary2[text] = (0, 0);
}
value.totalBet += item.bet;
value.totalPayout += item.payout;
value.totalGames++;
if (item.isWin)
{
value.wins++;
}
if (item.isLoss)
{
value.losses++;
}
if (!item.isWin && !item.isLoss)
{
value.pushes++;
}
var (num, num2) = dictionary2[text];
if (item.isWin)
{
num++;
num2 = 0;
if (num > value.longestWinStreak)
{
value.longestWinStreak = num;
}
}
else if (item.isLoss)
{
num2++;
num = 0;
if (num2 > value.longestLossStreak)
{
value.longestLossStreak = num2;
}
}
dictionary2[text] = (num, num2);
CasinoGameType key = (CasinoGameType)item.gameType;
if (!value.byGameType.TryGetValue(key, out GameTypeStats value2))
{
value2 = new GameTypeStats();
value.byGameType[key] = value2;
}
value2.totalBet += item.bet;
value2.totalPayout += item.payout;
value2.gameCount++;
if (item.isWin)
{
value2.winCount++;
long num3 = item.payout - item.bet;
if (num3 > value2.biggestWin)
{
value2.biggestWin = num3;
}
}
}
return dictionary.Values.OrderByDescending((PlayerDaySummary s) => s.NetProfit).ToList();
}
}
internal class FallbackInputHandler : MonoBehaviour
{
private void Update()
{
Keyboard current = Keyboard.current;
if (current != null && (((ButtonControl)current.enterKey).wasPressedThisFrame || ((ButtonControl)current.numpadEnterKey).wasPressedThisFrame || ((ButtonControl)current.spaceKey).wasPressedThisFrame))
{
FallbackRunOverModal.Close();
}
}
}
internal static class FallbackRunOverModal
{
private static GameObject? _currentRoot;
private static bool _savedCursorVisible;
private static CursorLockMode _savedCursorLock;
public static bool IsShowing => (Object)(object)_currentRoot != (Object)null;
public static void Show(List<PlayerDaySummary> stats)
{
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: Expected O, but got Unknown
//IL_0094: Unknown result type (might be due to invalid IL or missing references)
//IL_00a9: 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_00c0: Unknown result type (might be due to invalid IL or missing references)
//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
//IL_00dd: 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_0116: Unknown result type (might be due to invalid IL or missing references)
//IL_012b: Unknown result type (might be due to invalid IL or missing references)
//IL_0130: 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)
//IL_0153: Unknown result type (might be due to invalid IL or missing references)
//IL_0168: Unknown result type (might be due to invalid IL or missing references)
//IL_017d: Unknown result type (might be due to invalid IL or missing references)
//IL_0192: Unknown result type (might be due to invalid IL or missing references)
//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
//IL_020f: Unknown result type (might be due to invalid IL or missing references)
//IL_021e: Unknown result type (might be due to invalid IL or missing references)
//IL_022d: Unknown result type (might be due to invalid IL or missing references)
//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
//IL_0308: Unknown result type (might be due to invalid IL or missing references)
//IL_030f: Expected O, but got Unknown
//IL_0334: Unknown result type (might be due to invalid IL or missing references)
//IL_0349: Unknown result type (might be due to invalid IL or missing references)
//IL_035e: Unknown result type (might be due to invalid IL or missing references)
//IL_0373: Unknown result type (might be due to invalid IL or missing references)
//IL_0387: Unknown result type (might be due to invalid IL or missing references)
//IL_03bc: Unknown result type (might be due to invalid IL or missing references)
//IL_03d6: Unknown result type (might be due to invalid IL or missing references)
//IL_03db: Unknown result type (might be due to invalid IL or missing references)
//IL_03f3: Unknown result type (might be due to invalid IL or missing references)
//IL_0413: Unknown result type (might be due to invalid IL or missing references)
//IL_0433: Unknown result type (might be due to invalid IL or missing references)
//IL_043e: Unknown result type (might be due to invalid IL or missing references)
//IL_0451: Unknown result type (might be due to invalid IL or missing references)
//IL_045b: Expected O, but got Unknown
//IL_0460: Unknown result type (might be due to invalid IL or missing references)
//IL_0465: Unknown result type (might be due to invalid IL or missing references)
//IL_0478: Unknown result type (might be due to invalid IL or missing references)
//IL_047f: Unknown result type (might be due to invalid IL or missing references)
//IL_048a: Unknown result type (might be due to invalid IL or missing references)
//IL_0495: Unknown result type (might be due to invalid IL or missing references)
//IL_049f: Unknown result type (might be due to invalid IL or missing references)
//IL_04db: Unknown result type (might be due to invalid IL or missing references)
//IL_0264: Unknown result type (might be due to invalid IL or missing references)
//IL_0269: Unknown result type (might be due to invalid IL or missing references)
//IL_026c: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)_currentRoot != (Object)null)
{
Plugin.Log.LogInfo((object)"[VapuStats] Fallback already showing, ignoring duplicate");
return;
}
TMP_FontAsset font = PanelHelpers.GetFont((MonoBehaviour?)(object)Plugin.Instance);
_savedCursorVisible = Cursor.visible;
_savedCursorLock = Cursor.lockState;
Cursor.visible = true;
Cursor.lockState = (CursorLockMode)0;
GameObject val = new GameObject("VapuStats_FallbackModal");
Object.DontDestroyOnLoad((Object)(object)val);
val.AddComponent<FallbackInputHandler>();
Canvas obj = val.AddComponent<Canvas>();
obj.renderMode = (RenderMode)0;
obj.sortingOrder = 32000;
val.AddComponent<CanvasScaler>().uiScaleMode = (ScaleMode)1;
val.GetComponent<CanvasScaler>().referenceResolution = new Vector2(1920f, 1080f);
val.AddComponent<GraphicRaycaster>();
GameObject val2 = new GameObject("Backdrop");
val2.transform.SetParent(val.transform, false);
RectTransform obj2 = val2.AddComponent<RectTransform>();
obj2.anchorMin = Vector2.zero;
obj2.anchorMax = Vector2.one;
obj2.offsetMin = Vector2.zero;
obj2.offsetMax = Vector2.zero;
Image obj3 = val2.AddComponent<Image>();
obj3.sprite = StatsModal.GetWhiteSprite();
((Graphic)obj3).color = new Color(0f, 0f, 0f, 0.92f);
((Graphic)obj3).raycastTarget = true;
GameObject val3 = new GameObject("Title");
val3.transform.SetParent(val.transform, false);
RectTransform obj4 = val3.AddComponent<RectTransform>();
obj4.anchorMin = new Vector2(0.5f, 1f);
obj4.anchorMax = new Vector2(0.5f, 1f);
obj4.pivot = new Vector2(0.5f, 1f);
obj4.anchoredPosition = new Vector2(0f, -50f);
obj4.sizeDelta = new Vector2(800f, 70f);
TextMeshProUGUI val4 = val3.AddComponent<TextMeshProUGUI>();
if ((Object)(object)font != (Object)null)
{
((TMP_Text)val4).font = font;
}
((TMP_Text)val4).text = "RUN OVER";
((TMP_Text)val4).fontSize = 44f;
((Graphic)val4).color = Color.white;
((TMP_Text)val4).alignment = (TextAlignmentOptions)514;
((Graphic)val4).raycastTarget = false;
GameTypePanel.Build(val.transform, stats, (MonoBehaviour)(object)Plugin.Instance, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -140f));
HashSet<CasinoGameType> hashSet = new HashSet<CasinoGameType>();
foreach (PlayerDaySummary stat in stats)
{
foreach (CasinoGameType key in stat.byGameType.Keys)
{
hashSet.Add(key);
}
}
float num = (float)hashSet.Count * 26f + 40f;
PlayerStatsPanel.Build(val.transform, stats, (MonoBehaviour)(object)Plugin.Instance, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -140f - num - 30f));
GameObject val5 = new GameObject("ContinueButton");
val5.transform.SetParent(val.transform, false);
RectTransform obj5 = val5.AddComponent<RectTransform>();
obj5.anchorMin = new Vector2(0.5f, 0f);
obj5.anchorMax = new Vector2(0.5f, 0f);
obj5.pivot = new Vector2(0.5f, 0f);
obj5.anchoredPosition = new Vector2(0f, 50f);
obj5.sizeDelta = new Vector2(240f, 60f);
Image val6 = val5.AddComponent<Image>();
val6.sprite = StatsModal.GetWhiteSprite();
((Graphic)val6).color = new Color(0.2f, 0.55f, 0.3f, 1f);
Button obj6 = val5.AddComponent<Button>();
((Selectable)obj6).targetGraphic = (Graphic)(object)val6;
ColorBlock colors = ((Selectable)obj6).colors;
((ColorBlock)(ref colors)).normalColor = new Color(0.2f, 0.55f, 0.3f, 1f);
((ColorBlock)(ref colors)).highlightedColor = new Color(0.3f, 0.75f, 0.4f, 1f);
((ColorBlock)(ref colors)).pressedColor = new Color(0.15f, 0.4f, 0.2f, 1f);
((Selectable)obj6).colors = colors;
((UnityEvent)obj6.onClick).AddListener(new UnityAction(Close));
GameObject val7 = new GameObject("Label");
val7.transform.SetParent(val5.transform, false);
RectTransform obj7 = val7.AddComponent<RectTransform>();
obj7.anchorMin = Vector2.zero;
obj7.anchorMax = Vector2.one;
obj7.sizeDelta = Vector2.zero;
obj7.anchoredPosition = Vector2.zero;
TextMeshProUGUI val8 = val7.AddComponent<TextMeshProUGUI>();
if ((Object)(object)font != (Object)null)
{
((TMP_Text)val8).font = font;
}
((TMP_Text)val8).text = "CONTINUE (ENTER)";
((TMP_Text)val8).fontSize = 22f;
((Graphic)val8).color = Color.white;
((TMP_Text)val8).alignment = (TextAlignmentOptions)514;
((Graphic)val8).raycastTarget = false;
CanvasGroup[] componentsInChildren = val.GetComponentsInChildren<CanvasGroup>();
for (int i = 0; i < componentsInChildren.Length; i++)
{
componentsInChildren[i].alpha = 1f;
}
Canvas.ForceUpdateCanvases();
_currentRoot = val;
Plugin.Log.LogInfo((object)"[VapuStats] Fallback modal shown");
}
public static void Close()
{
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)_currentRoot != (Object)null)
{
Object.Destroy((Object)(object)_currentRoot);
_currentRoot = null;
Cursor.visible = _savedCursorVisible;
Cursor.lockState = _savedCursorLock;
Plugin.Log.LogInfo((object)"[VapuStats] Fallback modal dismissed");
}
}
}
internal static class GameTypePanel
{
private static readonly float[] ColX = new float[4] { -160f, -50f, 30f, 150f };
private static readonly float[] ColW = new float[4] { 130f, 60f, 70f, 200f };
private const float PanelWidth = 540f;
internal static GameObject Build(Transform parent, List<PlayerDaySummary> stats, MonoBehaviour instance, Vector2 anchorMinMax, Vector2 pivot, Vector2 anchoredPosition)
{
//IL_0150: Unknown result type (might be due to invalid IL or missing references)
//IL_0156: Expected O, but got Unknown
//IL_016a: Unknown result type (might be due to invalid IL or missing references)
//IL_0171: Unknown result type (might be due to invalid IL or missing references)
//IL_0178: Unknown result type (might be due to invalid IL or missing references)
//IL_0180: Unknown result type (might be due to invalid IL or missing references)
//IL_019f: 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_01ce: Unknown result type (might be due to invalid IL or missing references)
//IL_01e0: 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_01f2: Unknown result type (might be due to invalid IL or missing references)
//IL_0207: Unknown result type (might be due to invalid IL or missing references)
//IL_0212: Unknown result type (might be due to invalid IL or missing references)
//IL_0227: Unknown result type (might be due to invalid IL or missing references)
//IL_023b: Unknown result type (might be due to invalid IL or missing references)
//IL_0245: Unknown result type (might be due to invalid IL or missing references)
//IL_026b: 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_02da: Unknown result type (might be due to invalid IL or missing references)
//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
//IL_02ec: Unknown result type (might be due to invalid IL or missing references)
//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
//IL_0042: 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_034c: Unknown result type (might be due to invalid IL or missing references)
//IL_0351: Unknown result type (might be due to invalid IL or missing references)
//IL_0387: Unknown result type (might be due to invalid IL or missing references)
//IL_0389: Unknown result type (might be due to invalid IL or missing references)
//IL_0383: Unknown result type (might be due to invalid IL or missing references)
//IL_037c: Unknown result type (might be due to invalid IL or missing references)
//IL_03ac: Unknown result type (might be due to invalid IL or missing references)
//IL_03ae: Unknown result type (might be due to invalid IL or missing references)
//IL_03a8: Unknown result type (might be due to invalid IL or missing references)
//IL_03a1: Unknown result type (might be due to invalid IL or missing references)
//IL_0477: Unknown result type (might be due to invalid IL or missing references)
//IL_047c: Unknown result type (might be due to invalid IL or missing references)
//IL_0483: Unknown result type (might be due to invalid IL or missing references)
//IL_0488: Unknown result type (might be due to invalid IL or missing references)
//IL_048f: Unknown result type (might be due to invalid IL or missing references)
//IL_0491: Unknown result type (might be due to invalid IL or missing references)
//IL_0498: Unknown result type (might be due to invalid IL or missing references)
//IL_049a: Unknown result type (might be due to invalid IL or missing references)
TMP_FontAsset font = PanelHelpers.GetFont(instance);
Dictionary<CasinoGameType, (int, long, string, long)> dictionary = new Dictionary<CasinoGameType, (int, long, string, long)>();
foreach (PlayerDaySummary stat in stats)
{
foreach (KeyValuePair<CasinoGameType, GameTypeStats> item in stat.byGameType)
{
if (!dictionary.TryGetValue(item.Key, out var value))
{
value = (0, 0L, stat.playerName, long.MinValue);
}
bool flag = item.Value.biggestWin > value.Item4;
dictionary[item.Key] = (value.Item1 + item.Value.gameCount, value.Item2 + item.Value.NetProfit, flag ? stat.playerName : value.Item3, flag ? item.Value.biggestWin : value.Item4);
}
}
List<KeyValuePair<CasinoGameType, (int, long, string, long)>> list = dictionary.OrderByDescending<KeyValuePair<CasinoGameType, (int, long, string, long)>, int>((KeyValuePair<CasinoGameType, (int plays, long groupNet, string biggestWinPlayer, long biggestWin)> kvp) => kvp.Value.plays).ToList();
GameObject val = new GameObject("GWYF_GameTypePanel");
val.transform.SetParent(parent, false);
RectTransform obj = val.AddComponent<RectTransform>();
obj.anchorMin = anchorMinMax;
obj.anchorMax = anchorMinMax;
obj.pivot = pivot;
obj.anchoredPosition = anchoredPosition;
obj.sizeDelta = new Vector2(540f, (float)list.Count * 26f + 40f);
val.AddComponent<CanvasGroup>().alpha = 0f;
val.transform.SetAsLastSibling();
GameObject val2 = new GameObject("Background");
val2.transform.SetParent(val.transform, false);
RectTransform obj2 = val2.AddComponent<RectTransform>();
obj2.anchorMin = Vector2.zero;
obj2.anchorMax = Vector2.one;
obj2.pivot = new Vector2(0.5f, 0.5f);
obj2.anchoredPosition = Vector2.zero;
obj2.offsetMin = new Vector2(-12f, -12f);
obj2.offsetMax = new Vector2(12f, 12f);
Image obj3 = val2.AddComponent<Image>();
obj3.sprite = StatsModal.GetWhiteSprite();
((Graphic)obj3).color = new Color(0.13f, 0.13f, 0.16f, 0.97f);
((Graphic)obj3).raycastTarget = false;
val2.transform.SetAsFirstSibling();
Color val3 = default(Color);
((Color)(ref val3))..ctor(0.75f, 0.75f, 0.75f);
float num = -20f;
PanelHelpers.AddRow(val.transform, num, new string[4] { "GAME", "# HANDS", "GROUP NET", "BIGGEST WIN" }, (Color[])(object)new Color[4] { val3, val3, val3, val3 }, 11, font, ColX, ColW);
Color val4 = default(Color);
((Color)(ref val4))..ctor(0.4f, 1f, 0.4f);
Color val5 = default(Color);
((Color)(ref val5))..ctor(1f, 0.4f, 0.4f);
for (int i = 0; i < list.Count; i++)
{
CasinoGameType key = list[i].Key;
(int, long, string, long) value2 = list[i].Value;
Color val6 = ((value2.Item2 > 0) ? val4 : ((value2.Item2 < 0) ? val5 : Color.white));
Color val7 = ((value2.Item4 > 0) ? val4 : ((value2.Item4 < 0) ? val5 : Color.white));
string text = ((value2.Item3.Length > 12) ? (value2.Item3.Substring(0, 11) + "…") : value2.Item3);
string text2 = ((value2.Item4 == long.MinValue) ? "-" : (text + " (" + MoneyFormatter.FormatWithDollar(value2.Item4, false) + ")"));
PanelHelpers.AddRow(val.transform, num - 30f - (float)i * 26f, new string[4]
{
((object)(CasinoGameType)(ref key)).ToString(),
value2.Item1.ToString(),
MoneyFormatter.FormatWithDollar(value2.Item2, false),
text2
}, (Color[])(object)new Color[4]
{
Color.white,
Color.white,
val6,
val7
}, 15, font, ColX, ColW);
}
Canvas.ForceUpdateCanvases();
return val;
}
}
public class GameTypeStats
{
public long totalBet { get; set; }
public long totalPayout { get; set; }
public int gameCount { get; set; }
public int winCount { get; set; }
public long biggestWin { get; set; }
public long NetProfit => totalPayout - totalBet;
public float WinPercentage
{
get
{
if (gameCount > 0)
{
return (float)winCount * 100f / (float)gameCount;
}
return 0f;
}
}
}
internal static class PanelHelpers
{
private static TMP_FontAsset? _font;
internal static TMP_FontAsset? GetFont(MonoBehaviour? source = null)
{
if ((Object)(object)_font != (Object)null)
{
return _font;
}
if ((Object)(object)source != (Object)null)
{
object? obj = ((object)source).GetType().GetField("titleText", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(source);
TextMeshProUGUI val = (TextMeshProUGUI)((obj is TextMeshProUGUI) ? obj : null);
if (val != null)
{
_font = ((TMP_Text)val).font;
}
}
if ((Object)(object)_font == (Object)null)
{
TextMeshProUGUI val2 = Object.FindFirstObjectByType<TextMeshProUGUI>();
if ((Object)(object)val2 != (Object)null)
{
_font = ((TMP_Text)val2).font;
Plugin.Log.LogInfo((object)("[CustomStats] Font borrowed from '" + ((Object)((Component)val2).gameObject).name + "'"));
}
}
if ((Object)(object)_font == (Object)null)
{
Plugin.Log.LogWarning((object)"[CustomStats] Could not find any TMP font — text will be invisible");
}
else
{
Plugin.Log.LogInfo((object)("[CustomStats] Font resolved: " + ((Object)_font).name));
}
return _font;
}
internal static void AddRow(Transform parent, float y, string[] vals, Color[] colors, int fontSize, TMP_FontAsset? font, float[] colX, float[] colW)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_009a: Unknown result type (might be due to invalid IL or missing references)
//IL_00af: Unknown result type (might be due to invalid IL or missing references)
//IL_00c4: 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_00e7: Unknown result type (might be due to invalid IL or missing references)
for (int i = 0; i < vals.Length; i++)
{
GameObject val = new GameObject($"Cell_{y}_{i}");
val.transform.SetParent(parent, false);
TextMeshProUGUI val2 = val.AddComponent<TextMeshProUGUI>();
if ((Object)(object)font != (Object)null)
{
((TMP_Text)val2).font = font;
}
((TMP_Text)val2).text = vals[i];
((TMP_Text)val2).fontSize = fontSize;
((Graphic)val2).color = colors[i];
((TMP_Text)val2).alignment = (TextAlignmentOptions)((i == 0) ? 4097 : 4098);
((TMP_Text)val2).overflowMode = (TextOverflowModes)0;
((TMP_Text)val2).textWrappingMode = (TextWrappingModes)0;
RectTransform component = val.GetComponent<RectTransform>();
component.anchorMin = new Vector2(0.5f, 1f);
component.anchorMax = new Vector2(0.5f, 1f);
component.pivot = new Vector2(0.5f, 1f);
component.anchoredPosition = new Vector2(colX[i], y);
component.sizeDelta = new Vector2(colW[i], 28f);
}
}
}
[HarmonyPatch(typeof(DaySummaryUI), "Show")]
internal static class Patch_DaySummaryUI_Show
{
private static void Postfix(DaySummaryUI __instance)
{
((MonoBehaviour)__instance).StartCoroutine(ShowStatsAfterGraph(__instance));
}
private static IEnumerator ShowStatsAfterGraph(DaySummaryUI instance)
{
CanvasGroup[] field = GetField<CanvasGroup[]>(instance, "canvasGroups");
if (field == null || field.Length < 4)
{
Plugin.Log.LogWarning((object)"[CustomStats] canvasGroups missing or too short");
yield break;
}
CanvasGroup moneyGroup = field[3];
Plugin.Log.LogInfo((object)"[CustomStats] Waiting for money group to fade in...");
yield return (object)new WaitUntil((Func<bool>)(() => (Object)(object)moneyGroup != (Object)null && moneyGroup.alpha >= 0.9f));
Plugin.Log.LogInfo((object)"[CustomStats] Money group visible — building stats button + modal");
PayoutTracker instance2 = NetworkSingleton<PayoutTracker>.Instance;
List<PlayerProfile> list = (from p in Object.FindObjectsByType<PlayerProfile>((FindObjectsSortMode)0)
where (Object)(object)p != (Object)null && p.hasSynced && !string.IsNullOrEmpty(p.playerName)
select p).ToList();
List<PlayerDaySummary> list2 = ((!((Object)(object)instance2 != (Object)null) || list.Count <= 0) ? list.Select((PlayerProfile p) => new PlayerDaySummary
{
playerName = p.playerName
}).ToList() : DayStatsCalculator.CalculateAllPlayersStats(instance2, list));
Plugin.Log.LogInfo((object)$"[CustomStats] {list2.Count} player(s)");
PersistDailyHistory(instance2);
(GameObject, StatsModalController) tuple = StatsModal.BuildModal(((Component)instance).transform, list2, (MonoBehaviour)(object)instance);
GameObject modal = tuple.Item1;
StatsModalController item = tuple.Item2;
GameObject button = StatsModal.BuildButton(((Component)instance).transform, (MonoBehaviour)(object)instance, item);
CanvasGroup btnCg = button.GetComponent<CanvasGroup>();
float elapsed = 0f;
while (elapsed < 0.5f)
{
elapsed += Time.deltaTime;
if ((Object)(object)btnCg != (Object)null)
{
btnCg.alpha = Mathf.Clamp01(elapsed / 0.5f);
}
yield return null;
}
if ((Object)(object)btnCg != (Object)null)
{
btnCg.alpha = 1f;
}
yield return (object)new WaitUntil((Func<bool>)(() => (Object)(object)moneyGroup == (Object)null || moneyGroup.alpha < 0.1f));
if ((Object)(object)button != (Object)null)
{
Object.Destroy((Object)(object)button);
}
if ((Object)(object)modal != (Object)null)
{
Object.Destroy((Object)(object)modal);
}
}
private static void PersistDailyHistory(PayoutTracker? tracker)
{
if (!((Object)(object)tracker == (Object)null) && NetworkServer.active)
{
string text = RunSession.CurrentRunDirectory();
if (text == null)
{
Plugin.Log.LogInfo((object)"[VapuStats] No current save — skipping history persist");
return;
}
int num = RunSession.CurrentDaysPassed();
List<RunRecord> list = RunHistoryStore.LoadForCurrentRun(text, num);
int count = list.Count;
RunHistoryStore.Merge(list, tracker.GetAllRecords());
RunHistoryStore.Save(text, list, num);
Plugin.Log.LogInfo((object)$"[VapuStats] History persisted: {list.Count} records (+{list.Count - count}) at day {num} → {text}");
}
}
private static T? GetField<T>(object obj, string name) where T : class
{
FieldInfo field = typeof(DaySummaryUI).GetField(name, BindingFlags.Instance | BindingFlags.NonPublic);
if (field != null)
{
return (T)field.GetValue(obj);
}
Plugin.Log.LogWarning((object)("[CustomStats] Field '" + name + "' not found"));
return null;
}
}
[HarmonyPatch(typeof(GameOverUI), "Show")]
internal static class Patch_GameOverUI_Show
{
internal static GameObject? CurrentModal;
internal static GameObject? CurrentButton;
private static void Postfix(GameOverUI __instance)
{
Plugin.GameOverUIActivated = true;
Plugin.Log.LogInfo((object)"[VapuStats] GameOverUI.Show postfix fired");
CleanupNow();
((MonoBehaviour)__instance).StartCoroutine(SpawnStats(__instance));
}
private static IEnumerator SpawnStats(GameOverUI instance)
{
yield return null;
List<PlayerDaySummary> list = RunStatsLoader.BuildRunStats();
Plugin.Log.LogInfo((object)$"[VapuStats] GameOver stats built: {list.Count} player(s)");
Canvas componentInParent = ((Component)instance).GetComponentInParent<Canvas>();
Transform parent = (((Object)(object)componentInParent != (Object)null) ? ((Component)componentInParent.rootCanvas).transform : ((Component)instance).transform);
(GameObject modal, StatsModalController controller) tuple = StatsModal.BuildModal(parent, list, (MonoBehaviour)(object)instance, "RUN STATS");
GameObject item = tuple.modal;
StatsModalController item2 = tuple.controller;
GameObject obj = StatsModal.BuildButton(parent, (MonoBehaviour)(object)instance, item2);
CurrentModal = item;
CurrentButton = obj;
CanvasGroup component = obj.GetComponent<CanvasGroup>();
if ((Object)(object)component != (Object)null)
{
component.alpha = 1f;
}
Plugin.Log.LogInfo((object)"[VapuStats] GameOver stats button + modal spawned");
}
internal static void CleanupNow()
{
if ((Object)(object)CurrentButton != (Object)null)
{
Object.Destroy((Object)(object)CurrentButton);
}
if ((Object)(object)CurrentModal != (Object)null)
{
Object.Destroy((Object)(object)CurrentModal);
}
if ((Object)(object)CurrentButton != (Object)null || (Object)(object)CurrentModal != (Object)null)
{
Plugin.Log.LogInfo((object)"[VapuStats] GameOver stats cleaned up");
}
CurrentButton = null;
CurrentModal = null;
Plugin.GameOverUIActivated = false;
}
}
[HarmonyPatch(typeof(LocalSaveManager), "DeleteSave")]
internal static class Patch_LocalSaveManager_DeleteSave
{
private static void Postfix(string saveName)
{
if (string.IsNullOrEmpty(saveName))
{
return;
}
try
{
string text = Path.Combine(Paths.ConfigPath, "VapuStats");
if (!Directory.Exists(text))
{
return;
}
string text2 = RunSession.Sanitize(saveName);
string text3 = Path.Combine(text, text2);
if (Directory.Exists(text3))
{
Directory.Delete(text3, recursive: true);
Plugin.Log.LogInfo((object)("[VapuStats] Deleted run dir: " + text3));
}
string value = text2 + "__";
string[] directories = Directory.GetDirectories(text);
foreach (string text4 in directories)
{
string fileName = Path.GetFileName(text4);
if (fileName != null && fileName.StartsWith(value))
{
Directory.Delete(text4, recursive: true);
Plugin.Log.LogInfo((object)("[VapuStats] Deleted legacy run dir: " + text4));
}
}
}
catch (Exception ex)
{
Plugin.Log.LogWarning((object)("[VapuStats] DeleteSave cleanup failed: " + ex.Message));
}
}
}
[HarmonyPatch(typeof(SaveManager), "ResetCurrentSaveToDefaults")]
internal static class Patch_SaveManager_ResetCurrentSaveToDefaults
{
private static void Postfix()
{
if (NetworkServer.active && !((Object)(object)Plugin.Instance == (Object)null))
{
((MonoBehaviour)Plugin.Instance).StartCoroutine(DelayedArchive(RunSession.CurrentRunDirectory()));
}
}
private static IEnumerator DelayedArchive(string? runDir)
{
yield return (object)new WaitForSeconds(3f);
if (runDir != null)
{
RunHistoryStore.Archive(runDir);
Plugin.Log.LogInfo((object)"[VapuStats] Reset hook: archived previous run after delay");
}
}
}
[HarmonyPatch(typeof(NetworkManager), "ServerChangeScene")]
[HarmonyPriority(800)]
[HarmonyBefore(new string[] { "com.saltedbyte.nopitstops" })]
internal static class Patch_ServerChangeScene_RunEnd
{
private const string LoseSceneName = "LoseStateScene";
private const float SuppressTimeoutSeconds = 8f;
private static void Prefix(string newSceneName)
{
if (NetworkServer.active && !(newSceneName != "LoseStateScene"))
{
Plugin.Log.LogInfo((object)"[VapuStats] Run-end signal detected (ServerChangeScene LoseStateScene)");
RunStatsLoader.PersistFinalRecords();
if ((Object)(object)Plugin.Instance != (Object)null)
{
((MonoBehaviour)Plugin.Instance).StartCoroutine(MaybeShowFallback());
}
}
}
private static IEnumerator MaybeShowFallback()
{
Plugin.GameOverUIActivated = false;
Scene activeScene = SceneManager.GetActiveScene();
string startScene = ((Scene)(ref activeScene)).name;
float elapsed = 0f;
while (elapsed < 8f)
{
if (Plugin.GameOverUIActivated)
{
Plugin.Log.LogInfo((object)"[VapuStats] GameOverUI activated — fallback suppressed");
yield break;
}
activeScene = SceneManager.GetActiveScene();
string name = ((Scene)(ref activeScene)).name;
if (name != startScene)
{
if (name == "LoseStateScene")
{
Plugin.Log.LogInfo((object)("[VapuStats] Vanilla scene '" + name + "' loaded — fallback suppressed"));
yield break;
}
Plugin.Log.LogInfo((object)("[VapuStats] Scene rewritten to '" + name + "' — showing fallback modal"));
ShowFallback();
yield break;
}
elapsed += Time.unscaledDeltaTime;
yield return null;
}
Plugin.Log.LogWarning((object)"[VapuStats] Timeout waiting for scene change — showing fallback as safety net");
ShowFallback();
}
private static void ShowFallback()
{
FallbackRunOverModal.Show(RunStatsLoader.BuildRunStats());
}
}
public class PlayerDaySummary
{
public string playerName { get; set; } = "";
public long totalBet { get; set; }
public long totalPayout { get; set; }
public int totalGames { get; set; }
public int wins { get; set; }
public int losses { get; set; }
public int pushes { get; set; }
public int longestWinStreak { get; set; }
public int longestLossStreak { get; set; }
public Dictionary<CasinoGameType, GameTypeStats> byGameType { get; set; } = new Dictionary<CasinoGameType, GameTypeStats>();
public long NetProfit => totalPayout - totalBet;
public float WinPercentage
{
get
{
int num = wins + losses;
if (num > 0)
{
return (float)wins * 100f / (float)num;
}
return 0f;
}
}
}
internal static class PlayerStatsPanel
{
private static readonly float[] ColX = new float[7] { -160f, -75f, -25f, 30f, 95f, 155f, 210f };
private static readonly float[] ColW = new float[7] { 110f, 40f, 50f, 60f, 70f, 48f, 48f };
private const float PanelWidth = 480f;
internal static GameObject Build(Transform parent, List<PlayerDaySummary> stats, MonoBehaviour instance, Vector2 anchorMinMax, Vector2 pivot, Vector2 anchoredPosition)
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Expected O, but got Unknown
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
//IL_0085: 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)
//IL_009c: Unknown result type (might be due to invalid IL or missing references)
//IL_00a3: 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_00c3: Unknown result type (might be due to invalid IL or missing references)
//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
//IL_0101: Unknown result type (might be due to invalid IL or missing references)
//IL_0127: Unknown result type (might be due to invalid IL or missing references)
//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
//IL_01da: Unknown result type (might be due to invalid IL or missing references)
//IL_01db: Unknown result type (might be due to invalid IL or missing references)
//IL_029e: Unknown result type (might be due to invalid IL or missing references)
//IL_02a0: Unknown result type (might be due to invalid IL or missing references)
//IL_029a: Unknown result type (might be due to invalid IL or missing references)
//IL_0293: Unknown result type (might be due to invalid IL or missing references)
//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
//IL_02be: Unknown result type (might be due to invalid IL or missing references)
//IL_0358: Unknown result type (might be due to invalid IL or missing references)
//IL_0351: Unknown result type (might be due to invalid IL or missing references)
//IL_035a: Unknown result type (might be due to invalid IL or missing references)
//IL_036d: Unknown result type (might be due to invalid IL or missing references)
//IL_0366: Unknown result type (might be due to invalid IL or missing references)
//IL_036f: Unknown result type (might be due to invalid IL or missing references)
//IL_03e6: Unknown result type (might be due to invalid IL or missing references)
//IL_03eb: 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_03f7: Unknown result type (might be due to invalid IL or missing references)
//IL_03fe: Unknown result type (might be due to invalid IL or missing references)
//IL_0400: Unknown result type (might be due to invalid IL or missing references)
//IL_0407: Unknown result type (might be due to invalid IL or missing references)
//IL_0409: Unknown result type (might be due to invalid IL or missing references)
//IL_0410: Unknown result type (might be due to invalid IL or missing references)
//IL_0415: Unknown result type (might be due to invalid IL or missing references)
//IL_041c: Unknown result type (might be due to invalid IL or missing references)
//IL_041e: Unknown result type (might be due to invalid IL or missing references)
//IL_0425: Unknown result type (might be due to invalid IL or missing references)
//IL_0427: Unknown result type (might be due to invalid IL or missing references)
TMP_FontAsset font = PanelHelpers.GetFont(instance);
GameObject val = new GameObject("GWYF_StatsPanel");
val.transform.SetParent(parent, false);
RectTransform obj = val.AddComponent<RectTransform>();
obj.anchorMin = anchorMinMax;
obj.anchorMax = anchorMinMax;
obj.pivot = pivot;
obj.anchoredPosition = anchoredPosition;
obj.sizeDelta = new Vector2(480f, (float)stats.Count * 36f + 40f);
val.AddComponent<CanvasGroup>().alpha = 0f;
val.transform.SetAsLastSibling();
GameObject val2 = new GameObject("Background");
val2.transform.SetParent(val.transform, false);
RectTransform obj2 = val2.AddComponent<RectTransform>();
obj2.anchorMin = Vector2.zero;
obj2.anchorMax = Vector2.one;
obj2.pivot = new Vector2(0.5f, 0.5f);
obj2.anchoredPosition = Vector2.zero;
obj2.offsetMin = new Vector2(-12f, -12f);
obj2.offsetMax = new Vector2(12f, 12f);
Image obj3 = val2.AddComponent<Image>();
obj3.sprite = StatsModal.GetWhiteSprite();
((Graphic)obj3).color = new Color(0.13f, 0.13f, 0.16f, 0.97f);
((Graphic)obj3).raycastTarget = false;
val2.transform.SetAsFirstSibling();
Color val3 = default(Color);
((Color)(ref val3))..ctor(0.75f, 0.75f, 0.75f);
float num = -20f;
PanelHelpers.AddRow(val.transform, num, new string[7] { "PLAYER", "# BETS", "WIN %", "NET", "TOTAL BET", "WIN STK", "LOSS STK" }, (Color[])(object)new Color[7] { val3, val3, val3, val3, val3, val3, val3 }, 11, font, ColX, ColW);
Color val4 = default(Color);
((Color)(ref val4))..ctor(0.4f, 1f, 0.4f);
Color val5 = default(Color);
((Color)(ref val5))..ctor(1f, 0.4f, 0.4f);
for (int i = 0; i < stats.Count; i++)
{
PlayerDaySummary playerDaySummary = stats[i];
string text = MoneyFormatter.FormatWithDollar(Math.Abs(playerDaySummary.NetProfit), false);
string text2 = ((playerDaySummary.NetProfit > 0) ? ("+" + text) : ((playerDaySummary.NetProfit < 0) ? ("-" + text) : "$0"));
Color val6 = ((playerDaySummary.NetProfit > 0) ? val4 : ((playerDaySummary.NetProfit < 0) ? val5 : Color.white));
Color val7 = ((playerDaySummary.WinPercentage > 50f) ? val4 : ((playerDaySummary.WinPercentage < 50f) ? val5 : Color.white));
string text3 = ((playerDaySummary.playerName.Length > 12) ? (playerDaySummary.playerName.Substring(0, 11) + "…") : playerDaySummary.playerName);
string text4 = ((playerDaySummary.longestWinStreak > 0) ? playerDaySummary.longestWinStreak.ToString() : "-");
string text5 = ((playerDaySummary.longestLossStreak > 0) ? playerDaySummary.longestLossStreak.ToString() : "-");
Color val8 = ((playerDaySummary.longestWinStreak >= 3) ? val4 : Color.white);
Color val9 = ((playerDaySummary.longestLossStreak >= 3) ? val5 : Color.white);
PanelHelpers.AddRow(val.transform, num - 36f - (float)i * 34f, new string[7]
{
text3,
playerDaySummary.totalGames.ToString(),
$"{playerDaySummary.WinPercentage:F1}%",
text2,
MoneyFormatter.FormatWithDollar(playerDaySummary.totalBet, false),
text4,
text5
}, (Color[])(object)new Color[7]
{
Color.white,
Color.white,
val7,
val6,
Color.white,
val8,
val9
}, 15, font, ColX, ColW);
}
Canvas.ForceUpdateCanvases();
return val;
}
}
[BepInPlugin("com.vapu.stats", "Vapu Stats", "1.1.0")]
public class Plugin : BaseUnityPlugin
{
public const string PluginGuid = "com.vapu.stats";
public const string PluginName = "Vapu Stats";
public const string PluginVersion = "1.1.0";
internal static ManualLogSource Log;
internal static Plugin Instance;
internal static bool GameOverUIActivated;
private readonly Harmony _harmony = new Harmony("com.vapu.stats");
private void Awake()
{
Instance = this;
Log = ((BaseUnityPlugin)this).Logger;
_harmony.PatchAll();
int num = 0;
foreach (MethodBase patchedMethod in _harmony.GetPatchedMethods())
{
num++;
Log.LogInfo((object)(" patched: " + patchedMethod.DeclaringType?.Name + "." + patchedMethod.Name));
}
Log.LogInfo((object)string.Format("{0} v{1} loaded — {2} method(s) patched.", "Vapu Stats", "1.1.0", num));
SceneManager.activeSceneChanged += OnActiveSceneChanged;
}
private void OnDestroy()
{
SceneManager.activeSceneChanged -= OnActiveSceneChanged;
_harmony.UnpatchSelf();
}
private static void OnActiveSceneChanged(Scene from, Scene to)
{
Patch_GameOverUI_Show.CleanupNow();
}
}
[Serializable]
internal class RunRecord
{
public float timestamp;
public string playerName = "";
public long bet;
public long payout;
public bool isWin;
public bool isLoss;
public int gameType;
public static RunRecord From(PayoutRecord r)
{
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_0062: Expected I4, but got Unknown
return new RunRecord
{
timestamp = r.timestamp,
playerName = (r.playerName ?? ""),
bet = r.bet,
payout = r.payout,
isWin = r.isWin,
isLoss = r.isLoss,
gameType = (int)r.gameType
};
}
}
[Serializable]
internal class RunRecordsFile
{
public int version = 2;
public int recordedDaysPassed;
public List<RunRecord> records = new List<RunRecord>();
}
internal static class RunHistoryStore
{
private const string FileName = "history.json";
private const string ArchiveSubdir = "archive";
public static List<RunRecord> LoadForCurrentRun(string runDir, int currentDaysPassed)
{
try
{
string path = Path.Combine(runDir, "history.json");
if (!File.Exists(path))
{
return new List<RunRecord>();
}
RunRecordsFile runRecordsFile = JsonUtility.FromJson<RunRecordsFile>(File.ReadAllText(path));
if (runRecordsFile == null)
{
return new List<RunRecord>();
}
if (currentDaysPassed >= 0 && runRecordsFile.recordedDaysPassed > currentDaysPassed)
{
Plugin.Log.LogInfo((object)$"[VapuStats] Stale history detected (file day {runRecordsFile.recordedDaysPassed} > current {currentDaysPassed}) — archiving and starting fresh");
Archive(runDir);
return new List<RunRecord>();
}
return runRecordsFile.records ?? new List<RunRecord>();
}
catch (Exception ex)
{
Plugin.Log.LogWarning((object)("[VapuStats] Failed loading history from " + runDir + ": " + ex.Message));
return new List<RunRecord>();
}
}
public static List<RunRecord> LoadRaw(string runDir)
{
try
{
string path = Path.Combine(runDir, "history.json");
if (!File.Exists(path))
{
return new List<RunRecord>();
}
return JsonUtility.FromJson<RunRecordsFile>(File.ReadAllText(path))?.records ?? new List<RunRecord>();
}
catch (Exception ex)
{
Plugin.Log.LogWarning((object)("[VapuStats] Failed loading history from " + runDir + ": " + ex.Message));
return new List<RunRecord>();
}
}
public static void Save(string runDir, List<RunRecord> records, int currentDaysPassed)
{
try
{
Directory.CreateDirectory(runDir);
string path = Path.Combine(runDir, "history.json");
string contents = JsonUtility.ToJson((object)new RunRecordsFile
{
recordedDaysPassed = currentDaysPassed,
records = records
}, true);
File.WriteAllText(path, contents);
}
catch (Exception ex)
{
Plugin.Log.LogWarning((object)("[VapuStats] Failed saving history to " + runDir + ": " + ex.Message));
}
}
public static void Merge(List<RunRecord> existing, IEnumerable<PayoutRecord> incoming)
{
//IL_0098: Unknown result type (might be due to invalid IL or missing references)
//IL_00a2: Expected I4, but got Unknown
HashSet<string> hashSet = new HashSet<string>(existing.Count);
foreach (RunRecord item2 in existing)
{
hashSet.Add(MakeKey(item2.timestamp, item2.playerName, item2.bet, item2.payout, item2.gameType));
}
foreach (PayoutRecord item3 in incoming)
{
string item = MakeKey(item3.timestamp, item3.playerName ?? "", item3.bet, item3.payout, (int)item3.gameType);
if (hashSet.Add(item))
{
existing.Add(RunRecord.From(item3));
}
}
}
public static void Archive(string runDir)
{
try
{
string text = Path.Combine(runDir, "history.json");
if (File.Exists(text))
{
string text2 = Path.Combine(runDir, "archive");
Directory.CreateDirectory(text2);
long num = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
string text3 = Path.Combine(text2, $"run_{num}.json");
int num2 = 1;
while (File.Exists(text3))
{
text3 = Path.Combine(text2, $"run_{num}_{num2}.json");
num2++;
}
File.Move(text, text3);
Plugin.Log.LogInfo((object)("[VapuStats] Archived previous run to " + text3));
}
}
catch (Exception ex)
{
Plugin.Log.LogWarning((object)("[VapuStats] Failed archiving history in " + runDir + ": " + ex.Message));
}
}
public static void DeleteRun(string runDir)
{
try
{
if (Directory.Exists(runDir))
{
Directory.Delete(runDir, recursive: true);
}
}
catch (Exception ex)
{
Plugin.Log.LogWarning((object)("[VapuStats] Failed deleting run dir " + runDir + ": " + ex.Message));
}
}
private static string MakeKey(float ts, string name, long bet, long payout, int gameType)
{
return $"{ts:R}|{name}|{bet}|{payout}|{gameType}";
}
}
internal static class RunSession
{
private static readonly FieldInfo? CurrentSaveDataField = typeof(SaveManager).GetField("currentSaveData", BindingFlags.Instance | BindingFlags.NonPublic);
public static bool IsHost => NetworkServer.active;
public static string? CurrentSaveName()
{
SaveManager instance = NetworkSingleton<SaveManager>.Instance;
if ((Object)(object)instance == (Object)null || CurrentSaveDataField == null)
{
return null;
}
object? value = CurrentSaveDataField.GetValue(instance);
SaveData val = (SaveData)((value is SaveData) ? value : null);
if (val == null)
{
return null;
}
if (string.IsNullOrEmpty(val.saveName))
{
return null;
}
return val.saveName;
}
public static int CurrentDaysPassed()
{
GameManager instance = NetworkSingleton<GameManager>.Instance;
if (!((Object)(object)instance != (Object)null))
{
return 0;
}
return instance.daysPassed;
}
public static string RunDirectoryFor(string saveName)
{
return Path.Combine(Paths.ConfigPath, "VapuStats", Sanitize(saveName));
}
public static string? CurrentRunDirectory()
{
string text = CurrentSaveName();
if (text != null)
{
return RunDirectoryFor(text);
}
return null;
}
internal static string Sanitize(string s)
{
char[] invalidFileNameChars = Path.GetInvalidFileNameChars();
foreach (char oldChar in invalidFileNameChars)
{
s = s.Replace(oldChar, '_');
}
return s;
}
}
internal static class RunStatsLoader
{
public static List<PlayerDaySummary> BuildRunStats()
{
PayoutTracker instance = NetworkSingleton<PayoutTracker>.Instance;
if (NetworkServer.active)
{
string text = RunSession.CurrentRunDirectory();
if (text != null)
{
List<RunRecord> list = RunHistoryStore.LoadRaw(text);
if ((Object)(object)instance != (Object)null)
{
RunHistoryStore.Merge(list, instance.GetAllRecords());
}
Plugin.Log.LogInfo((object)$"[VapuStats] Host stats: {list.Count} records from {text}");
return DayStatsCalculator.CalculateFromRecords(list);
}
Plugin.Log.LogInfo((object)"[VapuStats] Host but no current save — using in-memory tracker");
}
if ((Object)(object)instance != (Object)null)
{
List<RunRecord> list2 = instance.GetAllRecords().Select(RunRecord.From).ToList();
Plugin.Log.LogInfo((object)$"[VapuStats] Client stats: {list2.Count} records from in-memory tracker");
return DayStatsCalculator.CalculateFromRecords(list2);
}
Plugin.Log.LogWarning((object)"[VapuStats] No PayoutTracker available");
return new List<PlayerDaySummary>();
}
public static void PersistFinalRecords()
{
if (!NetworkServer.active)
{
return;
}
PayoutTracker instance = NetworkSingleton<PayoutTracker>.Instance;
if (!((Object)(object)instance == (Object)null))
{
string text = RunSession.CurrentRunDirectory();
if (text != null)
{
int num = RunSession.CurrentDaysPassed();
List<RunRecord> list = RunHistoryStore.LoadForCurrentRun(text, num);
int count = list.Count;
RunHistoryStore.Merge(list, instance.GetAllRecords());
RunHistoryStore.Save(text, list, num);
Plugin.Log.LogInfo((object)$"[VapuStats] Final persist: {list.Count} records (+{list.Count - count}) at day {num}");
}
}
}
}
internal class StatsModalController : MonoBehaviour
{
public CanvasGroup? cg;
public bool isOpen;
public TextMeshProUGUI? buttonLabel;
private void Update()
{
Keyboard current = Keyboard.current;
if (current != null && ((ButtonControl)current.tabKey).wasPressedThisFrame)
{
Toggle();
}
}
public void Open()
{
if (!((Object)(object)cg == (Object)null))
{
isOpen = true;
cg.alpha = 1f;
cg.interactable = true;
cg.blocksRaycasts = true;
if ((Object)(object)buttonLabel != (Object)null)
{
((TMP_Text)buttonLabel).text = "Close (TAB)";
}
}
}
public void Close()
{
if (!((Object)(object)cg == (Object)null))
{
isOpen = false;
cg.alpha = 0f;
cg.interactable = false;
cg.blocksRaycasts = false;
if ((Object)(object)buttonLabel != (Object)null)
{
((TMP_Text)buttonLabel).text = "Stats (TAB)";
}
}
}
public void Toggle()
{
if (isOpen)
{
Close();
}
else
{
Open();
}
}
}
internal static class StatsModal
{
private static Sprite? _whiteSprite;
internal static Sprite GetWhiteSprite()
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_005a: Expected O, but got Unknown
if ((Object)(object)_whiteSprite != (Object)null)
{
return _whiteSprite;
}
Texture2D val = new Texture2D(1, 1);
val.SetPixel(0, 0, Color.white);
val.Apply();
_whiteSprite = Sprite.Create(val, new Rect(0f, 0f, 1f, 1f), new Vector2(0.5f, 0.5f));
return _whiteSprite;
}
internal static (GameObject modal, StatsModalController controller) BuildModal(Transform parent, List<PlayerDaySummary> stats, MonoBehaviour instance, string titleText = "DAY STATS")
{
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Expected O, but got Unknown
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: 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_007a: 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_00ce: 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_00f1: Unknown result type (might be due to invalid IL or missing references)
//IL_0106: Unknown result type (might be due to invalid IL or missing references)
//IL_011b: Unknown result type (might be due to invalid IL or missing references)
//IL_0126: Unknown result type (might be due to invalid IL or missing references)
//IL_013a: Unknown result type (might be due to invalid IL or missing references)
//IL_0144: Unknown result type (might be due to invalid IL or missing references)
//IL_016e: 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_01ab: Expected O, but got Unknown
//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
//IL_0202: Unknown result type (might be due to invalid IL or missing references)
//IL_0217: 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_0263: Unknown result type (might be due to invalid IL or missing references)
//IL_0286: Unknown result type (might be due to invalid IL or missing references)
//IL_028b: Unknown result type (might be due to invalid IL or missing references)
//IL_029d: Unknown result type (might be due to invalid IL or missing references)
//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
//IL_02c3: 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_02ed: Unknown result type (might be due to invalid IL or missing references)
//IL_0301: Unknown result type (might be due to invalid IL or missing references)
//IL_0351: Unknown result type (might be due to invalid IL or missing references)
//IL_0381: Unknown result type (might be due to invalid IL or missing references)
//IL_0390: Unknown result type (might be due to invalid IL or missing references)
//IL_039f: Unknown result type (might be due to invalid IL or missing references)
//IL_0442: Unknown result type (might be due to invalid IL or missing references)
//IL_0451: Unknown result type (might be due to invalid IL or missing references)
//IL_0469: Unknown result type (might be due to invalid IL or missing references)
//IL_03d7: Unknown result type (might be due to invalid IL or missing references)
//IL_03dc: Unknown result type (might be due to invalid IL or missing references)
//IL_03e0: Unknown result type (might be due to invalid IL or missing references)
TMP_FontAsset font = PanelHelpers.GetFont(instance);
Canvas componentInParent = ((Component)instance).GetComponentInParent<Canvas>();
Transform val = (Transform)(((Object)(object)componentInParent != (Object)null) ? ((object)((Component)componentInParent.rootCanvas).transform) : ((object)parent));
GameObject val2 = new GameObject("GWYF_StatsModal");
val2.transform.SetParent(val, false);
RectTransform obj = val2.AddComponent<RectTransform>();
obj.anchorMin = Vector2.zero;
obj.anchorMax = Vector2.one;
obj.pivot = new Vector2(0.5f, 0.5f);
obj.anchoredPosition = Vector2.zero;
obj.sizeDelta = Vector2.zero;
val2.transform.SetAsLastSibling();
CanvasGroup val3 = val2.AddComponent<CanvasGroup>();
val3.alpha = 0f;
val3.interactable = false;
val3.blocksRaycasts = false;
StatsModalController statsModalController = val2.AddComponent<StatsModalController>();
statsModalController.cg = val3;
GameObject val4 = new GameObject("Backdrop");
val4.transform.SetParent(val2.transform, false);
RectTransform obj2 = val4.AddComponent<RectTransform>();
obj2.anchorMin = new Vector2(0.5f, 0.5f);
obj2.anchorMax = new Vector2(0.5f, 0.5f);
obj2.pivot = new Vector2(0.5f, 0.5f);
obj2.anchoredPosition = Vector2.zero;
obj2.sizeDelta = new Vector2(10000f, 10000f);
Image val5 = val4.AddComponent<Image>();
val5.sprite = GetWhiteSprite();
((Graphic)val5).color = new Color(0f, 0f, 0f, 1f);
((Graphic)val5).raycastTarget = true;
Button obj3 = val4.AddComponent<Button>();
((Selectable)obj3).transition = (Transition)0;
((Selectable)obj3).targetGraphic = (Graphic)(object)val5;
((UnityEvent)obj3.onClick).AddListener(new UnityAction(statsModalController.Close));
GameObject val6 = new GameObject("Title");
val6.transform.SetParent(val2.transform, false);
RectTransform obj4 = val6.AddComponent<RectTransform>();
obj4.anchorMin = new Vector2(0.5f, 1f);
obj4.anchorMax = new Vector2(0.5f, 1f);
obj4.pivot = new Vector2(0.5f, 1f);
obj4.anchoredPosition = new Vector2(0f, -40f);
obj4.sizeDelta = new Vector2(600f, 60f);
TextMeshProUGUI val7 = val6.AddComponent<TextMeshProUGUI>();
if ((Object)(object)font != (Object)null)
{
((TMP_Text)val7).font = font;
}
((TMP_Text)val7).text = titleText;
((TMP_Text)val7).fontSize = 36f;
((Graphic)val7).color = Color.white;
((TMP_Text)val7).alignment = (TextAlignmentOptions)514;
((Graphic)val7).raycastTarget = false;
GameObject val8 = new GameObject("Hint");
val8.transform.SetParent(val2.transform, false);
RectTransform obj5 = val8.AddComponent<RectTransform>();
obj5.anchorMin = new Vector2(0.5f, 0f);
obj5.anchorMax = new Vector2(0.5f, 0f);
obj5.pivot = new Vector2(0.5f, 0f);
obj5.anchoredPosition = new Vector2(0f, 30f);
obj5.sizeDelta = new Vector2(600f, 30f);
TextMeshProUGUI val9 = val8.AddComponent<TextMeshProUGUI>();
if ((Object)(object)font != (Object)null)
{
((TMP_Text)val9).font = font;
}
((TMP_Text)val9).text = "Press TAB to close";
((TMP_Text)val9).fontSize = 16f;
((Graphic)val9).color = new Color(0.7f, 0.7f, 0.7f, 1f);
((TMP_Text)val9).alignment = (TextAlignmentOptions)514;
((Graphic)val9).raycastTarget = false;
GameTypePanel.Build(val2.transform, stats, instance, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -110f));
HashSet<CasinoGameType> hashSet = new HashSet<CasinoGameType>();
foreach (PlayerDaySummary stat in stats)
{
foreach (CasinoGameType key in stat.byGameType.Keys)
{
hashSet.Add(key);
}
}
float num = (float)hashSet.Count * 26f + 40f;
PlayerStatsPanel.Build(val2.transform, stats, instance, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -110f - num - 30f));
CanvasGroup[] componentsInChildren = val2.GetComponentsInChildren<CanvasGroup>();
foreach (CanvasGroup val10 in componentsInChildren)
{
if ((Object)(object)val10 != (Object)(object)val3)
{
val10.alpha = 1f;
}
}
Canvas.ForceUpdateCanvases();
return (val2, statsModalController);
}
internal static GameObject BuildButton(Transform parent, MonoBehaviour instance, StatsModalController controller)
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Expected O, but got Unknown
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
//IL_006f: Unknown result type (might be due to invalid IL or missing references)
//IL_0083: Unknown result type (might be due to invalid IL or missing references)
//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
//IL_00de: Unknown result type (might be due to invalid IL or missing references)
//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
//IL_011a: Unknown result type (might be due to invalid IL or missing references)
//IL_013a: Unknown result type (might be due to invalid IL or missing references)
//IL_0145: Unknown result type (might be due to invalid IL or missing references)
//IL_0157: Unknown result type (might be due to invalid IL or missing references)
//IL_0161: Expected O, but got Unknown
//IL_0166: Unknown result type (might be due to invalid IL or missing references)
//IL_016b: Unknown result type (might be due to invalid IL or missing references)
//IL_017d: Unknown result type (might be due to invalid IL or missing references)
//IL_0184: Unknown result type (might be due to invalid IL or missing references)
//IL_018f: Unknown result type (might be due to invalid IL or missing references)
//IL_019a: Unknown result type (might be due to invalid IL or missing references)
//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
TMP_FontAsset font = PanelHelpers.GetFont(instance);
GameObject val = new GameObject("GWYF_StatsButton");
val.transform.SetParent(parent, false);
RectTransform obj = val.AddComponent<RectTransform>();
obj.anchorMin = new Vector2(1f, 1f);
obj.anchorMax = new Vector2(1f, 1f);
obj.pivot = new Vector2(1f, 1f);
obj.anchoredPosition = new Vector2(-30f, -30f);
obj.sizeDelta = new Vector2(160f, 48f);
val.transform.SetAsLastSibling();
Image val2 = val.AddComponent<Image>();
val2.sprite = GetWhiteSprite();
((Graphic)val2).color = new Color(0.2f, 0.45f, 0.7f, 1f);
((Graphic)val2).raycastTarget = true;
Button obj2 = val.AddComponent<Button>();
((Selectable)obj2).targetGraphic = (Graphic)(object)val2;
ColorBlock colors = ((Selectable)obj2).colors;
((ColorBlock)(ref colors)).normalColor = new Color(0.2f, 0.45f, 0.7f, 1f);
((ColorBlock)(ref colors)).highlightedColor = new Color(0.3f, 0.6f, 0.9f, 1f);
((ColorBlock)(ref colors)).pressedColor = new Color(0.15f, 0.35f, 0.55f, 1f);
((Selectable)obj2).colors = colors;
((UnityEvent)obj2.onClick).AddListener(new UnityAction(controller.Toggle));
GameObject val3 = new GameObject("Label");
val3.transform.SetParent(val.transform, false);
RectTransform obj3 = val3.AddComponent<RectTransform>();
obj3.anchorMin = Vector2.zero;
obj3.anchorMax = Vector2.one;
obj3.sizeDelta = Vector2.zero;
obj3.anchoredPosition = Vector2.zero;
TextMeshProUGUI val4 = val3.AddComponent<TextMeshProUGUI>();
if ((Object)(object)font != (Object)null)
{
((TMP_Text)val4).font = font;
}
((TMP_Text)val4).text = "Stats (TAB)";
((TMP_Text)val4).fontSize = 18f;
((Graphic)val4).color = Color.white;
((TMP_Text)val4).alignment = (TextAlignmentOptions)514;
((Graphic)val4).raycastTarget = false;
controller.buttonLabel = val4;
val.AddComponent<CanvasGroup>().alpha = 0f;
return val;
}
}
}