Decompiled source of DayRetry v1.0.2

BepInEx\plugins\DayRetry\DayRetry.dll

Decompiled 3 hours ago
using System;
using System.Collections;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using Extensions;
using HarmonyLib;
using Mirror;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.UI;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace DayRetry;

[BepInPlugin("com.adam.dayretry", "Day Retry", "1.0.2")]
public sealed class DayRetryPlugin : BaseUnityPlugin
{
	[HarmonyPatch(typeof(GameManager), "StartDay")]
	private static class StartDayPatch
	{
		private static void Postfix(GameManager __instance)
		{
			CaptureDayStart(__instance);
		}
	}

	[HarmonyPatch(typeof(GameManager), "ProgressGame")]
	private static class ProgressGamePatch
	{
		[HarmonyPriority(800)]
		private static bool Prefix(GameManager __instance)
		{
			return !TryHoldQuotaFailure(__instance);
		}
	}

	[HarmonyPatch(typeof(GameManager), "ShowGameOverStats")]
	private static class ShowGameOverStatsPatch
	{
		private static void Prefix(GameManager __instance)
		{
			ArmLossRetryFromGameOverStats(__instance);
		}
	}

	[HarmonyPatch(typeof(GameOverUI), "Show")]
	private static class GameOverUiShowPatch
	{
		private static void Postfix(GameOverUI __instance)
		{
			InstallRestartButton(__instance);
		}
	}

	public const string PluginGuid = "com.adam.dayretry";

	public const string PluginName = "Day Retry";

	public const string PluginVersion = "1.0.2";

	private static readonly object SnapshotLock = new object();

	private static ConfigEntry<bool> _enabled;

	private static ConfigEntry<bool> _showDebugLogs;

	private static ConfigEntry<string> _buttonAnchor;

	private static ConfigEntry<int> _snapshotBackupsToKeep;

	private static ConfigEntry<float> _restartHoldDuration;

	private static Harmony _harmony;

	private static DayRetryPlugin _instance;

	private string _snapshotDirectory;

	private string _latestSnapshotPath;

	private string _latestSaveName;

	private int _latestSnapshotDaysPassed = -1;

	private GameManager _pendingGameManager;

	private bool _waitingForHostChoice;

	private bool _restoreInProgress;

	private bool _continueVanillaProgression;

	private bool _lossRetryAvailable;

	private GameObject _restartButtonObject;

	private Image _holdFillImage;

	private TextMeshProUGUI _restartButtonLabel;

	private TextMeshProUGUI _holdPromptLabel;

	private float _restartHoldProgress;

	private bool _hasCursorOverride;

	private bool _previousCursorVisible;

	private CursorLockMode _previousCursorLockState;

	private Rect _windowRect;

	private GUIStyle _windowStyle;

	private GUIStyle _titleStyle;

	private GUIStyle _bodyStyle;

	private GUIStyle _primaryButtonStyle;

	private GUIStyle _secondaryButtonStyle;

	private Texture2D _cursorTexture;

	public static bool IsEnabled
	{
		get
		{
			if (_enabled != null)
			{
				return _enabled.Value;
			}
			return false;
		}
	}

	private void Awake()
	{
		//IL_0103: Unknown result type (might be due to invalid IL or missing references)
		//IL_0108: Unknown result type (might be due to invalid IL or missing references)
		//IL_0112: Unknown result type (might be due to invalid IL or missing references)
		//IL_011c: Expected O, but got Unknown
		_instance = this;
		_enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable day-start retry after missing quota.");
		_showDebugLogs = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowDebugLogs", true, "Write detailed DayRetry messages to the BepInEx log.");
		_buttonAnchor = ((BaseUnityPlugin)this).Config.Bind<string>("UI", "ButtonAnchor", "Center", "Restart prompt anchor: Center, Top, Bottom.");
		_snapshotBackupsToKeep = ((BaseUnityPlugin)this).Config.Bind<int>("Snapshots", "SnapshotBackupsToKeep", 3, "Number of per-save day-start snapshots to retain.");
		_restartHoldDuration = ((BaseUnityPlugin)this).Config.Bind<float>("UI", "RestartHoldDuration", 1.35f, "Seconds the host must hold E to restart the failed day.");
		_snapshotDirectory = Path.Combine(Paths.ConfigPath, "DayRetry", "snapshots");
		Directory.CreateDirectory(_snapshotDirectory);
		_windowRect = new Rect(((float)Screen.width - 460f) * 0.5f, ((float)Screen.height - 230f) * 0.5f, 460f, 230f);
		_harmony = new Harmony("com.adam.dayretry");
		_harmony.PatchAll();
		((BaseUnityPlugin)this).Logger.LogInfo((object)"DayRetry loaded");
	}

