Decompiled source of SandboxMode v0.3.1

BepInEx/plugins/SandboxMode/SandboxMode.dll

Decompiled 10 hours ago
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;
			}
		}
	}
}