Decompiled source of QuickRestart v3.1.89

QuickRestart.dll

Decompiled 13 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.InputSystem;
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: AssemblyCompany("QuickRestart")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+757791390981cd33951aaf2d51e0cfb4294c8a26")]
[assembly: AssemblyProduct("QuickRestart")]
[assembly: AssemblyTitle("QuickRestart")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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 QuickRestart
{
	[BepInPlugin("com.ttr.quickrestart", "QuickRestart", "3.1.89")]
	public class QuickRestartPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.ttr.quickrestart";

		public const string PluginName = "QuickRestart";

		public const string PluginVersion = "3.1.89";

		internal static ManualLogSource Logger;

		private const KeyCode CancelDayKey = (KeyCode)290;

		private const string CancelDayBinding = "<Keyboard>/f9";

		private const float RestartTimeoutSeconds = 90f;

		private static QuickRestartPlugin _instance;

		internal static bool _isCancelling;

		private InputAction _cancelDayAction;

		private InputAction _fastForwardAction;

		private const string F8Binding = "<Keyboard>/f8";

		private void Awake()
		{
			_instance = this;
			Logger = ((BaseUnityPlugin)this).Logger;
			Harmony.CreateAndPatchAll(typeof(Patches), "com.ttr.quickrestart");
			Logger.LogInfo((object)string.Format("{0} v{1} loaded! Press {2} or use the pause menu to restart the current run.", "QuickRestart", "3.1.89", (object)(KeyCode)290));
		}

		private void OnDestroy()
		{
			if (_cancelDayAction != null)
			{
				_cancelDayAction.performed -= OnCancelDayPerformed;
				_cancelDayAction.Disable();
				_cancelDayAction.Dispose();
				_cancelDayAction = null;
			}
		}

		private static void OnCancelDayPerformed(CallbackContext _)
		{
			CancelDay();
		}

		private static void OnF8Performed(CallbackContext _)
		{
			FastForwardToDeadline();
		}

		internal static void EnsureCancelDayActionReady()
		{
			_instance?.EnsureCancelDayAction();
		}

		private void EnsureCancelDayAction()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			if (_cancelDayAction != null)
			{
				return;
			}
			try
			{
				_cancelDayAction = new InputAction("QuickRestartCancelDay", (InputActionType)1, "<Keyboard>/f9", (string)null, (string)null, (string)null);
				_cancelDayAction.performed += OnCancelDayPerformed;
				_cancelDayAction.Enable();
				Logger.LogInfo((object)"[QuickRestart] F9 restart binding ready.");
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("[QuickRestart] F9 restart binding could not be initialized yet: " + ex.Message));
				_cancelDayAction = null;
			}
		}

		internal static void FastForwardToDeadline()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Invalid comparison between Unknown and I4
			if (_isCancelling)
			{
				Logger.LogWarning((object)"[QuickRestart] F8 fast-forward blocked — cancellation in progress.");
				return;
			}
			Bootstrap val = Object.FindObjectOfType<Bootstrap>();
			if ((Object)(object)val == (Object)null || (int)val.State != 1)
			{
				Logger.LogInfo((object)"[QuickRestart] F8 fast-forward skipped — not in-game.");
				return;
			}
			GameProgressionManager instance = GameProgressionManager.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				Logger.LogInfo((object)"[QuickRestart] F8 fast-forward skipped — no GameProgressionManager.");
				return;
			}
			float num = instance.MaxSeconds - 60f;
			SetNetworkVar(instance, "n_currentGameTime", Mathf.Max(0f, num));
			Logger.LogInfo((object)$"[QuickRestart] Fast-forwarded: maxSeconds={instance.MaxSeconds}, set to t={num:F1} (~1 real min before deadline).");
		}

		internal static void CancelDay()
		{
			if (_isCancelling)
			{
				Logger.LogInfo((object)"[QuickRestart] Restart/cancel already in progress.");
				return;
			}
			if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsHost)
			{
				Logger.LogInfo((object)"[QuickRestart] Only the host can cancel the day.");
				return;
			}
			Bootstrap val = Object.FindObjectOfType<Bootstrap>();
			if ((Object)(object)val == (Object)null)
			{
				Logger.LogInfo((object)"[QuickRestart] Bootstrap not found.");
				return;
			}
			GameProgressionManager instance = GameProgressionManager.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				Logger.LogWarning((object)"[QuickRestart] GameProgressionManager not found.");
				return;
			}
			_isCancelling = true;
			RunCoroutine(RestartCurrentOrLastRun(val, instance));
		}

		private static IEnumerator RestartCurrentOrLastRun(Bootstrap bootstrap, GameProgressionManager progression)
		{
			try
			{
				Logger.LogInfo((object)$"[QuickRestart] Restart requested from {bootstrap.State} (transition: {IsInTransition()}).");
				bool transitionInProgress = IsInTransition();
				GameProgressionManager obj = progression;
				bool flag = (Object)(object)((obj != null) ? obj.Deposit : null) != (Object)null && (progression.Deposit.PapyrusIsAnimating || progression.Deposit.PreventingRespawns);
				if (!(transitionInProgress || flag) && !Patches.AnyPlayerDead())
				{
					Patches.HasLastGoodEquipment();
				}
				if ((int)bootstrap.State == 1)
				{
					Logger.LogInfo((object)$"[QuickRestart] Ending current run via owned instant transition (nativeTransition={transitionInProgress}, deadline={flag}, deadPlayers={Patches.AnyPlayerDead()}).");
					Patches.PrepareForOwnedInstantRestart(bootstrap, progression);
					if (!Patches.TryStartInstantLobbyTransition(bootstrap, (GameEndedReason)0, allowActiveTransition: true))
					{
						yield break;
					}
				}
				else if ((int)bootstrap.State != 0 && !transitionInProgress)
				{
					Logger.LogInfo((object)$"[QuickRestart] Cannot restart from game state {bootstrap.State}.");
					yield break;
				}
				yield return WaitForLobbyReady(bootstrap);
				bootstrap = Object.FindObjectOfType<Bootstrap>();
				progression = GameProgressionManager.Instance;
				if ((Object)(object)bootstrap == (Object)null || (int)bootstrap.State != 0 || IsInTransition())
				{
					if (!transitionInProgress)
					{
						Logger.LogWarning((object)"[QuickRestart] Timed out waiting for lobby/post-loss state.");
						yield break;
					}
					if (!IsInTransition() && (Object)(object)bootstrap != (Object)null && (int)bootstrap.State != 0)
					{
						Logger.LogInfo((object)"[QuickRestart] Native completed lobby but didn't set State; applying state.");
						typeof(Bootstrap).GetField("gameState", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(bootstrap, (object)(GameState)0);
					}
					else
					{
						Logger.LogInfo((object)"[QuickRestart] Native transition timed out; falling back to forced transition.");
						Patches.TryStartInstantLobbyTransition(bootstrap ?? Object.FindObjectOfType<Bootstrap>(), (GameEndedReason)0, allowActiveTransition: true);
						yield return WaitForLobbyReady(bootstrap ?? Object.FindObjectOfType<Bootstrap>());
						bootstrap = Object.FindObjectOfType<Bootstrap>();
						progression = GameProgressionManager.Instance;
						if ((Object)(object)bootstrap == (Object)null || (int)bootstrap.State != 0 || IsInTransition())
						{
							Logger.LogWarning((object)"[QuickRestart] Forced transition also failed.");
							yield break;
						}
					}
				}
				Logger.LogInfo((object)"[QuickRestart] Lobby reached; cleaning up post-transition state then recovering.");
				Patches.CancelActiveVortex(Patches.GetCurrentGnomeHouse());
				Patches.StopTaskCallbacks();
				if (Patches._depositWorldSaved)
				{
					GnomeHouse currentGnomeHouse = Patches.GetCurrentGnomeHouse();
					if ((Object)(object)((currentGnomeHouse != null) ? currentGnomeHouse.GnomiumDeposit : null) != (Object)null)
					{
						try
						{
							Transform transform = ((Component)currentGnomeHouse.GnomiumDeposit).transform;
							transform.position = Patches._savedDepositWorldPos;
							transform.rotation = Patches._savedDepositWorldRot;
							Logger.LogInfo((object)$"[QuickRestart] Restored deposit box (recovery path): worldPos={Patches._savedDepositWorldPos}");
						}
						catch (Exception ex)
						{
							Logger.LogWarning((object)("[QuickRestart] Failed to restore deposit box (recovery path): " + ex.Message));
						}
					}
				}
				if ((Object)(object)progression != (Object)null)
				{
					progression.SelectedLevelIndex = -1;
				}
				Patches.UseLastGoodEquipment();
				ForceLobbyReady(progression);
				ClearTaskListAndHints();
				ResetPlayerControllerUiState();
				yield return Patches.RecoverLobbyPlayersAndEquipment();
				try
				{
					Type type = Type.GetType("ControllerSupport.ControllerSupportPlugin, ControllerSupport");
					if (type != null)
					{
						type.GetMethod("OnGameRestarted", BindingFlags.Static | BindingFlags.Public)?.Invoke(null, null);
						Logger.LogInfo((object)"[QuickRestart] Called ControllerSupport.OnGameRestarted.");
					}
				}
				catch (Exception ex2)
				{
					Logger.LogWarning((object)("[QuickRestart] ControllerSupport.OnGameRestarted failed: " + ex2.Message));
				}
				Logger.LogInfo((object)"[QuickRestart] Restart recovery complete; staying in lobby.");
			}
			finally
			{
				FinishCancel();
			}
		}

		private static IEnumerator WaitForLobbyReady(Bootstrap bootstrap, float timeoutSeconds = 90f)
		{
			float elapsed = 0f;
			while ((Object)(object)bootstrap != (Object)null && ((int)bootstrap.State != 0 || IsInTransition()))
			{
				elapsed += Time.unscaledDeltaTime;
				if (elapsed > timeoutSeconds)
				{
					break;
				}
				yield return null;
			}
		}

		internal static void FinishCancel()
		{
			_isCancelling = false;
		}

		internal static void RunCoroutine(IEnumerator routine)
		{
			QuickRestartPlugin instance = _instance;
			if (instance != null)
			{
				((MonoBehaviour)instance).StartCoroutine(routine);
			}
		}

		internal static bool IsInTransition()
		{
			Bootstrap val = Object.FindObjectOfType<Bootstrap>();
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			FieldInfo field = typeof(Bootstrap).GetField("gameTransitionInProgress", BindingFlags.Instance | BindingFlags.NonPublic);
			if (field != null)
			{
				return (bool)field.GetValue(val);
			}
			return false;
		}

		internal static T GetPrivate<T>(object obj, string fieldName)
		{
			FieldInfo field = obj.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
			if (field == null)
			{
				return default(T);
			}
			object value = field.GetValue(obj);
			if (value is T)
			{
				return (T)value;
			}
			return default(T);
		}

		internal static bool IsUnityObjectAlive(object obj)
		{
			if (obj == null)
			{
				return false;
			}
			Object val = (Object)((obj is Object) ? obj : null);
			if (val != null)
			{
				return val != (Object)null;
			}
			return true;
		}

		internal static void SetNetworkVar<T>(object obj, string fieldName, T value)
		{
			if (obj.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(obj) is NetworkVariable<T> val)
			{
				val.Value = value;
			}
			else
			{
				Logger.LogWarning((object)("[QuickRestart] Could not set " + fieldName + "."));
			}
		}

		internal static void HideDeathOverlay()
		{
			//IL_00cf: 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)
			if ((Object)(object)_instance == (Object)null)
			{
				return;
			}
			string[] array = new string[6] { "DeathOverlay", "DeathScreen", "GameOver", "GameOverScreen", "ContinuePanel", "ContinueScreen" };
			foreach (string text in array)
			{
				try
				{
					GameObject val = GameObject.Find(text);
					if ((Object)(object)val != (Object)null && val.activeInHierarchy)
					{
						Logger.LogInfo((object)("[QuickRestart] Found and hiding death overlay: " + text));
						val.SetActive(false);
						return;
					}
				}
				catch
				{
				}
			}
			try
			{
				Canvas[] array2 = Object.FindObjectsOfType<Canvas>();
				foreach (Canvas val2 in array2)
				{
					if ((Object)(object)val2 == (Object)null || !((Component)val2).gameObject.activeInHierarchy)
					{
						continue;
					}
					Scene scene = ((Component)val2).gameObject.scene;
					if (((Scene)(ref scene)).name == "DontDestroyOnLoad")
					{
						continue;
					}
					TMP_Text[] componentsInChildren = ((Component)val2).GetComponentsInChildren<TMP_Text>(true);
					foreach (TMP_Text val3 in componentsInChildren)
					{
						if (!((Object)(object)val3 == (Object)null) && !string.IsNullOrEmpty(val3.text))
						{
							string text2 = val3.text.ToLowerInvariant();
							if (text2.Contains("continue") || text2.Contains("game over") || text2.Contains("you died") || text2.Contains("death"))
							{
								Logger.LogInfo((object)("[QuickRestart] Hiding death overlay (found text: '" + val3.text + "')"));
								((Component)val2).gameObject.SetActive(false);
								return;
							}
						}
					}
				}
			}
			catch
			{
			}
			Logger.LogInfo((object)"[QuickRestart] Could not find death overlay to hide.");
		}

		internal static void ClickContinueButton()
		{
			try
			{
				Button[] array = Object.FindObjectsOfType<Button>(true);
				foreach (Button val in array)
				{
					if (!((Object)(object)val == (Object)null) && ((Component)val).gameObject.activeInHierarchy && ((Selectable)val).interactable)
					{
						TMP_Text componentInChildren = ((Component)val).GetComponentInChildren<TMP_Text>(true);
						if ((Object)(object)componentInChildren != (Object)null && componentInChildren.text.ToLowerInvariant().Contains("continue"))
						{
							Logger.LogInfo((object)("[QuickRestart] Clicking Continue button (text: '" + componentInChildren.text + "')."));
							((UnityEvent)val.onClick).Invoke();
							return;
						}
					}
				}
				Logger.LogInfo((object)"[QuickRestart] Could not find Continue button.");
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("[QuickRestart] Exception finding Continue button: " + ex.Message));
			}
		}

		internal static void ClearTaskListAndHints()
		{
			//IL_0537: Unknown result type (might be due to invalid IL or missing references)
			//IL_0578: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				PlayerController[] array = Object.FindObjectsOfType<PlayerController>(false);
				Logger.LogInfo((object)$"[QuickRestart] Found {array.Length} PlayerController(s) in lobby.");
				PlayerController[] array2 = array;
				foreach (PlayerController val in array2)
				{
					if ((Object)(object)val == (Object)null)
					{
						Logger.LogInfo((object)"[QuickRestart]   PlayerController is null (Unity-destroyed).");
						continue;
					}
					ManualLogSource logger = Logger;
					GameObject gameObject = ((Component)val).gameObject;
					logger.LogInfo((object)string.Format("[QuickRestart]   Player: {0} active={1}", ((gameObject != null) ? ((Object)gameObject).name : null) ?? "(no GO)", ((Behaviour)val).isActiveAndEnabled));
					FieldInfo field = typeof(PlayerController).GetField("taskPanel", BindingFlags.Instance | BindingFlags.NonPublic);
					object obj = field?.GetValue(val);
					Logger.LogInfo((object)string.Format("[QuickRestart]   taskPanel field found={0}, value={1}", field != null, obj?.GetType().Name ?? "null"));
					GameObject val2 = (GameObject)((obj is GameObject) ? obj : null);
					if (val2 != null)
					{
						val2.SetActive(false);
						Logger.LogInfo((object)$"[QuickRestart]   Disabled task panel \"{((Object)val2).name}\" activeBefore={val2.activeSelf}.");
					}
					FieldInfo field2 = typeof(PlayerController).GetField("DescriptionDisplayer", BindingFlags.Instance | BindingFlags.NonPublic);
					object obj2 = field2?.GetValue(val);
					Logger.LogInfo((object)string.Format("[QuickRestart]   DescriptionDisplayer field found={0}, value={1}", field2 != null, obj2?.GetType().Name ?? "null"));
					DescriptionDisplayer val3 = (DescriptionDisplayer)((obj2 is DescriptionDisplayer) ? obj2 : null);
					if (val3 != null)
					{
						val3.DisableTaskList();
						val3.ClearTaskList();
						Logger.LogInfo((object)"[QuickRestart]   Called DisableTaskList and ClearTaskList.");
					}
				}
				GameProgressionManager instance = GameProgressionManager.Instance;
				if (!((Object)(object)instance != (Object)null))
				{
					return;
				}
				if (typeof(GameProgressionManager).GetField("onGameEnded", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(instance) is Delegate obj3)
				{
					Delegate[] invocationList = obj3.GetInvocationList();
					foreach (Delegate obj4 in invocationList)
					{
						Logger.LogInfo((object)("[QuickRestart] onGameEnded subscriber: " + obj4.Target?.GetType().FullName + "." + obj4.Method?.Name));
					}
					Dictionary<int, bool> dictionary = new Dictionary<int, bool>();
					Canvas[] array3 = Object.FindObjectsOfType<Canvas>(false);
					foreach (Canvas val4 in array3)
					{
						if ((Object)(object)val4 != (Object)null)
						{
							dictionary[((Object)val4).GetInstanceID()] = ((Behaviour)val4).isActiveAndEnabled;
						}
					}
					object obj5 = typeof(GameProgressionManager).GetField("n_day", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(instance);
					PropertyInfo propertyInfo = obj5?.GetType().GetProperty("Value", BindingFlags.Instance | BindingFlags.Public);
					int num = 0;
					if (obj5 != null && propertyInfo != null)
					{
						num = (int)(propertyInfo.GetValue(obj5) ?? ((object)0));
					}
					Logger.LogInfo((object)"[QuickRestart] Firing onGameEnded event manually as PLAYER_ACTION.");
					obj3.DynamicInvoke((object)(GameEndedReason)0);
					if (obj5 != null && propertyInfo != null)
					{
						int num2 = (int)propertyInfo.GetValue(obj5);
						if (num2 != num)
						{
							propertyInfo.SetValue(obj5, num);
							Logger.LogInfo((object)$"[QuickRestart] Restored day counter from {num2} to {num}.");
						}
					}
					object obj6 = typeof(GameProgressionManager).GetField("n_currentGameTime", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(instance);
					PropertyInfo propertyInfo2 = obj6?.GetType().GetProperty("Value", BindingFlags.Instance | BindingFlags.Public);
					if (obj6 != null && propertyInfo2 != null)
					{
						float num3 = (float)propertyInfo2.GetValue(obj6);
						if (num3 > 5f)
						{
							propertyInfo2.SetValue(obj6, 0f);
							Logger.LogInfo((object)$"[QuickRestart] Reset game time from {num3:F1}s to 0s.");
						}
					}
					array3 = Object.FindObjectsOfType<Canvas>(false);
					foreach (Canvas val5 in array3)
					{
						if (!((Object)(object)val5 == (Object)null))
						{
							int instanceID = ((Object)val5).GetInstanceID();
							bool value;
							bool flag = dictionary.TryGetValue(instanceID, out value);
							bool isActiveAndEnabled = ((Behaviour)val5).isActiveAndEnabled;
							if (!flag && isActiveAndEnabled)
							{
								Logger.LogInfo((object)$"[QuickRestart] NEW active Canvas after event: \"{((Object)val5).name}\" order={val5.sortingOrder} — disabling.");
								((Component)val5).gameObject.SetActive(false);
							}
							else if (flag && !value && isActiveAndEnabled)
							{
								Logger.LogInfo((object)$"[QuickRestart] ACTIVATED Canvas after event: \"{((Object)val5).name}\" order={val5.sortingOrder} — disabling.");
								((Component)val5).gameObject.SetActive(false);
							}
						}
					}
					Type type = Type.GetType("UnityEngine.UIElements.UIDocument, UnityEngine.UIElements, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null");
					if (!(type != null))
					{
						return;
					}
					HashSet<int> hashSet = new HashSet<int>();
					Object[] array4 = Resources.FindObjectsOfTypeAll(type);
					for (int i = 0; i < array4.Length; i++)
					{
						GameObject gameObject2 = ((Component)array4[i]).gameObject;
						if ((Object)(object)gameObject2 != (Object)null)
						{
							hashSet.Add(((Object)gameObject2).GetInstanceID());
						}
					}
					array4 = Resources.FindObjectsOfTypeAll(type);
					for (int i = 0; i < array4.Length; i++)
					{
						GameObject gameObject3 = ((Component)array4[i]).gameObject;
						if (!((Object)(object)gameObject3 == (Object)null) && gameObject3.activeInHierarchy && !hashSet.Contains(((Object)gameObject3).GetInstanceID()))
						{
							Logger.LogInfo((object)("[QuickRestart] NEW active UIDocument after event: \"" + ((Object)gameObject3).name + "\" — disabling."));
							gameObject3.SetActive(false);
						}
					}
				}
				else
				{
					Logger.LogInfo((object)"[QuickRestart] Could not access onGameEnded event backing field (no subscribers?).");
				}
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("[QuickRestart] ClearTaskListAndHints exception: " + ex.Message));
			}
		}

		internal static IEnumerator DelayedLobbyReinitialize(Bootstrap bootstrap)
		{
			yield return null;
			if ((Object)(object)bootstrap == (Object)null)
			{
				yield break;
			}
			LobbyManager component = ((Component)bootstrap).GetComponent<LobbyManager>();
			string[] array;
			if ((Object)(object)component != (Object)null)
			{
				array = new string[5] { "OnEnteredLobby", "OnLobbyReady", "OnLobbyEntered", "Initialize", "SetupLobby" };
				foreach (string text in array)
				{
					try
					{
						MethodInfo method = typeof(LobbyManager).GetMethod(text, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
						if (method != null && method.GetParameters().Length == 0)
						{
							Logger.LogInfo((object)("[QuickRestart] Calling LobbyManager." + text + "()"));
							method.Invoke(component, null);
						}
					}
					catch
					{
					}
				}
			}
			array = new string[6] { "Well", "WellOfCreation", "Bell", "TownBell", "Stockpile", "TownStockpile" };
			foreach (string text2 in array)
			{
				try
				{
					GameObject val = GameObject.Find(text2);
					if ((Object)(object)val != (Object)null && val.activeInHierarchy)
					{
						Logger.LogInfo((object)("[QuickRestart] Force-reinitializing lobby object: " + text2));
						val.SetActive(false);
						val.SetActive(true);
					}
				}
				catch
				{
				}
			}
		}

		internal static void ForceLobbyReady(GameProgressionManager progression)
		{
			if ((Object)(object)progression == (Object)null)
			{
				return;
			}
			try
			{
				Type type = ((object)progression).GetType();
				FieldInfo field = type.GetField("n_timeActive", BindingFlags.Instance | BindingFlags.NonPublic);
				if (field != null)
				{
					object value = field.GetValue(progression);
					PropertyInfo propertyInfo = value?.GetType().GetProperty("Value");
					if (propertyInfo != null && propertyInfo.PropertyType == typeof(bool))
					{
						propertyInfo.SetValue(value, false);
					}
				}
				FieldInfo field2 = type.GetField("n_gameState", BindingFlags.Instance | BindingFlags.NonPublic);
				if (field2 != null)
				{
					object value2 = field2.GetValue(progression);
					PropertyInfo propertyInfo2 = value2?.GetType().GetProperty("Value");
					if (propertyInfo2 != null && propertyInfo2.PropertyType.IsEnum)
					{
						object value3 = Enum.ToObject(propertyInfo2.PropertyType, 0);
						propertyInfo2.SetValue(value2, value3);
					}
				}
				GnomiumDeposit deposit = progression.Deposit;
				if ((Object)(object)deposit != (Object)null)
				{
					Type type2 = ((object)deposit).GetType();
					FieldInfo field3 = type2.GetField("preventRespawning", BindingFlags.Instance | BindingFlags.NonPublic);
					if (field3 != null && field3.FieldType == typeof(bool))
					{
						field3.SetValue(deposit, false);
					}
					FieldInfo field4 = type2.GetField("papyrusInProgress", BindingFlags.Instance | BindingFlags.NonPublic);
					if (field4 != null && field4.FieldType == typeof(bool))
					{
						field4.SetValue(deposit, false);
					}
				}
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("[QuickRestart] ForceLobbyReady exception: " + ex.Message));
			}
			ResetPlayerControllerUiState();
			HideGameOverScreen();
			Logger.LogInfo((object)"[QuickRestart] Lobby state forced to interactive.");
		}

		internal static void HideGameOverScreen()
		{
			try
			{
				GameObject[] array = Resources.FindObjectsOfTypeAll<GameObject>();
				foreach (GameObject val in array)
				{
					if (val.activeInHierarchy)
					{
						string name = ((Object)val).name;
						if (name.IndexOf("GameOver", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("DeadCanvas", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("GameOverlay", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("EndGame", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("Recap", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("text_gameover", StringComparison.OrdinalIgnoreCase) >= 0)
						{
							val.SetActive(false);
							Logger.LogInfo((object)("[QuickRestart] Hid screen: " + ((Object)val).name));
						}
					}
				}
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("[QuickRestart] HideGameOverScreen exception: " + ex.Message));
			}
		}

		internal static void ResetPlayerControllerUiState()
		{
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Expected O, but got Unknown
			//IL_0514: Unknown result type (might be due to invalid IL or missing references)
			//IL_051b: Expected O, but got Unknown
			int num = 0;
			PlayerController[] array = Object.FindObjectsOfType<PlayerController>();
			foreach (PlayerController val in array)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				bool flag = false;
				FieldInfo field = ((object)val).GetType().GetField("isUiOpen", BindingFlags.Instance | BindingFlags.NonPublic);
				if (field != null && field.FieldType == typeof(bool) && (bool)(field.GetValue(val) ?? ((object)false)))
				{
					field.SetValue(val, false);
					flag = true;
				}
				FieldInfo field2 = ((object)val).GetType().GetField("isInventoryOpen", BindingFlags.Instance | BindingFlags.NonPublic);
				if (field2 != null && field2.FieldType == typeof(bool) && (bool)(field2.GetValue(val) ?? ((object)false)))
				{
					field2.SetValue(val, false);
					flag = true;
				}
				object? obj = ((object)val).GetType().GetField("ingameMenu", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(val);
				GameObject val2 = (GameObject)((obj is GameObject) ? obj : null);
				if (val2 != null && val2.activeSelf)
				{
					foreach (Transform item in val2.transform)
					{
						Transform val3 = item;
						if (!((Component)val3).gameObject.activeSelf)
						{
							((Component)val3).gameObject.SetActive(true);
						}
					}
					val2.SetActive(false);
					flag = true;
				}
				FieldInfo? field3 = ((object)val).GetType().GetField("settingsPanel", BindingFlags.Instance | BindingFlags.NonPublic);
				FieldInfo field4 = ((object)val).GetType().GetField("settingsButtons", BindingFlags.Instance | BindingFlags.NonPublic);
				object? obj2 = field3?.GetValue(val);
				GameObject val4 = (GameObject)((obj2 is GameObject) ? obj2 : null);
				if (val4 != null && val4.activeSelf)
				{
					val4.SetActive(false);
					flag = true;
				}
				object? obj3 = field4?.GetValue(val);
				GameObject val5 = (GameObject)((obj3 is GameObject) ? obj3 : null);
				if (val5 != null && !val5.activeSelf)
				{
					val5.SetActive(true);
					flag = true;
				}
				FieldInfo field5 = ((object)val).GetType().GetField("settingsPanelMode", BindingFlags.Instance | BindingFlags.NonPublic);
				if (field5 != null)
				{
					field5.SetValue(val, 1);
				}
				FieldInfo? field6 = ((object)val).GetType().GetField("ingameMenu", BindingFlags.Instance | BindingFlags.NonPublic);
				FieldInfo field7 = ((object)val).GetType().GetField("settingsButtons", BindingFlags.Instance | BindingFlags.NonPublic);
				FieldInfo field8 = ((object)val).GetType().GetField("settingsPanel", BindingFlags.Instance | BindingFlags.NonPublic);
				FieldInfo field9 = ((object)val).GetType().GetField("rebindPanel", BindingFlags.Instance | BindingFlags.NonPublic);
				object? obj4 = field6?.GetValue(val);
				GameObject go = (GameObject)((obj4 is GameObject) ? obj4 : null);
				object? obj5 = field7?.GetValue(val);
				GameObject go2 = (GameObject)((obj5 is GameObject) ? obj5 : null);
				object? obj6 = field8?.GetValue(val);
				GameObject go3 = (GameObject)((obj6 is GameObject) ? obj6 : null);
				object? obj7 = field9?.GetValue(val);
				GameObject go4 = (GameObject)((obj7 is GameObject) ? obj7 : null);
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.Append("[QuickRestart] UI diag: isUiOpen=" + (field?.GetValue(val) ?? "null")?.ToString() + ", isInventoryOpen=" + (field2?.GetValue(val) ?? "null")?.ToString() + "\n");
				LogUiGameObject(stringBuilder, "ingameMenu", go);
				LogUiGameObject(stringBuilder, "settingsButtons", go2);
				LogUiGameObject(stringBuilder, "settingsPanel", go3);
				LogUiGameObject(stringBuilder, "rebindPanel", go4);
				Logger.LogInfo((object)stringBuilder.ToString());
				object? obj8 = ((object)val).GetType().GetField("ingameMenu", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(val);
				GameObject val6 = (GameObject)((obj8 is GameObject) ? obj8 : null);
				if (val6 != null && (Object)(object)val6 != (Object)null)
				{
					Transform parent = val6.transform.parent;
					if ((Object)(object)parent != (Object)null)
					{
						GameObject gameObject = ((Component)parent).gameObject;
						if ((Object)(object)gameObject != (Object)null)
						{
							Canvas val7 = gameObject.GetComponent<Canvas>();
							if ((Object)(object)val7 == (Object)null)
							{
								val7 = gameObject.AddComponent<Canvas>();
								val7.renderMode = (RenderMode)0;
								Logger.LogInfo((object)("[QuickRestart] Added Canvas to '" + ((Object)gameObject).name + "'."));
								flag = true;
							}
							if (!((Behaviour)val7).enabled)
							{
								((Behaviour)val7).enabled = true;
								Logger.LogInfo((object)("[QuickRestart] Re-enabled Canvas on '" + ((Object)gameObject).name + "'."));
								flag = true;
							}
							if (!gameObject.activeSelf)
							{
								gameObject.SetActive(true);
								Logger.LogInfo((object)("[QuickRestart] Activated '" + ((Object)gameObject).name + "' (was inactive)."));
								flag = true;
							}
							Transform parent2 = gameObject.transform.parent;
							while ((Object)(object)parent2 != (Object)null)
							{
								if (!((Component)parent2).gameObject.activeSelf)
								{
									((Component)parent2).gameObject.SetActive(true);
									Logger.LogInfo((object)("[QuickRestart] Activated ancestor '" + ((Object)parent2).name + "'."));
									flag = true;
								}
								parent2 = parent2.parent;
							}
						}
					}
					else
					{
						GameObject val8 = new GameObject("Canvas in front");
						val8.transform.SetParent(((Component)val).transform, false);
						val8.AddComponent<Canvas>().renderMode = (RenderMode)0;
						val6.transform.SetParent(val8.transform, false);
						Logger.LogInfo((object)"[QuickRestart] Created new 'Canvas in front' under PC, reparented menu.");
						flag = true;
					}
				}
				object obj9 = ((object)val).GetType().GetField("frontCanvas", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(val);
				if (obj9 != null)
				{
					GameObject val9 = (GameObject)((obj9 is GameObject) ? obj9 : null);
					if ((Object)(object)val9 != (Object)null && (Object)(object)val9.GetComponent<Canvas>() == (Object)null)
					{
						val9.AddComponent<Canvas>().renderMode = (RenderMode)0;
						Logger.LogInfo((object)"[QuickRestart] Added Canvas to frontCanvas fallback.");
						flag = true;
					}
				}
				if (flag)
				{
					num++;
				}
			}
			if (num > 0)
			{
				Logger.LogInfo((object)$"[QuickRestart] Reset UI state on {num} PlayerControllers (including ingameMenu).");
			}
		}

		private static void LogUiGameObject(StringBuilder sb, string label, GameObject go)
		{
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02de: Expected O, but got Unknown
			if ((Object)(object)go == (Object)null)
			{
				sb.Append("  " + label + ": NULL (destroyed or unassigned)\n");
				return;
			}
			Canvas componentInParent = go.GetComponentInParent<Canvas>();
			Canvas component = go.GetComponent<Canvas>();
			CanvasGroup component2 = go.GetComponent<CanvasGroup>();
			string text = (((Object)(object)component2 != (Object)null) ? component2.alpha.ToString("F2") : "N/A");
			string text2 = (((Object)(object)component2 != (Object)null) ? component2.blocksRaycasts.ToString() : "N/A");
			sb.Append("  " + label + ": activeSelf=" + go.activeSelf + ", activeInHierarchy=" + go.activeInHierarchy + "\n");
			sb.Append("    parent=" + (((Object)(object)go.transform.parent != (Object)null) ? ((Object)go.transform.parent).name : "null") + "\n");
			sb.Append("    hasCanvasAncestor=" + (((Object)(object)componentInParent != (Object)null) ? "true" : "false") + ", hasCanvasSelf=" + (((Object)(object)component != (Object)null) ? "true" : "false") + "\n");
			if ((Object)(object)componentInParent != (Object)null)
			{
				sb.Append("    canvas: renderMode=" + ((object)componentInParent.renderMode/*cast due to .constrained prefix*/).ToString() + ", worldCamera=" + (((Object)(object)componentInParent.worldCamera != (Object)null) ? ((Object)componentInParent.worldCamera).name : "null") + ", sortingOrder=" + componentInParent.sortingOrder + ", enabled=" + ((Behaviour)componentInParent).enabled + "\n");
			}
			sb.Append("    canvasGroup: alpha=" + text + ", blocksRaycasts=" + text2 + "\n");
			sb.Append("    hierarchyDepth=" + go.transform.hierarchyCount + ", childCount=" + go.transform.childCount + "\n");
			if (go.transform.childCount <= 0)
			{
				return;
			}
			sb.Append("    children:\n");
			foreach (Transform item in go.transform)
			{
				Transform val = item;
				sb.Append("      [" + val.GetSiblingIndex() + "] " + ((Object)val).name + ": activeSelf=" + ((Component)val).gameObject.activeSelf + ", activeInHierarchy=" + ((Component)val).gameObject.activeInHierarchy + "\n");
			}
		}

		internal static bool SetBoolField(object obj, string fieldName, bool value)
		{
			try
			{
				FieldInfo field = obj.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null && field.FieldType == typeof(bool))
				{
					field.SetValue(obj, value);
					return true;
				}
			}
			catch
			{
			}
			return false;
		}

		private static Transform FindChildTransform(Transform parent, string name)
		{
			if ((Object)(object)parent == (Object)null)
			{
				return null;
			}
			for (int i = 0; i < parent.childCount; i++)
			{
				Transform child = parent.GetChild(i);
				if (((Object)child).name == name)
				{
					return child;
				}
				Transform val = FindChildTransform(child, name);
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			return null;
		}

		internal static void ClearBlockingFlag(object obj, string name)
		{
			try
			{
				Type type = obj.GetType();
				FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null)
				{
					if (field.FieldType == typeof(bool))
					{
						field.SetValue(obj, false);
						return;
					}
					PropertyInfo property = field.FieldType.GetProperty("Value", typeof(bool));
					if (property != null)
					{
						object value = field.GetValue(obj);
						property.SetValue(value, false);
						return;
					}
				}
				PropertyInfo property2 = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (property2 != null && property2.CanWrite && property2.PropertyType == typeof(bool))
				{
					property2.SetValue(obj, false);
					return;
				}
				FieldInfo field2 = type.GetField("<" + name + ">k__BackingField", BindingFlags.Instance | BindingFlags.NonPublic);
				if (field2 != null && field2.FieldType == typeof(bool))
				{
					field2.SetValue(obj, false);
					return;
				}
				string[] array = new string[4]
				{
					"m_" + name,
					"_" + name,
					"net" + name,
					"_net" + name
				};
				foreach (string name2 in array)
				{
					FieldInfo field3 = type.GetField(name2, BindingFlags.Instance | BindingFlags.NonPublic);
					if (field3 != null)
					{
						if (field3.FieldType == typeof(bool))
						{
							field3.SetValue(obj, false);
							break;
						}
						PropertyInfo property3 = field3.FieldType.GetProperty("Value", typeof(bool));
						if (property3 != null)
						{
							object value2 = field3.GetValue(obj);
							property3.SetValue(value2, false);
							break;
						}
					}
				}
			}
			catch
			{
			}
		}
	}
	public static class Patches
	{
		private sealed class EquipmentSnapshot
		{
			public ulong NetworkObjectId;

			public ulong OwnerClientId;

			public List<InventoryItem> Items = new List<InventoryItem>();
		}

		[CompilerGenerated]
		private static class <>O
		{
			public static UnityAction <0>__CancelDay;
		}

		public static bool SkipVortex;

		internal static bool _depositWorldSaved = false;

		internal static Vector3 _savedDepositWorldPos;

		internal static Quaternion _savedDepositWorldRot;

		private static readonly List<EquipmentSnapshot> EquipmentSnapshots = new List<EquipmentSnapshot>();

		private static readonly List<EquipmentSnapshot> LastGoodEquipment = new List<EquipmentSnapshot>();

		private static readonly HashSet<ulong> _phase1CompletePlayers = new HashSet<ulong>();

		private static GameObject _lastSettingsButtons;

		private static Button _restartButton;

		internal static void UseLastGoodEquipment()
		{
			if (LastGoodEquipment.Count == 0)
			{
				QuickRestartPlugin.Logger.LogWarning((object)"[QuickRestart] No bell-time equipment snapshot available to restore.");
				return;
			}
			EquipmentSnapshots.Clear();
			int num = 0;
			foreach (EquipmentSnapshot item in LastGoodEquipment)
			{
				if (item.Items.Count != 0)
				{
					EquipmentSnapshot equipmentSnapshot = new EquipmentSnapshot
					{
						NetworkObjectId = item.NetworkObjectId,
						OwnerClientId = item.OwnerClientId
					};
					equipmentSnapshot.Items.AddRange(item.Items);
					EquipmentSnapshots.Add(equipmentSnapshot);
					num += item.Items.Count;
				}
			}
			QuickRestartPlugin.Logger.LogInfo((object)$"[QuickRestart] Loaded bell-time equipment snapshot: {EquipmentSnapshots.Count} players ({num} items).");
		}

		[HarmonyPatch(typeof(PlayerNetworking), "DisplayGameOverScreenRpc")]
		[HarmonyPrefix]
		public static bool DisplayGameOverRpcPrefix()
		{
			if (QuickRestartPlugin._isCancelling)
			{
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(PlayerController), "Start")]
		[HarmonyPostfix]
		public static void PlayerControllerStartPostfix(PlayerController __instance)
		{
			QuickRestartPlugin.EnsureCancelDayActionReady();
			TryInjectRestartButton(__instance);
		}

		[HarmonyPatch(typeof(InputSystemHandler), "Awake")]
		[HarmonyPostfix]
		public static void InputSystemHandlerAwakePostfix()
		{
			QuickRestartPlugin.EnsureCancelDayActionReady();
		}

		[HarmonyPatch(typeof(PlayerController), "OnDied")]
		[HarmonyPostfix]
		public static void PlayerControllerOnDiedPostfix(PlayerController __instance)
		{
			TryInjectRestartButton(__instance);
		}

		[HarmonyPatch(typeof(PlayerController), "OnRespawned")]
		[HarmonyPostfix]
		public static void PlayerControllerOnRespawnedPostfix(PlayerController __instance)
		{
			TryInjectRestartButton(__instance);
		}

		[HarmonyPatch(typeof(PlayerController), "OnTied")]
		[HarmonyPostfix]
		public static void PlayerControllerOnTiedPostfix(PlayerController __instance)
		{
			TryInjectRestartButton(__instance);
		}

		[HarmonyPatch(typeof(PlayerController), "OnUnTied")]
		[HarmonyPostfix]
		public static void PlayerControllerOnUnTiedPostfix(PlayerController __instance)
		{
			TryInjectRestartButton(__instance);
		}

		[HarmonyPatch(typeof(PlayerController), "DisplayGameOver")]
		[HarmonyPostfix]
		public static void PlayerControllerDisplayGameOverPostfix(PlayerController __instance)
		{
			TryInjectRestartButton(__instance);
		}

		[HarmonyPatch(typeof(GameProgressionManager), "OnGameStarted")]
		[HarmonyPostfix]
		public static void OnGameStartedPostfix()
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			ResetMenuInjection();
			EnsureRestartButtonOnLocalPlayer();
			QuickRestartPlugin.RunCoroutine(DelayedLastGoodEquipmentCapture());
			if (_depositWorldSaved)
			{
				return;
			}
			try
			{
				GnomeHouse val = Object.FindObjectOfType<GnomeHouse>();
				if ((Object)(object)((val != null) ? val.GnomiumDeposit : null) != (Object)null)
				{
					Transform transform = ((Component)val.GnomiumDeposit).transform;
					_savedDepositWorldPos = transform.position;
					_savedDepositWorldRot = transform.rotation;
					_depositWorldSaved = true;
					QuickRestartPlugin.Logger.LogInfo((object)$"[QuickRestart] Saved deposit box: worldPos={_savedDepositWorldPos} worldRot={((Quaternion)(ref _savedDepositWorldRot)).eulerAngles}");
				}
			}
			catch (Exception ex)
			{
				QuickRestartPlugin.Logger.LogWarning((object)("[QuickRestart] Failed to save deposit box: " + ex.Message));
			}
		}

		private static IEnumerator DelayedLastGoodEquipmentCapture()
		{
			yield return null;
			CaptureLastGoodEquipment();
			QuickRestartPlugin.Logger.LogInfo((object)$"[QuickRestart] Game-start snapshot: {LastGoodEquipment.Count} players with items.");
		}

		internal static void CaptureLastGoodEquipment()
		{
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: 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_00f0: Unknown result type (might be due to invalid IL or missing references)
			LastGoodEquipment.Clear();
			PlayerNetworking[] array = Object.FindObjectsOfType<PlayerNetworking>();
			foreach (PlayerNetworking val in array)
			{
				if ((Object)(object)val == (Object)null || (Object)(object)val.Inventory == (Object)null || (Object)(object)((NetworkBehaviour)val).NetworkObject == (Object)null)
				{
					continue;
				}
				EquipmentSnapshot equipmentSnapshot = new EquipmentSnapshot
				{
					NetworkObjectId = ((NetworkBehaviour)val).NetworkObjectId,
					OwnerClientId = ((NetworkBehaviour)val).OwnerClientId
				};
				foreach (InventoryItem content in ((InventoryBase)val.Inventory).Contents)
				{
					InventoryItem current = content;
					if (((InventoryItem)(ref current)).IsValidItem)
					{
						equipmentSnapshot.Items.Add(current);
					}
				}
				if (equipmentSnapshot.Items.Count > 0)
				{
					LastGoodEquipment.Add(equipmentSnapshot);
				}
				List<string> list = new List<string>();
				foreach (InventoryItem item in equipmentSnapshot.Items)
				{
					InventoryItem current2 = item;
					list.Add($"[slot:{current2.slotIndex} item:{((InventoryItem)(ref current2)).ItemIndex}]");
				}
				QuickRestartPlugin.Logger.LogInfo((object)string.Format("[QuickRestart]   Player {0} snapshot: {1} items — {2}", ((NetworkBehaviour)val).OwnerClientId, equipmentSnapshot.Items.Count, string.Join(", ", list)));
				QuickRestartPlugin.Logger.LogInfo((object)$"[QuickRestart]   Player {((NetworkBehaviour)val).OwnerClientId} slotCount={((InventoryBase)val.Inventory).SlotCount}");
			}
		}

		[HarmonyPatch(typeof(GameProgressionManager), "ResetGame")]
		[HarmonyPrefix]
		public static bool ResetGamePrefix()
		{
			if (QuickRestartPlugin._isCancelling)
			{
				QuickRestartPlugin.Logger.LogInfo((object)"[QuickRestart] Suppressed ResetGame (day/save) during restart.");
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(GameProgressionManager), "OnGameEnded")]
		[HarmonyPrefix]
		public static bool OnGameEndedPrefix(GameProgressionManager __instance)
		{
			if (QuickRestartPlugin._isCancelling)
			{
				QuickRestartPlugin.Logger.LogInfo((object)"[QuickRestart] Suppressed OnGameEnded during restart.");
				try
				{
					if (typeof(GameProgressionManager).GetField("onGameEnded", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(__instance) is Delegate obj)
					{
						Delegate[] invocationList = obj.GetInvocationList();
						foreach (Delegate obj2 in invocationList)
						{
							QuickRestartPlugin.Logger.LogInfo((object)("[QuickRestart]   onGameEnded subscriber: " + obj2.Target?.GetType().FullName + "." + obj2.Method?.Name));
						}
					}
				}
				catch
				{
				}
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(GnomeHouse), "OnNetworkSpawn")]
		[HarmonyPostfix]
		public static void GnomeHouseSpawned()
		{
			_depositWorldSaved = false;
		}

		[HarmonyPatch(typeof(Bootstrap), "GoToLobby")]
		[HarmonyPrefix]
		public static bool GoToLobbyPrefix(Bootstrap __instance, GameEndedReason reason)
		{
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: 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_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			if (QuickRestartPlugin._isCancelling)
			{
				QuickRestartPlugin._isCancelling = false;
				QuickRestartPlugin.Logger.LogWarning((object)"[QuickRestart] Cleared stuck _isCancelling in GoToLobbyPrefix.");
			}
			if (!_depositWorldSaved)
			{
				try
				{
					GnomeHouse val = Object.FindObjectOfType<GnomeHouse>();
					if ((Object)(object)((val != null) ? val.GnomiumDeposit : null) != (Object)null)
					{
						Transform transform = ((Component)val.GnomiumDeposit).transform;
						_savedDepositWorldPos = transform.position;
						_savedDepositWorldRot = transform.rotation;
						_depositWorldSaved = true;
						QuickRestartPlugin.Logger.LogInfo((object)$"[QuickRestart] GoToLobby fallback save: deposit worldPos={_savedDepositWorldPos} rot={((Quaternion)(ref _savedDepositWorldRot)).eulerAngles}");
					}
				}
				catch (Exception ex)
				{
					QuickRestartPlugin.Logger.LogWarning((object)("[QuickRestart] GoToLobby fallback save failed: " + ex.Message));
				}
			}
			if (!SkipVortex)
			{
				return true;
			}
			SkipVortex = false;
			QuickRestartPlugin.Logger.LogInfo((object)"[QuickRestart] Instant lobby transition.");
			TryStartInstantLobbyTransition(__instance, reason, allowActiveTransition: false);
			return false;
		}

		internal static bool TryStartInstantLobbyTransition(Bootstrap bootstrap, GameEndedReason reason, bool allowActiveTransition, bool skipHomeAssembly = false)
		{
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)bootstrap == (Object)null)
			{
				return false;
			}
			Type? typeFromHandle = typeof(Bootstrap);
			FieldInfo field = typeFromHandle.GetField("gameTransitionInProgress", BindingFlags.Instance | BindingFlags.NonPublic);
			FieldInfo field2 = typeFromHandle.GetField("gameState", BindingFlags.Instance | BindingFlags.NonPublic);
			FieldInfo field3 = typeFromHandle.GetField("isOnlineMode", BindingFlags.Instance | BindingFlags.NonPublic);
			FieldInfo field4 = typeFromHandle.GetField("gnomeHouse", BindingFlags.Instance | BindingFlags.NonPublic);
			if (field != null && (bool)field.GetValue(bootstrap))
			{
				if (!allowActiveTransition)
				{
					QuickRestartPlugin.Logger.LogInfo((object)"[QuickRestart] Transition already in progress.");
					return false;
				}
				QuickRestartPlugin.Logger.LogInfo((object)"[QuickRestart] Cancelling Bootstrap transition coroutine so QuickRestart can complete the restart.");
				((MonoBehaviour)bootstrap).StopAllCoroutines();
			}
			if ((int)bootstrap.State == 0)
			{
				QuickRestartPlugin.Logger.LogWarning((object)"[QuickRestart] Already in lobby.");
				return false;
			}
			object? obj = field4?.GetValue(bootstrap);
			GnomeHouse val = (GnomeHouse)((obj is GnomeHouse) ? obj : null);
			HomeManager val2 = null;
			if (!skipHomeAssembly && (Object)(object)val != (Object)null)
			{
				object? obj2 = typeof(GnomeHouse).GetProperty("PlayerHome")?.GetValue(val);
				val2 = (HomeManager)(((obj2 is HomeManager) ? obj2 : null) ?? ((Component)val).GetComponentInChildren<HomeManager>());
			}
			QuickRestartPlugin.Logger.LogInfo((object)$"[QuickRestart] gnomeHouse: {(Object)(object)val != (Object)null}, homeManager: {(Object)(object)val2 != (Object)null}");
			QuickRestartPlugin.RunCoroutine(InstantTransition(bootstrap, field, field2, field3, val, val2, reason));
			return true;
		}

		internal static void PrepareForOwnedInstantRestart(Bootstrap bootstrap, GameProgressionManager progression)
		{
			try
			{
				QuickRestartPlugin.HideDeathOverlay();
				QuickRestartPlugin.HideGameOverScreen();
				StopTaskCallbacks();
				if ((Object)(object)((progression != null) ? progression.Deposit : null) != (Object)null)
				{
					GnomiumDeposit deposit = progression.Deposit;
					((MonoBehaviour)deposit).StopAllCoroutines();
					Type type = ((object)deposit).GetType();
					type.GetField("papyrusInProgress", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(deposit, false);
					type.GetField("preventRespawning", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(deposit, false);
					type.GetMethod("ResetPapyrus", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.Invoke(deposit, null);
					CancelActiveVortex(deposit.House);
				}
				ResetPlayersForOwnedRestart();
			}
			catch (Exception ex)
			{
				QuickRestartPlugin.Logger.LogWarning((object)("[QuickRestart] Owned instant pre-cleanup failed (non-fatal): " + ex.Message));
			}
		}

		private static void ResetPlayersForOwnedRestart()
		{
			PlayerNetworking[] array = Object.FindObjectsOfType<PlayerNetworking>();
			foreach (PlayerNetworking val in array)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				try
				{
					((MonoBehaviour)val).StopAllCoroutines();
					RestorePlayerFromVortexState(val);
					AccessTools.Field(typeof(PlayerNetworking), "respawning")?.SetValue(val, false);
					AccessTools.Field(typeof(PlayerNetworking), "keepAtRespawnPos")?.SetValue(val, false);
					if ((Object)(object)val.Dismemberment != (Object)null)
					{
						val.Dismemberment.ResetAllRpc();
					}
					if ((Object)(object)val.Health != (Object)null && ((HealthBase)val.Health).Dead)
					{
						((HealthBase)val.Health).Respawn();
					}
				}
				catch (Exception ex)
				{
					QuickRestartPlugin.Logger.LogWarning((object)$"[QuickRestart] Player restart cleanup failed for {((NetworkBehaviour)val).NetworkObjectId} (non-fatal): {ex.Message}");
				}
			}
		}

		internal static void EnsureRestartButtonOnLocalPlayer()
		{
			PlayerController val = ResolveLocalPlayerController();
			if ((Object)(object)val != (Object)null)
			{
				TryInjectRestartButton(val);
			}
		}

		private static void TryInjectRestartButton(PlayerController controller)
		{
			if ((Object)(object)controller == (Object)null || !IsLocalPlayerController(controller))
			{
				return;
			}
			GameObject val = QuickRestartPlugin.GetPrivate<GameObject>(controller, "settingsButtons");
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			if ((Object)(object)_lastSettingsButtons != (Object)(object)val || (Object)(object)_restartButton == (Object)null || (Object)(object)((Component)_restartButton).gameObject == (Object)null)
			{
				ResetMenuInjection();
			}
			if ((Object)(object)_restartButton != (Object)null)
			{
				return;
			}
			Button val2 = FindExistingRestartButton(val);
			if ((Object)(object)val2 != (Object)null)
			{
				_restartButton = val2;
				PrepareRestartButton(((Component)_restartButton).gameObject);
				_lastSettingsButtons = val;
				QuickRestartPlugin.Logger.LogInfo((object)"[QuickRestart] Adopted existing RESTART button in pause menu.");
				return;
			}
			Button val3 = FindTemplateButton(val);
			if (!((Object)(object)val3 == (Object)null))
			{
				GameObject val4 = Object.Instantiate<GameObject>(((Component)val3).gameObject, ((Component)val3).transform.parent);
				((Object)val4).name = "QuickRestartButton";
				val4.transform.SetSiblingIndex(Mathf.Min(1, val4.transform.parent.childCount - 1));
				_restartButton = val4.GetComponent<Button>();
				if ((Object)(object)_restartButton == (Object)null)
				{
					Object.Destroy((Object)(object)val4);
					return;
				}
				PrepareRestartButton(val4);
				_lastSettingsButtons = val;
				QuickRestartPlugin.Logger.LogInfo((object)"[QuickRestart] Injected RESTART button into pause menu.");
			}
		}

		private static PlayerController ResolveLocalPlayerController()
		{
			try
			{
				PlayerNetworking localPlayer = ServerManager.GetLocalPlayer();
				if (QuickRestartPlugin.IsUnityObjectAlive(localPlayer) && QuickRestartPlugin.IsUnityObjectAlive(localPlayer.Controller))
				{
					return localPlayer.Controller;
				}
			}
			catch
			{
			}
			PlayerController[] array = Object.FindObjectsOfType<PlayerController>();
			foreach (PlayerController val in array)
			{
				if (IsLocalPlayerController(val))
				{
					return val;
				}
			}
			return null;
		}

		private static bool IsLocalPlayerController(PlayerController controller)
		{
			if (!QuickRestartPlugin.IsUnityObjectAlive(controller))
			{
				return false;
			}
			try
			{
				PlayerNetworking val = QuickRestartPlugin.GetPrivate<PlayerNetworking>(controller, "networking");
				return QuickRestartPlugin.IsUnityObjectAlive(val) && ((NetworkBehaviour)val).IsLocalPlayer;
			}
			catch
			{
				return false;
			}
		}

		private static Button FindTemplateButton(GameObject settingsButtons)
		{
			Button[] componentsInChildren = settingsButtons.GetComponentsInChildren<Button>(true);
			foreach (Button val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null && ((Object)((Component)val).gameObject).name != "QuickRestartButton")
				{
					return val;
				}
			}
			return null;
		}

		private static Button FindExistingRestartButton(GameObject settingsButtons)
		{
			Button val = null;
			Button[] componentsInChildren = settingsButtons.GetComponentsInChildren<Button>(true);
			foreach (Button val2 in componentsInChildren)
			{
				if ((Object)(object)val2 != (Object)null && ((Object)((Component)val2).gameObject).name == "QuickRestartButton")
				{
					if ((Object)(object)val == (Object)null)
					{
						val = val2;
					}
					else
					{
						Object.Destroy((Object)(object)((Component)val2).gameObject);
					}
				}
			}
			return val;
		}

		private static void PrepareRestartButton(GameObject buttonObject)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			StripLocalization(buttonObject);
			SetButtonText(buttonObject, "RESTART");
			QuickRestartPlugin.RunCoroutine(EnsureButtonTextNextFrame(buttonObject));
			Button component = buttonObject.GetComponent<Button>();
			if (!((Object)(object)component == (Object)null))
			{
				((UnityEventBase)component.onClick).RemoveAllListeners();
				ButtonClickedEvent onClick = component.onClick;
				object obj = <>O.<0>__CancelDay;
				if (obj == null)
				{
					UnityAction val = QuickRestartPlugin.CancelDay;
					<>O.<0>__CancelDay = val;
					obj = (object)val;
				}
				((UnityEvent)onClick).AddListener((UnityAction)obj);
			}
		}

		private static IEnumerator EnsureButtonTextNextFrame(GameObject buttonObject)
		{
			yield return null;
			if (QuickRestartPlugin.IsUnityObjectAlive(buttonObject))
			{
				SetButtonText(buttonObject, "RESTART");
			}
		}

		private static void StripLocalization(GameObject buttonObject)
		{
			Component[] componentsInChildren = buttonObject.GetComponentsInChildren<Component>(true);
			foreach (Component val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				string fullName = ((object)val).GetType().FullName;
				if (fullName != null && IsLocalizationComponent(fullName))
				{
					Behaviour val2 = (Behaviour)(object)((val is Behaviour) ? val : null);
					if (val2 != null)
					{
						val2.enabled = false;
					}
					Object.DestroyImmediate((Object)(object)val);
				}
			}
		}

		private static bool IsLocalizationComponent(string typeName)
		{
			if (!typeName.StartsWith("Kamgam.LocalizationForSettings.", StringComparison.Ordinal) && !typeName.StartsWith("UnityEngine.Localization.Components.", StringComparison.Ordinal) && typeName.IndexOf("Localize", StringComparison.OrdinalIgnoreCase) < 0)
			{
				return typeName.IndexOf("Localization", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return true;
		}

		private static void SetButtonText(GameObject buttonObject, string textValue)
		{
			TMP_Text[] componentsInChildren = buttonObject.GetComponentsInChildren<TMP_Text>(true);
			foreach (TMP_Text obj in componentsInChildren)
			{
				obj.text = textValue;
				obj.SetText(textValue);
			}
			Text[] componentsInChildren2 = buttonObject.GetComponentsInChildren<Text>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				componentsInChildren2[i].text = textValue;
			}
		}

		private static void ResetMenuInjection()
		{
			_lastSettingsButtons = null;
			_restartButton = null;
		}

		private static IEnumerator InstantTransition(Bootstrap bootstrap, FieldInfo fiTransition, FieldInfo fiGameState, FieldInfo fiOnlineMode, GnomeHouse gnomeHouse, HomeManager homeManager, GameEndedReason reason)
		{
			fiTransition?.SetValue(bootstrap, true);
			try
			{
				CancelActiveVortex(gnomeHouse);
				GameProgressionManager instance = GameProgressionManager.Instance;
				if ((Object)(object)instance != (Object)null)
				{
					PreserveDayCounter(instance);
					QuickRestartPlugin.SetNetworkVar(instance, "n_timeActive", value: false);
					QuickRestartPlugin.SetNetworkVar(instance, "n_karma", 0f);
					QuickRestartPlugin.SetNetworkVar(instance, "n_currentGameTime", 0f);
					instance.SelectedLevelIndex = -1;
					GnomiumDeposit deposit = instance.Deposit;
					if ((Object)(object)deposit != (Object)null)
					{
						QuickRestartPlugin.Logger.LogInfo((object)"[QuickRestart] Resetting deposit game state.");
						deposit.InitGameState();
					}
					StopTaskCallbacks();
					TriggerGameEndedPlayerAction(instance);
				}
				GnomeHouse val = Object.FindObjectOfType<GnomeHouse>();
				if (_depositWorldSaved && (Object)(object)((val != null) ? val.GnomiumDeposit : null) != (Object)null)
				{
					try
					{
						Transform transform = ((Component)val.GnomiumDeposit).transform;
						transform.position = _savedDepositWorldPos;
						transform.rotation = _savedDepositWorldRot;
						QuickRestartPlugin.Logger.LogInfo((object)$"[QuickRestart] Restored deposit box: worldPos={_savedDepositWorldPos} worldRot={((Quaternion)(ref _savedDepositWorldRot)).eulerAngles}");
					}
					catch (Exception ex)
					{
						QuickRestartPlugin.Logger.LogWarning((object)("[QuickRestart] Failed to restore deposit box: " + ex.Message));
					}
				}
				else
				{
					QuickRestartPlugin.Logger.LogInfo((object)$"[QuickRestart] Skipped deposit box restore: saved={_depositWorldSaved}, gnomeHouse={(Object)(object)val != (Object)null}, deposit={(Object)(object)((val != null) ? val.GnomiumDeposit : null) != (Object)null}");
				}
				if ((Object)(object)homeManager != (Object)null)
				{
					QuickRestartPlugin.Logger.LogInfo((object)"[QuickRestart] Moving house to plateau + assembly.");
					homeManager.MoveHomeToPlateau();
					homeManager.PerformAssembly(true);
				}
				object? obj = typeof(Bootstrap).GetField("gnomeHouse", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(bootstrap);
				GnomeHouse val2 = (GnomeHouse)((obj is GnomeHouse) ? obj : null);
				if ((Object)(object)val2 != (Object)null)
				{
					CancelActiveVortex(val2);
				}
				else
				{
					CancelActiveVortex(gnomeHouse);
				}
				yield return null;
				yield return null;
				Scene activeScene = SceneManager.GetActiveScene();
				NetworkManager singleton = NetworkManager.Singleton;
				if (((singleton != null) ? singleton.SceneManager : null) != null)
				{
					QuickRestartPlugin.Logger.LogInfo((object)"[QuickRestart] Unloading gameplay scene.");
					NetworkManager.Singleton.SceneManager.UnloadScene(activeScene);
					float sceneTimeout = 10f;
					while (sceneTimeout > 0f)
					{
						Scene activeScene2 = SceneManager.GetActiveScene();
						if (activeScene2 != activeScene && ((Scene)(ref activeScene2)).IsValid())
						{
							break;
						}
						sceneTimeout -= Time.unscaledDeltaTime;
						yield return null;
					}
				}
				MethodInfo methodInfo = typeof(Bootstrap).GetProperty("State", BindingFlags.Instance | BindingFlags.Public)?.GetSetMethod(nonPublic: true);
				if (methodInfo != null)
				{
					QuickRestartPlugin.Logger.LogInfo((object)"[QuickRestart] Setting State via property setter.");
					methodInfo.Invoke(bootstrap, new object[1] { (object)(GameState)0 });
				}
				else
				{
					QuickRestartPlugin.Logger.LogInfo((object)"[QuickRestart] No State setter found; using field.");
					fiGameState?.SetValue(bootstrap, (object)(GameState)0);
				}
				if (fiOnlineMode != null && (bool)fiOnlineMode.GetValue(bootstrap))
				{
					LobbyManager component = ((Component)bootstrap).GetComponent<LobbyManager>();
					if (component != null)
					{
						component.SetCanJoin(true);
					}
				}
				QuickRestartPlugin.Logger.LogInfo((object)"[QuickRestart] Starting lobby object reinitialization.");
				QuickRestartPlugin.RunCoroutine(QuickRestartPlugin.DelayedLobbyReinitialize(bootstrap));
				QuickRestartPlugin.Logger.LogInfo((object)"[QuickRestart] Lobby transition complete.");
			}
			finally
			{
				object? obj2 = typeof(Bootstrap).GetField("gnomeHouse", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(bootstrap);
				GnomeHouse val3 = (GnomeHouse)((obj2 is GnomeHouse) ? obj2 : null);
				if ((Object)(object)val3 != (Object)null)
				{
					CancelActiveVortex(val3);
				}
				fiTransition?.SetValue(bootstrap, false);
				ResetMenuInjection();
			}
		}

		internal static void CancelActiveVortex(GnomeHouse gnomeHouse)
		{
			if ((Object)(object)gnomeHouse == (Object)null || !gnomeHouse.IsVortexActive)
			{
				return;
			}
			QuickRestartPlugin.Logger.LogInfo((object)"[QuickRestart] Cancelling active house vortex.");
			try
			{
				PlayerNetworking[] array = Object.FindObjectsOfType<PlayerNetworking>();
				for (int i = 0; i < array.Length; i++)
				{
					RestorePlayerFromVortexState(array[i]);
				}
				((MonoBehaviour)gnomeHouse).StopAllCoroutines();
				AccessTools.Field(typeof(GnomeHouse), "vortexAcceptingNewPlayers")?.SetValue(gnomeHouse, false);
				AccessTools.Field(typeof(GnomeHouse), "currentVortexDirection")?.SetValue(gnomeHouse, 0);
				AccessTools.Field(typeof(GnomeHouse), "playerBoundsChecker")?.SetValue(gnomeHouse, null);
				AccessTools.Method(typeof(GnomeHouse), "ToggleVortexObject", (Type[])null, (Type[])null)?.Invoke(gnomeHouse, new object[1] { false });
				AccessTools.Method(typeof(GnomeHouse), "OnVortexEnded", (Type[])null, (Type[])null)?.Invoke(gnomeHouse, Array.Empty<object>());
				string[] array2 = new string[4] { "playersInVortex", "playersAlreadyInVortexThisCycle", "playersAlreadyReceivedImpulse", "playersWhoGotStuckOnPlateau" };
				foreach (string text in array2)
				{
					try
					{
						ClearPrivateList(gnomeHouse, text);
					}
					catch (Exception ex)
					{
						QuickRestartPlugin.Logger.LogWarning((object)("[QuickRestart] List clear skipped (" + text + "): " + ex.Message));
					}
				}
			}
			catch (Exception ex2)
			{
				Exception innerException = ex2.InnerException;
				if (innerException != null)
				{
					QuickRestartPlugin.Logger.LogWarning((object)("[QuickRestart] Active vortex cleanup failed: " + ex2.Message + " | Inner: " + innerException.GetType().Name + ": " + innerException.Message));
				}
				else
				{
					QuickRestartPlugin.Logger.LogWarning((object)("[QuickRestart] Active vortex cleanup failed: " + ex2.Message));
				}
				QuickRestartPlugin.Logger.LogWarning((object)("[QuickRestart] Vortex cleanup stack: " + ex2.StackTrace));
			}
		}

		private static void RestorePlayerFromVortexState(PlayerNetworking player)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null)
			{
				return;
			}
			try
			{
				if ((int)((GameEntityBase)player).CurrentContainment != 0)
				{
					((GameEntityBase)player).SetContainmentState((ContainmentState)0);
				}
				player.ToggleRagdollGravity(true);
				if (((NetworkBehaviour)player).IsLocalPlayer)
				{
					player.StatusEffects.OnVortexLeft();
				}
			}
			catch (Exception ex)
			{
				QuickRestartPlugin.Logger.LogWarning((object)$"[QuickRestart] Player vortex state cleanup failed for {((NetworkBehaviour)player).NetworkObjectId} (non-fatal): {ex.Message}");
			}
		}

		private static void ClearPrivateList(object owner, string fieldName)
		{
			object obj = AccessTools.Field(owner.GetType(), fieldName)?.GetValue(owner);
			obj?.GetType().GetMethod("Clear", Type.EmptyTypes)?.Invoke(obj, Array.Empty<object>());
		}

		private static void PreserveDayCounter(GameProgressionManager progression)
		{
			int value = Math.Max(0, progression.CurrentLevel - 1);
			int value2 = progression.CurrentDay + 1;
			QuickRestartPlugin.SetNetworkVar(progression, "n_level", value);
			QuickRestartPlugin.SetNetworkVar(progression, "n_day", value2);
		}

		internal static void TriggerGameEndedPlayerAction(GameProgressionManager progression)
		{
			try
			{
				MethodInfo method = typeof(GameProgressionManager).GetMethod("TriggerGameEventRpc", BindingFlags.Instance | BindingFlags.NonPublic);
				if (!(method == null))
				{
					object obj = Enum.Parse(method.GetParameters()[0].ParameterType, "On_Game_Ended_PLAYER_ACTION");
					method.Invoke(progression, new object[1] { obj });
				}
			}
			catch (Exception ex)
			{
				QuickRestartPlugin.Logger.LogWarning((object)("[QuickRestart] Game-ended UI cleanup event failed (non-fatal): " + ex.Message));
			}
		}

		internal static void StopTaskCallbacks()
		{
			try
			{
				PlayerTaskManager val = Object.FindObjectOfType<PlayerTaskManager>();
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				QuickRestartPlugin.Logger.LogInfo((object)"[QuickRestart] Stopping task callbacks.");
				if (!(typeof(PlayerTaskManager).GetField("allTasks", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(val) is List<PlayerTaskBase> list))
				{
					return;
				}
				foreach (PlayerTaskBase item in list)
				{
					try
					{
						item.StopListeningToCallbacks();
					}
					catch
					{
					}
				}
			}
			catch (Exception ex)
			{
				QuickRestartPlugin.Logger.LogWarning((object)("[QuickRestart] Task callback cleanup failed (non-fatal): " + ex.Message));
			}
		}

		internal static IEnumerator RecoverLobbyPlayersAndEquipment()
		{
			yield return WaitForCurrentHomeReady();
			int num = RepositionAllPlayersAtLobbySpawn();
			if (num > 0)
			{
				QuickRestartPlugin.Logger.LogInfo((object)$"[QuickRestart] Repositioned {num} players at lobby mouth spawn.");
				float elapsed = 0f;
				while (elapsed < 2f && AnyPlayerDead())
				{
					elapsed += Time.unscaledDeltaTime;
					yield return null;
				}
				QuickRestartPlugin.ResetPlayerControllerUiState();
			}
			yield return RestoreEquipmentUntilStable();
		}

		private static IEnumerator WaitForCurrentHomeReady()
		{
			float elapsed = 0f;
			while (elapsed < 10f)
			{
				HomeManager currentPlayerHome = GetCurrentPlayerHome();
				if ((Object)(object)currentPlayerHome != (Object)null && !currentPlayerHome.IsLoadingHome && (Object)(object)currentPlayerHome.CurrentHome != (Object)null)
				{
					yield break;
				}
				elapsed += Time.unscaledDeltaTime;
				yield return null;
			}
			QuickRestartPlugin.Logger.LogWarning((object)"[QuickRestart] Timed out waiting for current home before lobby recovery.");
		}

		private static int RepositionAllPlayersAtLobbySpawn()
		{
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: 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_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			GnomeHouse currentGnomeHouse = GetCurrentGnomeHouse();
			HomeManager val = ((currentGnomeHouse != null) ? currentGnomeHouse.PlayerHome : null) ?? GetCurrentPlayerHome();
			if ((Object)(object)currentGnomeHouse == (Object)null && (Object)(object)((val != null) ? val.CurrentHome : null) == (Object)null)
			{
				return 0;
			}
			int num = 0;
			Vector3 val2 = (((Object)(object)((val != null) ? val.CurrentHome : null) != (Object)null) ? val.CurrentHome.PlayerRespawnPosition : (((Object)(object)currentGnomeHouse != (Object)null) ? currentGnomeHouse.PlayerSpawnPosition : Vector3.zero));
			QuickRestartPlugin.Logger.LogInfo((object)string.Format("[QuickRestart] Respawn position: {0} (homeCurrentHomePos={1})", val2, ((Object)(object)((val != null) ? val.CurrentHome : null) != (Object)null) ? ((object)((Component)val.CurrentHome).transform.position/*cast due to .constrained prefix*/).ToString() : "null"));
			PlayerNetworking[] array = Object.FindObjectsOfType<PlayerNetworking>();
			foreach (PlayerNetworking val3 in array)
			{
				if ((Object)(object)val3 == (Object)null || (Object)(object)val3.Health == (Object)null)
				{
					continue;
				}
				try
				{
					if (((HealthBase)val3.Health).Dead)
					{
						val3.InstantRespawn(val2);
					}
					else if ((Object)(object)((NetworkBehaviour)val3).NetworkObject != (Object)null)
					{
						((Component)((NetworkBehaviour)val3).NetworkObject).transform.position = val2;
					}
					else
					{
						((Component)val3).transform.position = val2;
					}
					num++;
				}
				catch (Exception ex)
				{
					QuickRestartPlugin.Logger.LogWarning((object)$"[QuickRestart] Player reposition failed for {((NetworkBehaviour)val3).NetworkObjectId} (non-fatal): {ex.Message}");
				}
			}
			return num;
		}

		internal static bool AnyPlayerDead()
		{
			PlayerNetworking[] array = Object.FindObjectsOfType<PlayerNetworking>();
			foreach (PlayerNetworking val in array)
			{
				if ((Object)(object)((val != null) ? val.Health : null) != (Object)null && ((HealthBase)val.Health).Dead)
				{
					return true;
				}
			}
			return false;
		}

		internal static GnomeHouse GetCurrentGnomeHouse()
		{
			GameProgressionManager instance = GameProgressionManager.Instance;
			if (instance == null)
			{
				return null;
			}
			GnomiumDeposit deposit = instance.Deposit;
			if (deposit == null)
			{
				return null;
			}
			return deposit.House;
		}

		private static HomeManager GetCurrentPlayerHome()
		{
			GameProgressionManager instance = GameProgressionManager.Instance;
			if (instance == null)
			{
				return null;
			}
			GnomiumDeposit deposit = instance.Deposit;
			if (deposit == null)
			{
				return null;
			}
			GnomeHouse house = deposit.House;
			if (house == null)
			{
				return null;
			}
			return house.PlayerHome;
		}

		internal static void SnapshotEquipment()
		{
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: 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_0327: Unknown result type (might be due to invalid IL or missing references)
			//IL_032c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0343: Unknown result type (might be due to invalid IL or missing references)
			//IL_034d: Unknown result type (might be due to invalid IL or missing references)
			//IL_049c: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_037f: Unknown result type (might be due to invalid IL or missing references)
			EquipmentSnapshots.Clear();
			PlayerNetworking[] array = Object.FindObjectsOfType<PlayerNetworking>();
			foreach (PlayerNetworking val in array)
			{
				if ((Object)(object)val == (Object)null || (Object)(object)val.Inventory == (Object)null || (Object)(object)((NetworkBehaviour)val).NetworkObject == (Object)null)
				{
					continue;
				}
				EquipmentSnapshot equipmentSnapshot = new EquipmentSnapshot
				{
					NetworkObjectId = ((NetworkBehaviour)val).NetworkObjectId,
					OwnerClientId = ((NetworkBehaviour)val).OwnerClientId
				};
				foreach (InventoryItem content in ((InventoryBase)val.Inventory).Contents)
				{
					InventoryItem current = content;
					if (((InventoryItem)(ref current)).IsValidItem)
					{
						equipmentSnapshot.Items.Add(current);
					}
				}
				EquipmentSnapshots.Add(equipmentSnapshot);
			}
			int num = 0;
			foreach (EquipmentSnapshot equipmentSnapshot7 in EquipmentSnapshots)
			{
				num += equipmentSnapshot7.Items.Count;
			}
			int num2 = 0;
			for (int j = 0; j < EquipmentSnapshots.Count; j++)
			{
				EquipmentSnapshot equipmentSnapshot2 = EquipmentSnapshots[j];
				if (equipmentSnapshot2.Items.Count > 0)
				{
					continue;
				}
				EquipmentSnapshot equipmentSnapshot3 = FindMatchingLastGood(equipmentSnapshot2);
				if (equipmentSnapshot3 == null || equipmentSnapshot3.Items.Count <= 0)
				{
					continue;
				}
				foreach (InventoryItem item in equipmentSnapshot3.Items)
				{
					_ = item;
					equipmentSnapshot2.Items.Clear();
				}
				equipmentSnapshot2.Items.AddRange(equipmentSnapshot3.Items);
				num2++;
			}
			int num3 = 0;
			foreach (EquipmentSnapshot item2 in LastGoodEquipment)
			{
				bool flag = false;
				for (int k = 0; k < EquipmentSnapshots.Count; k++)
				{
					if (EquipmentSnapshots[k].OwnerClientId == item2.OwnerClientId || EquipmentSnapshots[k].NetworkObjectId == item2.NetworkObjectId)
					{
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					QuickRestartPlugin.Logger.LogInfo((object)$"[QuickRestart] Player {item2.OwnerClientId} networking object gone; restoring {item2.Items.Count} items from last known good.");
					EquipmentSnapshot equipmentSnapshot4 = new EquipmentSnapshot
					{
						NetworkObjectId = item2.NetworkObjectId,
						OwnerClientId = item2.OwnerClientId
					};
					equipmentSnapshot4.Items.AddRange(item2.Items);
					EquipmentSnapshots.Add(equipmentSnapshot4);
					num3++;
				}
			}
			int num4 = 0;
			for (int l = 0; l < EquipmentSnapshots.Count; l++)
			{
				EquipmentSnapshot equipmentSnapshot5 = EquipmentSnapshots[l];
				EquipmentSnapshot equipmentSnapshot6 = FindMatchingLastGood(equipmentSnapshot5);
				if (equipmentSnapshot6 == null || equipmentSnapshot6.Items.Count <= equipmentSnapshot5.Items.Count)
				{
					continue;
				}
				int num5 = 0;
				foreach (InventoryItem item3 in equipmentSnapshot6.Items)
				{
					bool flag2 = false;
					foreach (InventoryItem item4 in equipmentSnapshot5.Items)
					{
						if (item4.slotIndex == item3.slotIndex)
						{
							flag2 = true;
							break;
						}
					}
					if (!flag2)
					{
						equipmentSnapshot5.Items.Add(item3);
						num5++;
					}
				}
				if (num5 > 0)
				{
					QuickRestartPlugin.Logger.LogInfo((object)$"[QuickRestart] Supplemented {num5} missing items from LastGoodEquipment for player {equipmentSnapshot5.OwnerClientId} (snapshot had {equipmentSnapshot5.Items.Count - num5}, last-good had {equipmentSnapshot6.Items.Count}).");
					num4++;
				}
			}
			if (num2 > 0 || num3 > 0 || num4 > 0)
			{
				QuickRestartPlugin.Logger.LogInfo((object)$"[QuickRestart] Applied last-good fallback: {num2} empty players, {num3} missing players, {num4} supplemented.");
			}
			int num6 = 0;
			foreach (EquipmentSnapshot equipmentSnapshot8 in EquipmentSnapshots)
			{
				num6 += equipmentSnapshot8.Items.Count;
				List<string> list = new List<string>();
				foreach (InventoryItem item5 in equipmentSnapshot8.Items)
				{
					InventoryItem current6 = item5;
					list.Add($"[slot:{current6.slotIndex} item:{((InventoryItem)(ref current6)).ItemIndex}]");
				}
				QuickRestartPlugin.Logger.LogInfo((object)string.Format("[QuickRestart]   Snapshot player {0}: {1} items — {2}", equipmentSnapshot8.OwnerClientId, equipmentSnapshot8.Items.Count, string.Join(", ", list)));
			}
			QuickRestartPlugin.Logger.LogInfo((object)$"[QuickRestart] Snapshotted equipment for {EquipmentSnapshots.Count} players ({num6} items).");
		}

		private static IEnumerator RestoreEquipmentUntilStable()
		{
			_phase1CompletePlayers.Clear();
			float elapsed = 0f;
			int attempts = 0;
			while (elapsed < 8f)
			{
				if (IsNativePostGameCleanupActive())
				{
					elapsed += Time.unscaledDeltaTime;
					yield return null;
					continue;
				}
				attempts++;
				if (RestoreEquipmentSnapshot() && elapsed >= 1f)
				{
					break;
				}
				float wait = 0f;
				while (wait < 0.5f)
				{
					wait += Time.unscaledDeltaTime;
					elapsed += Time.unscaledDeltaTime;
					yield return null;
				}
			}
			QuickRestartPlugin.Logger.LogInfo((object)$"[QuickRestart] Equipment restore stabilization finished after {attempts} attempts.");
		}

		private static bool IsNativePostGameCleanupActive()
		{
			GameProgressionManager instance = GameProgressionManager.Instance;
			GnomiumDeposit val = ((instance != null) ? instance.Deposit : null);
			if ((Object)(object)val != (Object)null)
			{
				if (!val.PreventingRespawns)
				{
					return val.PapyrusIsAnimating;
				}
				return true;
			}
			return false;
		}

		internal static bool RestoreEquipmentSnapshot()
		{
			//IL_0291: Unknown result type (might be due to invalid IL or missing references)
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: Unknown result type (might be due to invalid IL or missing references)
			//IL_0334: Unknown result type (might be due to invalid IL or missing references)
			//IL_0339: Unknown result type (might be due to invalid IL or missing references)
			//IL_033b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: 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_02a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_034e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0353: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_036c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_039c: 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_03ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_03da: 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_0423: Unknown result type (might be due to invalid IL or missing references)
			//IL_0437: Unknown result type (might be due to invalid IL or missing references)
			if (EquipmentSnapshots.Count == 0)
			{
				QuickRestartPlugin.Logger.LogWarning((object)"[QuickRestart] No equipment snapshot is available to restore.");
				return true;
			}
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			PlayerNetworking[] array = Object.FindObjectsOfType<PlayerNetworking>();
			foreach (PlayerNetworking val in array)
			{
				if ((Object)(object)val == (Object)null || (Object)(object)val.Inventory == (Object)null || (Object)(object)((NetworkBehaviour)val).NetworkObject == (Object)null)
				{
					continue;
				}
				EquipmentSnapshot equipmentSnapshot = FindEquipmentSnapshot(val);
				if (equipmentSnapshot == null)
				{
					continue;
				}
				try
				{
					if (InventoryMatchesSnapshot(val.Inventory, equipmentSnapshot.Items))
					{
						num3++;
						continue;
					}
					if (equipmentSnapshot.Items.Count == 0)
					{
						num3++;
						QuickRestartPlugin.Logger.LogInfo((object)$"[QuickRestart] Player {((NetworkBehaviour)val).OwnerClientId} snapshot is empty (was dead at capture); keeping lobby spawn items.");
						continue;
					}
					QuickRestartPlugin.Logger.LogInfo((object)$"[QuickRestart]   Restoring player {((NetworkBehaviour)val).OwnerClientId}: snapshot has {equipmentSnapshot.Items.Count} items, player has {((InventoryBase)val.Inventory).Contents.Count} items, SlotCount={((InventoryBase)val.Inventory).SlotCount}, IsHost={NetworkManager.Singleton.IsHost}");
					try
					{
						GameObject gameObject = ((Component)val.Inventory).gameObject;
						if ((Object)(object)gameObject != (Object)null && !gameObject.activeInHierarchy)
						{
							gameObject.SetActive(true);
							QuickRestartPlugin.Logger.LogInfo((object)$"[QuickRestart] Re-activated disabled inventory for player {((NetworkBehaviour)val).NetworkObjectId}.");
						}
					}
					catch
					{
					}
					int num4 = 0;
					int num5 = 0;
					List<InventoryItem> list = new List<InventoryItem>();
					if (!_phase1CompletePlayers.Contains(((NetworkBehaviour)val).OwnerClientId))
					{
						((InventoryBase)val.Inventory).ClearInventory();
						foreach (InventoryItem item in equipmentSnapshot.Items)
						{
							InventoryItem current = item;
							if (current.slotIndex <= 1)
							{
								if (((InventoryBase)val.Inventory).TryAddItemToSlot(((InventoryItem)(ref current)).InstanceData, (int)current.slotIndex) > 0)
								{
									num4++;
								}
								else
								{
									list.Add(current);
								}
							}
						}
						try
						{
							if ((Object)(object)val.Equipment != (Object)null)
							{
								val.Equipment.UpdateEquipmentState();
							}
						}
						catch (Exception ex)
						{
							QuickRestartPlugin.Logger.LogWarning((object)("[QuickRestart] UpdateEquipmentState failed: " + ex.Message));
						}
						int slotCount = ((InventoryBase)val.Inventory).SlotCount;
						byte b = 0;
						foreach (InventoryItem item2 in equipmentSnapshot.Items)
						{
							if (item2.slotIndex > b)
							{
								b = item2.slotIndex;
							}
						}
						if (slotCount <= b)
						{
							((InventoryBase)val.Inventory).ResizeInventory(b + 1);
							QuickRestartPlugin.Logger.LogInfo((object)$"[QuickRestart] Resized inventory from {slotCount} to {b + 1} for player {((NetworkBehaviour)val).NetworkObjectId} (backpack slot sync).");
						}
						_phase1CompletePlayers.Add(((NetworkBehaviour)val).OwnerClientId);
						continue;
					}
					foreach (InventoryItem item3 in equipmentSnapshot.Items)
					{
						InventoryItem current3 = item3;
						if (current3.slotIndex > 1)
						{
							if (((InventoryBase)val.Inventory).TryAddItemToSlot(((InventoryItem)(ref current3)).InstanceData, (int)current3.slotIndex) > 0)
							{
								num4++;
							}
							else
							{
								list.Add(current3);
							}
						}
					}
					foreach (InventoryItem item4 in list)
					{
						InventoryItem current4 = item4;
						if (((InventoryBase)val.Inventory).TryAddItem(((InventoryItem)(ref current4)).InstanceData) > 0)
						{
							num5++;
							continue;
						}
						QuickRestartPlugin.Logger.LogWarning((object)($"[QuickRestart] TryAddItem failed for item {((InventoryItem)(ref current4)).ItemIndex} (slot {current4.slotIndex}); scanning " + $"{((InventoryBase)val.Inventory).SlotCount} slots for empty spot..."));
						for (int j = 0; j < ((InventoryBase)val.Inventory).SlotCount; j++)
						{
							InventoryItem itemInSlot = ((InventoryBase)val.Inventory).GetItemInSlot(j);
							if (!((InventoryItem)(ref itemInSlot)).IsValidItem && ((InventoryBase)val.Inventory).TryAddItemToSlot(((InventoryItem)(ref current4)).InstanceData, j) > 0)
							{
								num5++;
								break;
							}
						}
					}
					num2 = num4 + num5;
					num++;
				}
				catch (Exception ex2)
				{
					QuickRestartPlugin.Logger.LogWarning((object)$"[QuickRestart] Equipment restore failed for player {((NetworkBehaviour)val).NetworkObjectId} (non-fatal): {ex2.Message}");
				}
			}
			bool result = num + num3 >= EquipmentSnapshots.Count;
			QuickRestartPlugin.Logger.LogInfo((object)$"[QuickRestart] Restored equipment snapshot for {num} players ({num2} items); {num3} already matched.");
			return result;
		}

		internal static bool HasLastGoodEquipment()
		{
			if (LastGoodEquipment.Count == 0)
			{
				return false;
			}
			foreach (EquipmentSnapshot item in LastGoodEquipment)
			{
				if (item.Items.Count == 0)
				{
					continue;
				}
				bool flag = false;
				PlayerNetworking[] array = Object.FindObjectsOfType<PlayerNetworking>();
				foreach (PlayerNetworking val in array)
				{
					if ((Object)(object)val != (Object)null && (((NetworkBehaviour)val).OwnerClientId == item.OwnerClientId || ((NetworkBehaviour)val).NetworkObjectId == item.NetworkObjectId))
					{
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					return true;
				}
			}
			return false;
		}

		private static EquipmentSnapshot FindMatchingLastGood(EquipmentSnapshot snap)
		{
			foreach (EquipmentSnapshot item in LastGoodEquipment)
			{
				if (item.OwnerClientId == snap.OwnerClientId)
				{
					return item;
				}
			}
			foreach (EquipmentSnapshot item2 in LastGoodEquipment)
			{
				if (item2.NetworkObjectId == snap.NetworkObjectId)
				{
					return item2;
				}
			}
			return null;
		}

		private static EquipmentSnapshot FindEquipmentSnapshot(PlayerNetworking player)
		{
			foreach (EquipmentSnapshot equipmentSnapshot in EquipmentSnapshots)
			{
				if (equipmentSnapshot.OwnerClientId == ((NetworkBehaviour)player).OwnerClientId)
				{
					return equipmentSnapshot;
				}
			}
			foreach (EquipmentSnapshot equipmentSnapshot2 in EquipmentSnapshots)
			{
				if (equipmentSnapshot2.NetworkObjectId == ((NetworkBehaviour)player).NetworkObjectId)
				{
					return equipmentSnapshot2;
				}
			}
			return null;
		}

		private static bool InventoryMatchesSnapshot(PlayerInventory inventory, List<InventoryItem> snapshot)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: 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_0032: Unknown result type (might be due to invalid IL or missing references)
			if (((InventoryBase)inventory).Contents.Count != snapshot.Count)
			{
				return false;
			}
			foreach (InventoryItem item in snapshot)
			{
				InventoryItem current = item;
				InventoryItem itemInSlot = ((InventoryBase)inventory).GetItemInSlot((int)current.slotIndex);
				if (!((InventoryItem)(ref itemInSlot)).IsValidItem || ((InventoryItem)(ref itemInSlot)).ItemIndex != ((InventoryItem)(ref current)).ItemIndex || ((InventoryItem)(ref itemInSlot)).ItemCount != ((InventoryItem)(ref current)).ItemCount || Math.Abs(((InventoryItem)(ref itemInSlot)).Durability - ((InventoryItem)(ref current)).Durability) > 0.01f)
				{
					return false;
				}
			}
			return true;
		}
	}
}