	private void OnDestroy()
	{
		if (_harmony != null)
		{
			_harmony.UnpatchSelf();
			_harmony = null;
		}
		if ((Object)(object)_instance == (Object)(object)this)
		{
			_instance.ReleaseCursorControl();
			_instance = null;
		}
	}

	private void Update()
	{
		if (_waitingForHostChoice && !_restoreInProgress && NetworkServer.active && NetworkClient.active)
		{
			TakeCursorControl();
		}
		if (_lossRetryAvailable && (Object)(object)_restartButtonObject == (Object)null && !_restoreInProgress && NetworkServer.active && NetworkClient.active)
		{
			GameOverUI val = Object.FindAnyObjectByType<GameOverUI>();
			if ((Object)(object)val != (Object)null)
			{
				CreateRestartButton(val);
			}
		}
		UpdateRestartHoldProgress();
	}

	private void LateUpdate()
	{
		if (_waitingForHostChoice && !_restoreInProgress && NetworkServer.active && NetworkClient.active)
		{
			TakeCursorControl();
		}
	}

	internal static void CaptureDayStart(GameManager gameManager)
	{
		if (!((Object)(object)_instance == (Object)null) && IsEnabled && !((Object)(object)gameManager == (Object)null) && NetworkServer.active)
		{
			_instance.CaptureDayStartSnapshot();
		}
	}

	internal static bool TryHoldQuotaFailure(GameManager gameManager)
	{
		if ((Object)(object)_instance == (Object)null || !IsEnabled || (Object)(object)gameManager == (Object)null || !NetworkServer.active)
		{
			return false;
		}
		if (!NetworkClient.active)
		{
			_instance.LogWarning("Quota failure detected on a server without a local host client. DayRetry needs the lobby host UI, so vanilla loss flow will continue.");
			return false;
		}
		if (_instance._continueVanillaProgression)
		{
			_instance._continueVanillaProgression = false;
			return false;
		}
		if (!IsQuotaFailure(gameManager))
		{
			return false;
		}
		if (!_instance.HasUsableSnapshot())
		{
			_instance.LogWarning("Quota failure detected, but no usable day-start snapshot was available. Allowing vanilla loss flow.");
			return false;
		}
		if (_instance._waitingForHostChoice)
		{
			return true;
		}
		_instance._pendingGameManager = gameManager;
		_instance._lossRetryAvailable = true;
		_instance._waitingForHostChoice = false;
		_instance._restoreInProgress = false;
		_instance.LogInfo("Quota failure detected. Restart button will be added to the loss stats menu.");
		return false;
	}

