using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Extensions;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using SandboxMode.Patches;
using UnityEngine;
using UnityEngine.SceneManagement;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("SandboxMode")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.3.1.0")]
[assembly: AssemblyInformationalVersion("0.3.1+739db765c31be9369934de526d6b15bd578d2386")]
[assembly: AssemblyProduct("SandboxMode")]
[assembly: AssemblyTitle("SandboxMode")]
[assembly: AssemblyVersion("0.3.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace SandboxMode
{
[BepInPlugin("com.saltedbyte.sandboxmode", "SandboxMode", "0.3.0")]
public class Plugin : BaseUnityPlugin
{
public const string PluginGuid = "com.saltedbyte.sandboxmode";
public const string PluginName = "SandboxMode";
public const string PluginVersion = "0.3.0";
public const long StartingMoney = 1000000000000L;
public const float SandboxDayDuration = 3600f;
internal static ManualLogSource Log = null;
internal static ConfigEntry<long> BetQuota = null;
private static readonly Type[] PatchClasses = new Type[6]
{
typeof(GameManager_CaptureOriginalDayDuration),
typeof(GameSettings_SandboxQuota),
typeof(LocalSaveManager_CreateNewSave),
typeof(LocalSaveManager_DeleteSave),
typeof(SaveManager_RefreshSandboxState),
typeof(SaveSlotUI_SandboxDialog)
};
private void Awake()
{
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Expected O, but got Unknown
Log = ((BaseUnityPlugin)this).Logger;
BindConfig();
Log.LogInfo((object)"SandboxMode v0.3.0 loaded.");
SandboxLabel.Bootstrap();
Harmony val = new Harmony("com.saltedbyte.sandboxmode");
int num = 0;
Type[] patchClasses = PatchClasses;
foreach (Type type in patchClasses)
{
try
{
val.CreateClassProcessor(type).Patch();
Log.LogInfo((object)(" ✔ patched " + type.Name));
num++;
}
catch (Exception arg)
{
Log.LogError((object)$" ✘ FAILED to patch {type.Name}: {arg}");
}
}
Log.LogInfo((object)$"Harmony patches applied: {num}/{PatchClasses.Length}");
}
private void BindConfig()
{
BetQuota = ((BaseUnityPlugin)this).Config.Bind<long>("Sandbox", "BetQuota", 5000L, "Effective `currentQuota` value used by MinBet/MaxBet formulas when a sandbox save is loaded. Pinned across days (GameSettings.GetQuota always returns this in sandbox). Higher = larger casino-game bet ranges. Tune to taste; 5000 is a starting guess for late-game stakes.");
}
}
internal sealed class SandboxLabel : MonoBehaviour
{
private static readonly string[] VisibleScenes = new string[2] { "HomeScene", "CasinoScene" };
private static SandboxLabel _instance;
private GUIStyle _style;
private Texture2D _bgTex;
public static void Bootstrap()
{
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Expected O, but got Unknown
if (!((Object)(object)_instance != (Object)null))
{
GameObject val = new GameObject("SandboxMode.SandboxLabel");
Object.DontDestroyOnLoad((Object)val);
_instance = val.AddComponent<SandboxLabel>();
}
}
private void OnGUI()
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: 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)
if (!SandboxState.IsCurrentSaveSandbox)
{
return;
}
Scene activeScene = SceneManager.GetActiveScene();
string name = ((Scene)(ref activeScene)).name;
bool flag = false;
for (int i = 0; i < VisibleScenes.Length; i++)
{
if (name == VisibleScenes[i])
{
flag = true;
break;
}
}
if (flag)
{
EnsureStyle();
GUI.Box(new Rect(14f, 14f, 180f, 30f), "SANDBOX MODE", _style);
}
}
private void EnsureStyle()
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Expected O, but got Unknown
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_0074: Unknown result type (might be due to invalid IL or missing references)
//IL_007e: Expected O, but got Unknown
//IL_007e: Unknown result type (might be due to invalid IL or missing references)
//IL_0098: Unknown result type (might be due to invalid IL or missing references)
//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
//IL_00b8: Expected O, but got Unknown
if (_style == null)
{
_bgTex = new Texture2D(1, 1);
_bgTex.SetPixel(0, 0, new Color(0f, 0f, 0f, 0.72f));
_bgTex.Apply();
GUIStyle val = new GUIStyle(GUI.skin.box)
{
fontSize = 16,
fontStyle = (FontStyle)1,
alignment = (TextAnchor)4,
padding = new RectOffset(10, 10, 4, 4)
};
val.normal.textColor = new Color(1f, 0.78f, 0.2f, 1f);
val.normal.background = _bgTex;
_style = val;
}
}
}
internal static class SandboxState
{
private const string MarkerExtension = ".sandbox";
public static bool NextSaveIsSandbox;
public static bool IsCurrentSaveSandbox;
public static float OriginalDayDuration;
public static bool DayDurationCaptured;
private static string SavesDirectory => Path.Combine(Application.persistentDataPath, "Saves");
public static string MarkerPath(string saveName)
{
return Path.Combine(SavesDirectory, saveName + ".sandbox");
}
public static bool IsMarked(string saveName)
{
if (string.IsNullOrEmpty(saveName))
{
return false;
}
try
{
return File.Exists(MarkerPath(saveName));
}
catch
{
return false;
}
}
public static void WriteMarker(string saveName)
{
if (string.IsNullOrEmpty(saveName))
{
return;
}
try
{
Directory.CreateDirectory(SavesDirectory);
File.WriteAllText(MarkerPath(saveName), "sandbox");
}
catch (Exception ex)
{
Plugin.Log.LogError((object)("[SandboxMode] failed to write sandbox marker for '" + saveName + "': " + ex.Message));
}
}
public static void DeleteMarker(string saveName)
{
if (string.IsNullOrEmpty(saveName))
{
return;
}
try
{
string path = MarkerPath(saveName);
if (File.Exists(path))
{
File.Delete(path);
}
}
catch (Exception ex)
{
Plugin.Log.LogError((object)("[SandboxMode] failed to delete sandbox marker for '" + saveName + "': " + ex.Message));
}
}
public static void RefreshFromCurrentSave()
{
string @string = PlayerPrefs.GetString("SelectedSaveName", "");
IsCurrentSaveSandbox = IsMarked(@string);
GameSettings val = Resources.Load<GameSettings>("GameSettings");
if ((Object)(object)val == (Object)null)
{
Plugin.Log.LogWarning((object)"[SandboxMode] GameSettings not found — cannot adjust dayDuration");
return;
}
if (!DayDurationCaptured)
{
OriginalDayDuration = val.dayDuration;
DayDurationCaptured = true;
}
float num = (IsCurrentSaveSandbox ? 3600f : OriginalDayDuration);
if (!Mathf.Approximately(val.dayDuration, num))
{
Plugin.Log.LogInfo((object)$"[SandboxMode] save '{@string}' sandbox={IsCurrentSaveSandbox} → dayDuration {val.dayDuration}s → {num}s");
val.dayDuration = num;
}
}
}
}
namespace SandboxMode.Patches
{
[HarmonyPatch(typeof(GameManager), "OnAwake")]
internal static class GameManager_CaptureOriginalDayDuration
{
[HarmonyPostfix]
private static void Postfix()
{
if (!SandboxState.DayDurationCaptured)
{
GameSettings val = Resources.Load<GameSettings>("GameSettings");
if ((Object)(object)val == (Object)null)
{
Plugin.Log.LogWarning((object)"[SandboxMode] GameSettings not found in OnAwake postfix");
return;
}
SandboxState.OriginalDayDuration = val.dayDuration;
SandboxState.DayDurationCaptured = true;
Plugin.Log.LogInfo((object)$"[SandboxMode] captured original dayDuration = {val.dayDuration}s");
}
}
}
[HarmonyPatch(typeof(GameSettings), "GetQuota")]
internal static class GameSettings_SandboxQuota
{
[HarmonyPrefix]
private static bool Prefix(ref long __result)
{
if (!SandboxState.IsCurrentSaveSandbox)
{
return true;
}
__result = Plugin.BetQuota.Value;
return false;
}
}
[HarmonyPatch(typeof(LocalSaveManager), "CreateNewSave")]
internal static class LocalSaveManager_CreateNewSave
{
[HarmonyPostfix]
private static void Postfix(string saveName)
{
bool nextSaveIsSandbox = SandboxState.NextSaveIsSandbox;
SandboxState.NextSaveIsSandbox = false;
if (!nextSaveIsSandbox || string.IsNullOrEmpty(saveName))
{
return;
}
try
{
string text = Path.Combine(Path.Combine(Application.persistentDataPath, "Saves"), saveName + ".json");
if (!File.Exists(text))
{
Plugin.Log.LogWarning((object)("[SandboxMode] expected save file missing after CreateNewSave: " + text));
return;
}
SaveData val = JsonUtility.FromJson<SaveData>(File.ReadAllText(text));
if (val == null)
{
Plugin.Log.LogWarning((object)("[SandboxMode] failed to deserialize save file: " + text));
return;
}
GameSettings val2 = Resources.Load<GameSettings>("GameSettings");
int currentFloor = (((Object)(object)val2 != (Object)null && val2.floorData != null && val2.floorData.Count > 0) ? (val2.floorData.Count - 1) : 4);
val.money = 1000000000000L;
val.currentQuota = Plugin.BetQuota.Value;
val.currentFloor = currentFloor;
val.requiredQuotaToNextFloor = long.MaxValue;
val.successfulQuota = 0;
File.WriteAllText(text, JsonUtility.ToJson((object)val, true));
PlayerPrefs.SetString("SelectedSaveData", JsonUtility.ToJson((object)val));
PlayerPrefs.Save();
SandboxState.WriteMarker(saveName);
Plugin.Log.LogInfo((object)$"[SandboxMode] save '{saveName}' marked sandbox — money={val.money}, quota={val.currentQuota}, floor={val.currentFloor}");
}
catch (Exception arg)
{
Plugin.Log.LogError((object)$"[SandboxMode] failed to apply sandbox values to '{saveName}': {arg}");
}
}
}
[HarmonyPatch(typeof(LocalSaveManager), "DeleteSave")]
internal static class LocalSaveManager_DeleteSave
{
[HarmonyPostfix]
private static void Postfix(string saveName)
{
SandboxState.DeleteMarker(saveName);
}
}
[HarmonyPatch(typeof(SaveManager), "LoadGame")]
internal static class SaveManager_RefreshSandboxState
{
[HarmonyPostfix]
private static void Postfix()
{
SandboxState.RefreshFromCurrentSave();
}
}
[HarmonyPatch(typeof(SaveSlotUI), "OnSlotClicked")]
internal static class SaveSlotUI_SandboxDialog
{
private const string DialogMessage = "What kind of save?";
[HarmonyPrefix]
private static bool Prefix(SaveSlotUI __instance, ref bool ___isEmpty)
{
if (!___isEmpty)
{
return true;
}
LocalSaveManager manager = MonoSingleton<LocalSaveManager>.Instance;
if ((Object)(object)manager == (Object)null)
{
Plugin.Log.LogWarning((object)"[SandboxMode] LocalSaveManager.Instance null — falling back to vanilla create flow");
return true;
}
string saveName = $"Save_{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}";
ConfirmationDialogManager instance = MonoSingleton<ConfirmationDialogManager>.Instance;
if ((Object)(object)instance == (Object)null)
{
Plugin.Log.LogWarning((object)"[SandboxMode] ConfirmationDialogManager.Instance null — creating normal save without prompt");
CreateAndSelect(__instance, manager, saveName, sandbox: false);
return false;
}
SaveSlotUI slotRef = __instance;
instance.ShowConfirmation("What kind of save?", (Action)delegate
{
CreateAndSelect(slotRef, manager, saveName, sandbox: false);
}, (Action)delegate
{
CreateAndSelect(slotRef, manager, saveName, sandbox: true);
}, "Normal", "Sandbox");
return false;
}
private static void CreateAndSelect(SaveSlotUI slot, LocalSaveManager manager, string saveName, bool sandbox)
{
try
{
SandboxState.NextSaveIsSandbox = sandbox;
manager.CreateNewSave(saveName);
slot.OnSlotSelected?.Invoke(saveName);
}
catch (Exception arg)
{
Plugin.Log.LogError((object)$"[SandboxMode] CreateAndSelect failed for '{saveName}' (sandbox={sandbox}): {arg}");
SandboxState.NextSaveIsSandbox = false;
}
}
}
}