	private static bool IsQuotaFailure(GameManager gameManager)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Invalid comparison between Unknown and I4
		try
		{
			if ((int)gameManager.state != 1)
			{
				return false;
			}
			MoneyManager instance = NetworkSingleton<MoneyManager>.Instance;
			return gameManager.daysLeft <= 1 && (Object)(object)instance != (Object)null && instance.balance < gameManager.currentQuota;
		}
		catch (Exception ex)
		{
			if ((Object)(object)_instance != (Object)null)
			{
				_instance.LogWarning("Failed to evaluate quota failure: " + ex);
			}
			return false;
		}
	}

	private void CaptureDayStartSnapshot()
	{
		lock (SnapshotLock)
		{
			_lossRetryAvailable = false;
			DestroyRestartButton();
			SaveManager instance = NetworkSingleton<SaveManager>.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				LogWarning("SaveManager is not available; cannot snapshot day start.");
				return;
			}
			string currentSaveName = instance.CurrentSaveName;
			if (string.IsNullOrEmpty(currentSaveName))
			{
				LogWarning("Current save name is empty; cannot snapshot day start.");
				return;
			}
			string saveDirectory = GetSaveDirectory(instance);
			string text = Path.Combine(saveDirectory, currentSaveName + ".json");
			string text2 = MakeSafeFileName(currentSaveName);
			string text3 = DateTimeOffset.UtcNow.ToString("yyyyMMdd-HHmmss");
			string text4 = Path.Combine(_snapshotDirectory, text2 + "-" + text3 + ".json");
			string text5 = Path.Combine(_snapshotDirectory, text2 + ".active-before-capture.tmp");
			bool flag = File.Exists(text);
			try
			{
				Directory.CreateDirectory(saveDirectory);
				Directory.CreateDirectory(_snapshotDirectory);
				if (flag)
				{
					File.Copy(text, text5, overwrite: true);
				}
				instance.SaveGame();
				if (!File.Exists(text))
				{
					LogWarning("SaveGame did not produce an active save file; snapshot skipped.");
					return;
				}
				File.Copy(text, text4, overwrite: true);
				_latestSnapshotPath = text4;
				_latestSaveName = currentSaveName;
				GameManager instance2 = NetworkSingleton<GameManager>.Instance;
				_latestSnapshotDaysPassed = (((Object)(object)instance2 != (Object)null) ? instance2.daysPassed : (-1));
				PruneSnapshots(text2);
				LogInfo("Captured day-start snapshot for save '" + currentSaveName + "': " + text4);
			}
			catch (Exception ex)
			{
				LogWarning("Failed to capture day-start snapshot: " + ex);
			}
			finally
			{
				try
				{
					if (flag && File.Exists(text5))
					{
						File.Copy(text5, text, overwrite: true);
					}
					else if (!flag && File.Exists(text))
					{
						File.Delete(text);
					}
					if (File.Exists(text5))
					{
						File.Delete(text5);
					}
				}
				catch (Exception ex2)
				{
					LogWarning("Failed to restore active save after snapshot capture: " + ex2);
				}
			}
		}
	}

	private bool HasUsableSnapshot()
	{
		if (string.IsNullOrEmpty(_latestSnapshotPath) || !File.Exists(_latestSnapshotPath))
		{
			return false;
		}
		GameManager val = (((Object)(object)_pendingGameManager != (Object)null) ? _pendingGameManager : NetworkSingleton<GameManager>.Instance);
		if ((Object)(object)val == (Object)null || _latestSnapshotDaysPassed < 0)
		{
			return true;
		}
		int num = val.daysPassed - _latestSnapshotDaysPassed;
		if (num >= 0)
		{
			return num <= 1;
		}
		return false;
	}

	private IEnumerator RestoreDayRoutine()
	{
		if (_restoreInProgress)
		{
			yield break;
		}
		_restoreInProgress = true;
		bool restored = false;
		try
		{
			restored = RestoreSnapshotToGame();
		}
		catch (Exception ex)
		{
			LogWarning("Restore failed: " + ex);
		}
		if (restored)
		{
			_waitingForHostChoice = false;
			_lossRetryAvailable = false;
			_pendingGameManager = null;
			ReleaseCursorControl();
			DestroyRestartButton();
			yield return null;
			NetworkManager networkManager = NetworkManager.singleton;
			if ((Object)(object)networkManager != (Object)null && NetworkServer.active)
			{
				GameManager instance = NetworkSingleton<GameManager>.Instance;
				if ((Object)(object)instance != (Object)null)
				{
					AccessTools.Field(typeof(GameManager), "_isTransitioning").SetValue(instance, true);
				}
				networkManager.ServerChangeScene("CasinoScene");
				LogInfo("Restarted failed day from snapshot.");
			}
			else
			{
				LogWarning("NetworkManager was not available after restore.");
			}
		}
		else
		{
			LogWarning("Snapshot restore failed. Continuing vanilla loss flow.");
			ContinueVanillaLoss();
		}
		_restoreInProgress = false;
	}

	private bool RestoreSnapshotToGame()
	{
		if (!HasUsableSnapshot())
		{
			return false;
		}
		SaveManager instance = NetworkSingleton<SaveManager>.Instance;
		GameManager val = (((Object)(object)_pendingGameManager != (Object)null) ? _pendingGameManager : NetworkSingleton<GameManager>.Instance);
		if ((Object)(object)instance == (Object)null || (Object)(object)val == (Object)null)
		{
			LogWarning("Required managers are missing during restore.");
			return false;
		}
		string text = (string.IsNullOrEmpty(_latestSaveName) ? instance.CurrentSaveName : _latestSaveName);
		if (string.IsNullOrEmpty(text))
		{
			LogWarning("No save name available during restore.");
			return false;
		}
		string text2 = File.ReadAllText(_latestSnapshotPath);
		SaveData val2 = JsonUtility.FromJson<SaveData>(text2);
		if (val2 == null)
		{
			LogWarning("Snapshot JSON could not be parsed.");
			return false;
		}
		val2.saveName = text;
		string path = Path.Combine(GetSaveDirectory(instance), text + ".json");
		Directory.CreateDirectory(Path.GetDirectoryName(path));
		File.WriteAllText(path, JsonUtility.ToJson((object)val2, true));
		AccessTools.Field(typeof(SaveManager), "currentSaveData").SetValue(instance, val2);
		AccessTools.Field(typeof(SaveManager), "hasLoadedGame").SetValue(instance, false);
		instance.LoadGame();
		val.Networkstate = (GameState)1;
		val.Network_timer = 0f;
		AccessTools.Field(typeof(GameManager), "_hasDayStarted").SetValue(val, false);
		AccessTools.Field(typeof(GameManager), "_isTimeOver").SetValue(val, false);
		AccessTools.Field(typeof(GameManager), "_isTransitioning").SetValue(val, false);
		return true;
	}

	private void ContinueVanillaLoss()
	{
		GameManager val = (((Object)(object)_pendingGameManager != (Object)null) ? _pendingGameManager : NetworkSingleton<GameManager>.Instance);
		_waitingForHostChoice = false;
		_lossRetryAvailable = false;
		_pendingGameManager = null;
		ReleaseCursorControl();
		DestroyRestartButton();
		if (!((Object)(object)val == (Object)null))
		{
			_continueVanillaProgression = true;
			val.ProgressGame();
		}
	}

	internal static void InstallRestartButton(GameOverUI gameOverUI)
	{
		if ((Object)(object)_instance == (Object)null || !IsEnabled || (Object)(object)gameOverUI == (Object)null || !NetworkServer.active || !NetworkClient.active)
		{
			if ((Object)(object)_instance != (Object)null)
			{
				_instance.LogInfo("Skipped Restart Day button install because this instance is not the local host.");
			}
		}
		else if (!_instance._lossRetryAvailable || !_instance.HasUsableSnapshot())
		{
			_instance.LogInfo("Skipped Restart Day button install. RetryAvailable=" + _instance._lossRetryAvailable + ", HasSnapshot=" + _instance.HasUsableSnapshot());
		}
		else
		{
			_instance.CreateRestartButton(gameOverUI);
		}
	}

	internal static void ArmLossRetryFromGameOverStats(GameManager gameManager)
	{
		if (!((Object)(object)_instance == (Object)null) && IsEnabled && !((Object)(object)gameManager == (Object)null) && NetworkServer.active)
		{
			if (!_instance.HasSnapshotFile())
			{
				_instance.LogWarning("Game over stats opened, but no day-start snapshot file exists.");
				return;
			}
			_instance._pendingGameManager = gameManager;
			_instance._lossRetryAvailable = true;
			_instance._waitingForHostChoice = false;
			_instance._restoreInProgress = false;
			_instance.LogInfo("Game over stats opened. Armed Restart Day button.");
		}
	}

	private void UpdateRestartHoldProgress()
	{
		if ((Object)(object)_restartButtonObject == (Object)null || !_lossRetryAvailable || _restoreInProgress || !NetworkServer.active || !NetworkClient.active)
		{
			_restartHoldProgress = 0f;
			UpdateHoldFillVisual();
			return;
		}
		Keyboard current = Keyboard.current;
		bool flag = current != null && current.eKey != null && ((ButtonControl)current.eKey).isPressed;
		float num = Mathf.Max(0.15f, (_restartHoldDuration != null) ? _restartHoldDuration.Value : 1.35f);
		if (flag)
		{
			_restartHoldProgress = Mathf.Min(1f, _restartHoldProgress + Time.unscaledDeltaTime / num);
		}
		else
		{
			_restartHoldProgress = 0f;
		}
		UpdateHoldFillVisual();
		if (_restartHoldProgress >= 1f && !_restoreInProgress)
		{
			_restartHoldProgress = 0f;
			if ((Object)(object)_restartButtonLabel != (Object)null)
			{
				((TMP_Text)_restartButtonLabel).text = "Restarting...";
			}
			if ((Object)(object)_holdPromptLabel != (Object)null)
			{
				((TMP_Text)_holdPromptLabel).text = "";
			}
			((MonoBehaviour)this).StartCoroutine(RestoreDayRoutine());
		}
	}

	private void UpdateHoldFillVisual()
	{
		//IL_0026: 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_0047: 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)
		if (!((Object)(object)_holdFillImage == (Object)null))
		{
			RectTransform rectTransform = ((Graphic)_holdFillImage).rectTransform;
			rectTransform.anchorMin = new Vector2(0f, 0f);
			rectTransform.anchorMax = new Vector2(_restartHoldProgress, 1f);
			rectTransform.offsetMin = Vector2.zero;
			rectTransform.offsetMax = Vector2.zero;
		}
	}

	private void CreateRestartButton(GameOverUI gameOverUI)
	{
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Expected O, but got Unknown
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_0104: Expected O, but got Unknown
		//IL_012a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0140: Unknown result type (might be due to invalid IL or missing references)
		//IL_0156: Unknown result type (might be due to invalid IL or missing references)
		//IL_016c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0182: 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_01be: 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_01db: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_021b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0229: Unknown result type (might be due to invalid IL or missing references)
		//IL_0249: Unknown result type (might be due to invalid IL or missing references)
		//IL_0255: 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_02a4: Expected O, but got Unknown
		//IL_02de: Unknown result type (might be due to invalid IL or missing references)
		//IL_0325: Unknown result type (might be due to invalid IL or missing references)
		//IL_032c: Expected O, but got Unknown
		//IL_034a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0356: Unknown result type (might be due to invalid IL or missing references)
		//IL_0362: Unknown result type (might be due to invalid IL or missing references)
		//IL_036e: Unknown result type (might be due to invalid IL or missing references)
		//IL_03af: Unknown result type (might be due to invalid IL or missing references)
		//IL_03f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_03fb: Expected O, but got Unknown
		//IL_0423: Unknown result type (might be due to invalid IL or missing references)
		//IL_0439: Unknown result type (might be due to invalid IL or missing references)
		//IL_044f: 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_047b: Unknown result type (might be due to invalid IL or missing references)
		//IL_04e8: Unknown result type (might be due to invalid IL or missing references)
		DestroyRestartButton();
		EnsureEventSystem();
		GameObject val = new GameObject("DayRetry_RestartDayCanvas", new Type[4]
		{
			typeof(RectTransform),
			typeof(Canvas),
			typeof(CanvasScaler),
			typeof(GraphicRaycaster)
		});
		Object.DontDestroyOnLoad((Object)(object)val);
		Canvas component = val.GetComponent<Canvas>();
		component.renderMode = (RenderMode)0;
		component.sortingOrder = 32000;
		CanvasScaler component2 = val.GetComponent<CanvasScaler>();
		component2.uiScaleMode = (ScaleMode)1;
		component2.referenceResolution = new Vector2(1920f, 1080f);
		component2.matchWidthOrHeight = 0.5f;
		_restartButtonObject = val;
		_restartHoldProgress = 0f;
		GameObject val2 = new GameObject("RestartDayButton", new Type[4]
		{
			typeof(RectTransform),
			typeof(CanvasRenderer),
			typeof(Image),
			typeof(Button)
		});
		val2.transform.SetParent(val.transform, false);
		RectTransform component3 = val2.GetComponent<RectTransform>();
		component3.anchorMin = new Vector2(0.5f, 0f);
		component3.anchorMax = new Vector2(0.5f, 0f);
		component3.pivot = new Vector2(0.5f, 0.5f);
		component3.anchoredPosition = new Vector2(0f, 150f);
		component3.sizeDelta = new Vector2(320f, 68f);
		Image component4 = val2.GetComponent<Image>();
		((Graphic)component4).color = new Color(0.06f, 0.62f, 0.38f, 0.96f);
		Button component5 = val2.GetComponent<Button>();
		ColorBlock colors = ((Selectable)component5).colors;
		((ColorBlock)(ref colors)).normalColor = new Color(0.06f, 0.62f, 0.38f, 0.96f);
		((ColorBlock)(ref colors)).highlightedColor = new Color(0.08f, 0.78f, 0.47f, 1f);
		((ColorBlock)(ref colors)).pressedColor = new Color(0.04f, 0.42f, 0.27f, 1f);
		((ColorBlock)(ref colors)).selectedColor = ((ColorBlock)(ref colors)).highlightedColor;
		((ColorBlock)(ref colors)).disabledColor = new Color(0.2f, 0.24f, 0.23f, 0.55f);
		((Selectable)component5).colors = colors;
		((Selectable)component5).interactable = true;
		GameObject val3 = new GameObject("HoldProgressFill", new Type[3]
		{
			typeof(RectTransform),
			typeof(CanvasRenderer),
			typeof(Image)
		});
		val3.transform.SetParent(val2.transform, false);
		_holdFillImage = val3.GetComponent<Image>();
		((Graphic)_holdFillImage).color = new Color(0f, 0f, 0f, 0.42f);
		((Graphic)_holdFillImage).raycastTarget = false;
		UpdateHoldFillVisual();
		GameObject val4 = new GameObject("Label", new Type[2]
		{
			typeof(RectTransform),
			typeof(TextMeshProUGUI)
		});
		val4.transform.SetParent(val2.transform, false);
		RectTransform component6 = val4.GetComponent<RectTransform>();
		component6.anchorMin = Vector2.zero;
		component6.anchorMax = Vector2.one;
		component6.offsetMin = Vector2.zero;
		component6.offsetMax = Vector2.zero;
		TextMeshProUGUI component7 = val4.GetComponent<TextMeshProUGUI>();
		((TMP_Text)component7).text = "Restart Day";
		((TMP_Text)component7).fontSize = 24f;
		((TMP_Text)component7).fontStyle = (FontStyles)1;
		((TMP_Text)component7).alignment = (TextAlignmentOptions)514;
		((Graphic)component7).color = Color.white;
		((Graphic)component7).raycastTarget = false;
		_restartButtonLabel = component7;
		GameObject val5 = new GameObject("HoldPrompt", new Type[2]
		{
			typeof(RectTransform),
			typeof(TextMeshProUGUI)
		});
		val5.transform.SetParent(val.transform, false);
		RectTransform component8 = val5.GetComponent<RectTransform>();
		component8.anchorMin = new Vector2(0.5f, 0f);
		component8.anchorMax = new Vector2(0.5f, 0f);
		component8.pivot = new Vector2(0.5f, 0.5f);
		component8.anchoredPosition = new Vector2(0f, 96f);
		component8.sizeDelta = new Vector2(320f, 34f);
		_holdPromptLabel = val5.GetComponent<TextMeshProUGUI>();
		((TMP_Text)_holdPromptLabel).text = "Hold E";
		((TMP_Text)_holdPromptLabel).fontSize = 21f;
		((TMP_Text)_holdPromptLabel).fontStyle = (FontStyles)1;
		((TMP_Text)_holdPromptLabel).alignment = (TextAlignmentOptions)514;
		((Graphic)_holdPromptLabel).color = new Color(1f, 0.94f, 0.72f, 1f);
		((Graphic)_holdPromptLabel).raycastTarget = false;
		val2.transform.SetAsLastSibling();
		LogInfo("Added Restart Day button overlay to the loss stats menu.");
	}

	private void DestroyRestartButton()
	{
		if (!((Object)(object)_restartButtonObject == (Object)null))
		{
			Object.Destroy((Object)(object)_restartButtonObject);
			_restartButtonObject = null;
			_holdFillImage = null;
			_restartButtonLabel = null;
			_holdPromptLabel = null;
			_restartHoldProgress = 0f;
		}
	}

	private bool HasSnapshotFile()
	{
		if (!string.IsNullOrEmpty(_latestSnapshotPath))
		{
			return File.Exists(_latestSnapshotPath);
		}
		return false;
	}

	private static void EnsureEventSystem()
	{
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Expected O, but got Unknown
		if (!((Object)(object)Object.FindAnyObjectByType<EventSystem>() != (Object)null))
		{
			GameObject val = new GameObject("DayRetry_EventSystem", new Type[2]
			{
				typeof(EventSystem),
				typeof(InputSystemUIInputModule)
			});
			Object.DontDestroyOnLoad((Object)(object)val);
		}
	}

	private void OnGUI()
	{
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Expected O, but got Unknown
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		if (_waitingForHostChoice && !_restoreInProgress && NetworkServer.active && NetworkClient.active)
		{
			TakeCursorControl();
			EnsureGuiStyles();
			UpdateWindowPosition();
			_windowRect = GUI.ModalWindow(903204, _windowRect, new WindowFunction(DrawRestartWindow), GUIContent.none, _windowStyle);
			DrawHostCursor();
		}
	}

	private void TakeCursorControl()
	{
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		if (!_hasCursorOverride)
		{
			_previousCursorVisible = Cursor.visible;
			_previousCursorLockState = Cursor.lockState;
			_hasCursorOverride = true;
		}
		if ((int)Cursor.lockState != 0)
		{
			Cursor.lockState = (CursorLockMode)0;
		}
		Cursor.SetCursor((Texture2D)null, Vector2.zero, (CursorMode)0);
		if (!Cursor.visible)
		{
			Cursor.visible = true;
		}
	}

	private void ReleaseCursorControl()
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		if (_hasCursorOverride)
		{
			Cursor.visible = _previousCursorVisible;
			Cursor.lockState = _previousCursorLockState;
			_hasCursorOverride = false;
		}
	}

	private void DrawHostCursor()
	{
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Invalid comparison between Unknown and I4
		//IL_003d: 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_005b: Unknown result type (might be due to invalid IL or missing references)
		Event current = Event.current;
		if (current != null && (int)current.type == 7)
		{
			if ((Object)(object)_cursorTexture == (Object)null)
			{
				_cursorTexture = CreateCursorTexture();
			}
			int depth = GUI.depth;
			GUI.depth = -10000;
			Vector2 mousePosition = current.mousePosition;
			GUI.DrawTexture(new Rect(mousePosition.x, mousePosition.y, 28f, 28f), (Texture)(object)_cursorTexture);
			GUI.depth = depth;
		}
	}

	private void DrawRestartWindow(int id)
	{
		//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d6: Invalid comparison between Unknown and I4
		//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: Invalid comparison between Unknown and I4
		//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ed: Invalid comparison between Unknown and I4
		//IL_010d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0114: Invalid comparison between Unknown and I4
		GUILayout.Space(16f);
		GUILayout.Label("Quota Failed", _titleStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
		GUILayout.Space(8f);
		GUILayout.Label("Restart from the beginning of this day before the run is lost.", _bodyStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
		GUILayout.Space(18f);
		GUI.enabled = HasUsableSnapshot();
		if (GUILayout.Button("Restart Day", _primaryButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(48f) }))
		{
			((MonoBehaviour)this).StartCoroutine(RestoreDayRoutine());
		}
		GUI.enabled = true;
		GUILayout.Space(8f);
		if (GUILayout.Button("Continue Loss", _secondaryButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(34f) }))
		{
			ContinueVanillaLoss();
		}
		Event current = Event.current;
		if (current != null && (int)current.type == 4)
		{
			if ((int)current.keyCode == 13 || (int)current.keyCode == 271)
			{
				if (HasUsableSnapshot())
				{
					((MonoBehaviour)this).StartCoroutine(RestoreDayRoutine());
					current.Use();
				}
			}
			else if ((int)current.keyCode == 27)
			{
				ContinueVanillaLoss();
				current.Use();
			}
		}
		GUI.DragWindow();
	}

	private void EnsureGuiStyles()
	{
		//IL_001d: 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_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Expected O, but got Unknown
		//IL_009a: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: Expected O, but got Unknown
		//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: Expected O, but got Unknown
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cd: Expected O, but got Unknown
		//IL_0111: 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_0130: Expected O, but got Unknown
		//IL_0174: Unknown result type (might be due to invalid IL or missing references)
		//IL_0189: Unknown result type (might be due to invalid IL or missing references)
		//IL_0193: Expected O, but got Unknown
		//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0214: Unknown result type (might be due to invalid IL or missing references)
		//IL_0229: Unknown result type (might be due to invalid IL or missing references)
		//IL_0233: Expected O, but got Unknown
		//IL_0292: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
		if (_windowStyle == null)
		{
			Texture2D background = MakeTexture(new Color(0.035f, 0.04f, 0.055f, 0.96f));
			Texture2D background2 = MakeTexture(new Color(0.08f, 0.55f, 0.35f, 1f));
			Texture2D background3 = MakeTexture(new Color(0.17f, 0.19f, 0.23f, 1f));
			_windowStyle = new GUIStyle(GUI.skin.window);
			_windowStyle.normal.background = background;
			_windowStyle.padding = new RectOffset(24, 24, 18, 20);
			_windowStyle.border = new RectOffset(8, 8, 8, 8);
			_titleStyle = new GUIStyle(GUI.skin.label);
			_titleStyle.fontSize = 24;
			_titleStyle.fontStyle = (FontStyle)1;
			_titleStyle.alignment = (TextAnchor)4;
			_titleStyle.normal.textColor = new Color(1f, 0.93f, 0.72f, 1f);
			_bodyStyle = new GUIStyle(GUI.skin.label);
			_bodyStyle.fontSize = 15;
			_bodyStyle.wordWrap = true;
			_bodyStyle.alignment = (TextAnchor)4;
			_bodyStyle.normal.textColor = new Color(0.9f, 0.92f, 0.96f, 1f);
			_primaryButtonStyle = new GUIStyle(GUI.skin.button);
			_primaryButtonStyle.fontSize = 18;
			_primaryButtonStyle.fontStyle = (FontStyle)1;
			_primaryButtonStyle.normal.background = background2;
			_primaryButtonStyle.hover.background = background2;
			_primaryButtonStyle.active.background = background2;
			_primaryButtonStyle.normal.textColor = Color.white;
			_primaryButtonStyle.hover.textColor = Color.white;
			_primaryButtonStyle.active.textColor = Color.white;
			_secondaryButtonStyle = new GUIStyle(GUI.skin.button);
			_secondaryButtonStyle.fontSize = 13;
			_secondaryButtonStyle.normal.background = background3;
			_secondaryButtonStyle.hover.background = background3;
			_secondaryButtonStyle.active.background = background3;
			_secondaryButtonStyle.normal.textColor = new Color(0.88f, 0.9f, 0.94f, 1f);
			_secondaryButtonStyle.hover.textColor = Color.white;
			_secondaryButtonStyle.active.textColor = Color.white;
		}
	}

	private static Texture2D MakeTexture(Color color)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Expected O, but got Unknown
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		Texture2D val = new Texture2D(1, 1);
		val.SetPixel(0, 0, color);
		val.Apply();
		return val;
	}

	private static Texture2D CreateCursorTexture()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Expected O, but got Unknown
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0139: Unknown result type (might be due to invalid IL or missing references)
		//IL_0144: 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)
		Texture2D val = new Texture2D(24, 24, (TextureFormat)5, false);
		Color val2 = default(Color);
		((Color)(ref val2))..ctor(0f, 0f, 0f, 0f);
		Color val3 = default(Color);
		((Color)(ref val3))..ctor(0f, 0f, 0f, 0.95f);
		Color val4 = default(Color);
		((Color)(ref val4))..ctor(1f, 1f, 1f, 1f);
		for (int i = 0; i < 24; i++)
		{
			for (int j = 0; j < 24; j++)
			{
				val.SetPixel(j, i, val2);
			}
		}
		for (int k = 1; k < 20; k++)
		{
			int num = Mathf.Max(1, k / 2 + 1);
			for (int l = 1; l <= num; l++)
			{
				val.SetPixel(l, 23 - k, val3);
			}
		}
		for (int m = 3; m < 16; m++)
		{
			int num2 = Mathf.Max(1, m / 2);
			for (int n = 3; n <= num2; n++)
			{
				val.SetPixel(n, 23 - m, val4);
			}
		}
		for (int num3 = 5; num3 < 11; num3++)
		{
			for (int num4 = 8; num4 < 12; num4++)
			{
				val.SetPixel(num4, 23 - num3, val3);
			}
		}
		val.SetPixel(9, 14, val4);
		val.SetPixel(10, 13, val4);
		val.Apply();
		return val;
	}

	private void UpdateWindowPosition()
	{
		float x = ((float)Screen.width - ((Rect)(ref _windowRect)).width) * 0.5f;
		float y = ((float)Screen.height - ((Rect)(ref _windowRect)).height) * 0.5f;
		string text = (_buttonAnchor.Value ?? "Center").Trim().ToLowerInvariant();
		if (text == "top")
		{
			y = 80f;
		}
		else if (text == "bottom")
		{
			y = Mathf.Max(80f, (float)Screen.height - ((Rect)(ref _windowRect)).height - 90f);
		}
		((Rect)(ref _windowRect)).x = x;
		((Rect)(ref _windowRect)).y = y;
	}

	private static string GetSaveDirectory(SaveManager saveManager)
	{
		return (string)AccessTools.Property(typeof(SaveManager), "SaveDirectoryPath").GetValue(saveManager, null);
	}

	private static string MakeSafeFileName(string value)
	{
		char[] invalidFileNameChars = Path.GetInvalidFileNameChars();
		foreach (char oldChar in invalidFileNameChars)
		{
			value = value.Replace(oldChar, '_');
		}
		return value;
	}

	private void PruneSnapshots(string safeSaveName)
	{
		int num = Mathf.Max(1, _snapshotBackupsToKeep.Value);
		FileInfo[] files = new DirectoryInfo(_snapshotDirectory).GetFiles(safeSaveName + "-*.json");
		Array.Sort(files, (FileInfo a, FileInfo b) => b.CreationTimeUtc.CompareTo(a.CreationTimeUtc));
		for (int i = num; i < files.Length; i++)
		{
			try
			{
				files[i].Delete();
			}
			catch (Exception ex)
			{
				LogWarning("Failed to prune old snapshot '" + files[i].FullName + "': " + ex.Message);
			}
		}
	}

	private void LogInfo(string message)
	{
		if (_showDebugLogs == null || _showDebugLogs.Value)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)message);
		}
	}

	private void LogWarning(string message)
	{
		((BaseUnityPlugin)this).Logger.LogWarning((object)message);
	}
}