Decompiled source of Nivalis Better Time v2.0.10

BepInEx/plugins/NivalisSlowDays/NivalisSlowDays.dll

Decompiled 13 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.Json;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using Cysharp.Threading.Tasks;
using Cysharp.Threading.Tasks.CompilerServices;
using HarmonyLib;
using Hvizeu.NivalisMods;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.Attributes;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Il2CppSystem.Reflection;
using Il2CppSystem.Threading;
using Microsoft.CodeAnalysis;
using Nivalis;
using Nivalis.Dialogue;
using Nivalis.GhostSystem;
using Nivalis.GhostSystem.Ai;
using Nivalis.GhostSystem.CustomerLoop;
using Nivalis.Localization;
using Nivalis.Player;
using Nivalis.UI.Concrete;
using Nivalis.UI.InGameMenu;
using Nivalis.Utility;
using TMPro;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.Utilities;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("Hvizeu")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Configurable time and curfew-aware waiting for Nivalis Nights.")]
[assembly: AssemblyFileVersion("2.0.10.0")]
[assembly: AssemblyInformationalVersion("2.0.10")]
[assembly: AssemblyProduct("NivalisSlowDays")]
[assembly: AssemblyTitle("NivalisSlowDays")]
[assembly: AssemblyVersion("2.0.10.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NativeIntegerAttribute : Attribute
	{
		public readonly bool[] TransformFlags;

		public NativeIntegerAttribute()
		{
			TransformFlags = new bool[1] { true };
		}

		public NativeIntegerAttribute(bool[] P_0)
		{
			TransformFlags = P_0;
		}
	}
}
namespace Hvizeu.NivalisMods
{
	internal static class CharacterClearance
	{
		internal static void Volume(Character character, out Vector3 lower, out Vector3 upper, out float radius)
		{
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: 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_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: 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_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: 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_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: 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_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			Collider collide = character.Collide;
			CapsuleCollider val = ((collide != null) ? ((Il2CppObjectBase)collide).TryCast<CapsuleCollider>() : null);
			Vector3 val2;
			float num;
			if ((Object)(object)val != (Object)null && val.direction == 1)
			{
				Vector3 lossyScale = ((Component)val).transform.lossyScale;
				val2 = ((Component)val).transform.TransformPoint(val.center);
				radius = val.radius * Mathf.Max(Mathf.Abs(lossyScale.x), Mathf.Abs(lossyScale.z));
				num = val.height * Mathf.Abs(lossyScale.y);
			}
			else
			{
				if ((Object)(object)collide != (Object)null && collide.enabled)
				{
					Bounds bounds = collide.bounds;
					Vector3 size = ((Bounds)(ref bounds)).size;
					if (((Vector3)(ref size)).sqrMagnitude > 0.01f)
					{
						Bounds bounds2 = collide.bounds;
						val2 = ((Bounds)(ref bounds2)).center;
						radius = Mathf.Max(((Bounds)(ref bounds2)).extents.x, ((Bounds)(ref bounds2)).extents.z);
						num = ((Bounds)(ref bounds2)).size.y;
						goto IL_013a;
					}
				}
				NavMeshAgent agent = character.Movement.Agent;
				radius = agent.radius;
				num = agent.height;
				val2 = ((BaseCharacter)character).ThisTransform.position + Vector3.up * (num * 0.5f + agent.baseOffset);
			}
			goto IL_013a;
			IL_013a:
			radius = Mathf.Max(0.1f, radius);
			float num2 = Mathf.Max(0f, num * 0.5f - radius);
			lower = val2 - Vector3.up * num2;
			upper = val2 + Vector3.up * num2;
		}

		internal static bool Blocks(Character character, Collider collider)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			Character componentInParent = ((Component)collider).GetComponentInParent<Character>();
			if ((Object)(object)componentInParent != (Object)null)
			{
				return ((Il2CppObjectBase)componentInParent).Pointer != ((Il2CppObjectBase)character).Pointer;
			}
			Collider collide = character.Collide;
			if ((Object)(object)collide == (Object)null)
			{
				return true;
			}
			int layer = ((Component)collider).gameObject.layer;
			if (Singleton<CharacterManager>.InstanceExist() && (LayerMask.op_Implicit(Singleton<CharacterManager>.Instance.EnvironmentLayer) & (1 << layer)) != 0)
			{
				return true;
			}
			return !Physics.GetIgnoreLayerCollision(((Component)collide).gameObject.layer, layer);
		}
	}
}
namespace NivalisSlowDays
{
	internal static class BindingJson
	{
		internal const string WaitId = "495c85ec-ebbd-47ae-8b9c-91a662d095eb";

		internal const string WaitGamepadId = "73a613ea-91c5-4aac-af1c-ff77e2968d34";

		internal static string WithoutWait(string json)
		{
			if (string.IsNullOrEmpty(json))
			{
				return json;
			}
			using (JsonDocument jsonDocument = JsonDocument.Parse(json))
			{
				JsonElement rootElement = jsonDocument.RootElement;
				if (!rootElement.TryGetProperty("bindings", out var value) || value.ValueKind != JsonValueKind.Array)
				{
					return json;
				}
				if (!value.EnumerateArray().Any(IsWait))
				{
					return json;
				}
				using MemoryStream memoryStream = new MemoryStream();
				using (Utf8JsonWriter utf8JsonWriter = new Utf8JsonWriter((Stream)memoryStream, default(JsonWriterOptions)))
				{
					utf8JsonWriter.WriteStartObject();
					foreach (JsonProperty item in rootElement.EnumerateObject())
					{
						if (item.Name != "bindings")
						{
							item.WriteTo(utf8JsonWriter);
							continue;
						}
						utf8JsonWriter.WriteStartArray("bindings");
						foreach (JsonElement item2 in value.EnumerateArray())
						{
							if (!IsWait(item2))
							{
								item2.WriteTo(utf8JsonWriter);
							}
						}
						utf8JsonWriter.WriteEndArray();
					}
					utf8JsonWriter.WriteEndObject();
				}
				return Encoding.UTF8.GetString(memoryStream.ToArray());
			}
			static bool IsWait(JsonElement entry)
			{
				if (entry.ValueKind == JsonValueKind.Object && entry.TryGetProperty("id", out var value2) && value2.ValueKind == JsonValueKind.String)
				{
					if (!string.Equals(value2.GetString(), "495c85ec-ebbd-47ae-8b9c-91a662d095eb", StringComparison.OrdinalIgnoreCase))
					{
						return string.Equals(value2.GetString(), "73a613ea-91c5-4aac-af1c-ff77e2968d34", StringComparison.OrdinalIgnoreCase);
					}
					return true;
				}
				return false;
			}
		}
	}
	[HarmonyPatch(typeof(VisitVenueAgentActionType), "MeetsRequirements")]
	internal static class CustomerArrivalPatch
	{
		private static void Postfix(ref bool __result)
		{
			if (__result && Plugin.BalanceArrivals.Value)
			{
				__result = CustomerArrivalPolicy.Admit(Plugin.Rate.Value, WaitFaults.Active);
			}
		}
	}
	internal static class CustomerArrivalPolicy
	{
		internal static bool Admit(float rate, bool explicitWait)
		{
			if (!float.IsFinite(rate))
			{
				rate = 1f;
			}
			rate = Math.Clamp(rate, 0f, 2f);
			return rate > 0f || explicitWait;
		}
	}
	internal static class HourlyWork
	{
		private static UniTask task = null;

		private static VenueManager? owner;

		private static int queued;

		private static Stopwatch? acceleratedTime;

		internal static bool Pending { get; private set; }

		internal static bool NeedsUnpausedDrain { get; private set; }

		internal static int FaultSequence { get; private set; }

		internal static string ProgressText { get; private set; } = "Updating venues for the new hour...";

		internal static bool Start(VenueManager venue)
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Expected O, but got Unknown
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Expected O, but got Unknown
			//IL_00ba: Expected O, but got Unknown
			if ((Object)(object)TimeController.Current == (Object)null)
			{
				return false;
			}
			if (Pending)
			{
				if ((Object)(object)owner != (Object)null && ((Il2CppObjectBase)owner).Pointer == ((Il2CppObjectBase)venue).Pointer)
				{
					queued++;
					return true;
				}
				return false;
			}
			if (TimeController.Current.Busy)
			{
				try
				{
					WaitVenueHour.Run(venue);
				}
				catch (Exception ex)
				{
					FaultSequence++;
					ManualLogSource modLog = Plugin.ModLog;
					bool flag = default(bool);
					BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(35, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Native venue catch-up hour failed: ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
					}
					modLog.LogError(val);
				}
				return true;
			}
			owner = venue;
			if (venue.onDestroyCancelToken == null)
			{
				CancellationTokenSource val2 = new CancellationTokenSource();
				CancellationTokenSource val3 = val2;
				venue.onDestroyCancelToken = val2;
			}
			task = venue.HourlyUpdateTask(venue.onDestroyCancelToken.Token);
			Pending = true;
			ProgressText = "Updating venues for the new hour...";
			acceleratedTime = null;
			return true;
		}

		internal static void Poll()
		{
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Expected O, but got Unknown
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Expected O, but got Unknown
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Expected O, but got Unknown
			if (!Pending)
			{
				return;
			}
			bool flag = default(bool);
			try
			{
				if ((int)task.Status == 0)
				{
					if (!NeedsUnpausedDrain)
					{
						TimeController? current = TimeController.Current;
						if (current != null && current.Busy)
						{
							ExpediteOwnedDelay();
						}
					}
					return;
				}
			}
			catch (Exception ex)
			{
				if (!NeedsUnpausedDrain)
				{
					NeedsUnpausedDrain = true;
					FaultSequence++;
					ManualLogSource modLog = Plugin.ModLog;
					BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(91, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Cannot accelerate the active venue hour. Returning to gameplay to drain its original task: ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
					}
					modLog.LogError(val);
				}
				return;
			}
			Pending = false;
			NeedsUnpausedDrain = false;
			try
			{
				task.GetAwaiter().GetResult();
				if (acceleratedTime != null)
				{
					ManualLogSource modLog2 = Plugin.ModLog;
					BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(55, 2, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Venue hour completed after ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<double>(acceleratedTime.Elapsed.TotalSeconds, "0.00");
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("s of wait catch-up; venues=");
						VenueManager? obj = owner;
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int?>((obj != null) ? new int?(obj._venueGhosts.Count) : ((int?)null));
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(".");
					}
					modLog2.LogInfo(val2);
				}
				task = null;
				while (queued > 0 && (Object)(object)owner != (Object)null && !Pending)
				{
					queued--;
					Start(owner);
				}
			}
			catch (Exception ex2)
			{
				queued = 0;
				FaultSequence++;
				ManualLogSource modLog3 = Plugin.ModLog;
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(35, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Native venue hourly update failed: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex2);
				}
				modLog3.LogError(val);
			}
			finally
			{
				if (!Pending)
				{
					owner = null;
					task = null;
					acceleratedTime = null;
				}
			}
		}

		private static void ExpediteOwnedDelay()
		{
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			IUniTaskSource source = task.source;
			_HourlyUpdateTask_d__48 val = NativeHourState.Read(((source != null) ? ((Il2CppObjectBase)source).TryCast<AsyncUniTask<_HourlyUpdateTask_d__48>>() : null) ?? throw new InvalidOperationException("Unknown native venue-hour task runner; cannot safely remove its paused delay."));
			if ((Object)(object)owner == (Object)null || ((Il2CppObjectBase)val.__4__this).Pointer != ((Il2CppObjectBase)owner).Pointer || val.__1__state != 0)
			{
				throw new InvalidOperationException($"Native venue-hour await state or owner does not match: state={val.__1__state}, ownerMatches={(Object)(object)owner != (Object)null && ((Il2CppObjectBase)val.__4__this).Pointer == ((Il2CppObjectBase)owner).Pointer}.");
			}
			UniTask val2 = val.__u__1.task;
			if ((int)val2.Status == 0)
			{
				IUniTaskSource source2 = val2.source;
				DelayPromise obj = ((source2 != null) ? ((Il2CppObjectBase)source2).TryCast<DelayPromise>() : null) ?? throw new InvalidOperationException("Venue hour is awaiting an unexpected task instead of its pacing delay.");
				if (acceleratedTime == null)
				{
					acceleratedTime = Stopwatch.StartNew();
				}
				obj.delayTimeSpan = 0f;
				ProgressText = $"Updating venues {val._i_5__2 + 1}/{owner._venueGhosts.Count}...";
			}
		}
	}
	internal static class NativeHourState
	{
		private static readonly IntPtr field = IL2CPP.il2cpp_class_get_field_from_name(Il2CppClassPointerStore<AsyncUniTask<_HourlyUpdateTask_d__48>>.NativeClassPtr, "stateMachine");

		internal static _HourlyUpdateTask_d__48 Read(AsyncUniTask<_HourlyUpdateTask_d__48> runner)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			if (field == IntPtr.Zero)
			{
				throw new MissingFieldException("Native venue-hour stateMachine field was not found.");
			}
			IntPtr intPtr = IL2CPP.il2cpp_field_get_value_object(field, ((Il2CppObjectBase)runner).Pointer);
			if (intPtr == IntPtr.Zero)
			{
				throw new InvalidOperationException("Native venue-hour state could not be read.");
			}
			return new _HourlyUpdateTask_d__48(intPtr);
		}
	}
	internal static class NativeSettings
	{
		private sealed class RowCheck
		{
			internal GameObject Source;

			internal GameObject Row;

			internal int RowId;

			internal int VisibleFrame = -1;

			internal bool Reported;
		}

		private const string RateName = "HvizeuClockRate";

		private const string WaitName = "Hvizeu.Wait";

		private static InputAction? action;

		private static InputActionReference? reference;

		private static InputActionAsset? owner;

		private static LocObjRef<LocStringSingle>? waitText;

		private static readonly WaitShortcut controls = new WaitShortcut();

		private static Action<InputDevice, InputDeviceChange>? deviceChanged;

		private static readonly List<GameObject> rows = new List<GameObject>();

		private static readonly Dictionary<int, CanvasBehaviourManager> canvasOwners = new Dictionary<int, CanvasBehaviourManager>();

		private static readonly List<RowCheck> layoutChecks = new List<RowCheck>();

		internal static bool Pressed
		{
			get
			{
				if (action == null)
				{
					return false;
				}
				ReadOnlyArray<InputBinding> bindings = action.bindings;
				int i = 0;
				for (int count = bindings.Count; i < count; i++)
				{
					string effectivePath = bindings[i].effectivePath;
					if (controls.Pressed(effectivePath))
					{
						return true;
					}
				}
				return false;
			}
		}

		private static void WatchDevices()
		{
			if (deviceChanged == null)
			{
				deviceChanged = Action<InputDevice, InputDeviceChange>.op_Implicit((Action<InputDevice, InputDeviceChange>)delegate
				{
					controls.Clear();
				});
				InputSystem.onDeviceChange += deviceChanged;
			}
		}

		internal static void InitializeInput(PlayerInputManager manager)
		{
			InputActionAsset asset = manager.Input.asset;
			if ((Object)(object)owner == (Object)(object)asset && action != null)
			{
				return;
			}
			Enumerator<InputActionMap> enumerator = asset.actionMaps.GetEnumerator();
			while (enumerator.MoveNext())
			{
				if (enumerator.Current.enabled)
				{
					throw new InvalidOperationException("Wait must be registered before native input actions are enabled.");
				}
			}
			string text = "";
			enumerator = asset.actionMaps.GetEnumerator();
			while (enumerator.MoveNext())
			{
				Enumerator<InputBinding> enumerator2 = enumerator.Current.bindings.GetEnumerator();
				while (enumerator2.MoveNext())
				{
					InputBinding current = enumerator2.Current;
					string path = current.path;
					if (path != null && path.StartsWith("<Keyboard>/", StringComparison.OrdinalIgnoreCase))
					{
						text = current.groups;
						break;
					}
				}
			}
			if (string.IsNullOrEmpty(text))
			{
				throw new InvalidOperationException("Native keyboard binding group was not found.");
			}
			string text2 = "";
			enumerator = asset.actionMaps.GetEnumerator();
			while (enumerator.MoveNext())
			{
				Enumerator<InputBinding> enumerator2 = enumerator.Current.bindings.GetEnumerator();
				while (enumerator2.MoveNext())
				{
					InputBinding current2 = enumerator2.Current;
					string path2 = current2.path;
					if (path2 != null && path2.StartsWith("<Gamepad>/", StringComparison.OrdinalIgnoreCase))
					{
						text2 = current2.groups.Split(';')[0];
						break;
					}
				}
			}
			if (string.IsNullOrEmpty(text2))
			{
				throw new InvalidOperationException("Native controller binding group was not found.");
			}
			InputActionMap gameplayControls = manager.GameplayControls;
			action = InputActionSetupExtensions.AddAction(gameplayControls, "Wait", (InputActionType)1, "<Keyboard>/t", (string)null, (string)null, text, "Button");
			action.m_Id = "6697fae0-b29e-493c-9cc9-d76d317452c7";
			Il2CppReferenceArray<InputBinding> bindings = gameplayControls.m_Bindings;
			InputBinding val = ((Il2CppArrayBase<InputBinding>)(object)bindings)[((Il2CppArrayBase<InputBinding>)(object)bindings).Length - 1];
			val.m_Id = "495c85ec-ebbd-47ae-8b9c-91a662d095eb";
			((Il2CppArrayBase<InputBinding>)(object)bindings)[((Il2CppArrayBase<InputBinding>)(object)bindings).Length - 1] = val;
			InputActionSetupExtensions.AddBinding(action, "<Gamepad>/leftTrigger", (string)null, (string)null, text2);
			Il2CppReferenceArray<InputBinding> bindings2 = gameplayControls.m_Bindings;
			val = ((Il2CppArrayBase<InputBinding>)(object)bindings2)[((Il2CppArrayBase<InputBinding>)(object)bindings2).Length - 1];
			val.m_Id = "73a613ea-91c5-4aac-af1c-ff77e2968d34";
			((Il2CppArrayBase<InputBinding>)(object)bindings2)[((Il2CppArrayBase<InputBinding>)(object)bindings2).Length - 1] = val;
			gameplayControls.ClearActionLookupTable();
			gameplayControls.OnSetupChanged();
			InputActionReference val2 = reference;
			reference = InputActionReference.Create(action);
			foreach (GameObject row in rows)
			{
				if (!((Object)(object)row == (Object)null))
				{
					InputRebindUI component = row.GetComponent<InputRebindUI>();
					if ((Object)(object)component != (Object)null)
					{
						((InputDisplayUI)component).action.actionReference = reference;
					}
				}
			}
			if ((Object)(object)val2 != (Object)null)
			{
				Object.Destroy((Object)(object)val2);
			}
			owner = asset;
			RestoreBinding();
			WatchDevices();
			Plugin.ModLog.LogInfo((object)"Registered native Wait action before input activation; vanilla input was not disabled or re-enabled.");
		}

		internal static void RestoreBinding()
		{
			controls.Clear();
			if (action != null)
			{
				InputActionRebindingExtensions.ApplyBindingOverride(action, 0, Plugin.BindingPath.Value);
				InputActionRebindingExtensions.ApplyBindingOverride(action, 1, Plugin.GamepadBindingPath.Value);
			}
		}

		internal static void SaveBinding()
		{
			if (action != null)
			{
				string text = action.bindings[0].effectivePath ?? "";
				string text2 = action.bindings[1].effectivePath ?? "";
				if (!(text == Plugin.BindingPath.Value) || !(text2 == Plugin.GamepadBindingPath.Value))
				{
					Plugin.BindingPath.Value = text;
					Plugin.GamepadBindingPath.Value = text2;
					((ConfigEntryBase)Plugin.BindingPath).ConfigFile.Save();
				}
			}
		}

		internal static void Attach(GameplaySettingsUI settings)
		{
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Expected O, but got Unknown
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0244: Expected O, but got Unknown
			if ((Object)(object)((Component)settings).transform.parent.Find("Hvizeu.ModsOptions") != (Object)null)
			{
				Transform previous = ((Transform)settings.scroll.content).Find("HvizeuClockRate");
				if ((Object)(object)previous != (Object)null)
				{
					int id = ((Object)((Component)previous).gameObject).GetInstanceID();
					((SettingsTabPanel)settings)._elements = Il2CppReferenceArray<SettingUIElementBase>.op_Implicit(((IEnumerable<SettingUIElementBase>)((SettingsTabPanel)settings)._elements).Where((SettingUIElementBase e) => (Object)(object)e != (Object)null && (Object)(object)((Component)e).gameObject != (Object)(object)((Component)previous).gameObject).ToArray());
					if (canvasOwners.Remove(id, out CanvasBehaviourManager value) && (Object)(object)value != (Object)null)
					{
						CanvasBehaviourManager.UnregisterRuntimeChildren(previous, value);
					}
					rows.RemoveAll((GameObject r) => (Object)(object)r == (Object)null || (Object)(object)r == (Object)(object)((Component)previous).gameObject);
					layoutChecks.RemoveAll((RowCheck r) => r.RowId == id);
					((Component)previous).gameObject.SetActive(false);
					Object.Destroy((Object)(object)((Component)previous).gameObject);
					settings.UpdateManualUINavigation();
				}
			}
			else
			{
				if ((Object)(object)((Transform)settings.scroll.content).Find("HvizeuClockRate") != (Object)null)
				{
					return;
				}
				SettingsCategory category = ((SettingsTabPanel)settings)._category;
				category.DefaultSettings["HvizeuClockRate"] = "0.3";
				category._settings["HvizeuClockRate"] = Plugin.Rate.Value.ToString("R", CultureInfo.InvariantCulture);
				GameObject val = new GameObject("SlowDays.SettingsConstruction");
				val.SetActive(false);
				try
				{
					GameObject val2 = CloneRow(((Component)settings.mouseSensitivity).gameObject, val.transform);
					((Object)val2).name = "HvizeuClockRate";
					SliderSettingUI slider = val2.GetComponent<SliderSettingUI>();
					((SettingUIElementBase)slider).settingName = "HvizeuClockRate";
					((SettingUIElementBase)slider).OnValueChanged = null;
					((SettingUIElement<float>)(object)slider).defaultValue = 0.3f;
					slider.valueTextFormat = "F1";
					slider.slider.onValueChanged = new SliderEvent();
					slider.slider.minValue = 0f;
					slider.slider.maxValue = 2f;
					slider.slider.wholeNumbers = false;
					slider.slider.SetValueWithoutNotify(Plugin.Rate.Value);
					TextMeshProUGUI component = ((Component)val2.transform.Find("Label")).GetComponent<TextMeshProUGUI>();
					foreach (MonoBehaviour component2 in ((Component)component).GetComponents<MonoBehaviour>())
					{
						if (((MemberInfo)((Object)component2).GetIl2CppType()).Name != "TextMeshProUGUI")
						{
							((Behaviour)component2).enabled = false;
						}
					}
					((TMP_Text)component).text = "CLOCK SPEED";
					TMP_InputField precise = AddPreciseValue(slider);
					((SettingUIElementBase)slider).OnValueChanged += Action<SettingUIElementBase>.op_Implicit((Action<SettingUIElementBase>)delegate(SettingUIElementBase element)
					{
						//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
						//IL_00ab: Expected O, but got Unknown
						try
						{
							slider.slider.SetValueWithoutNotify(TimePolicy.SnapRate(((SettingUIElement<float>)(object)slider).CurrentChoice));
							slider.RefreshValueText();
							((SettingsTabPanel)settings).ApplySetting(element);
							Plugin.Rate.Value = ((SettingUIElement<float>)(object)slider).CurrentChoice;
							((ConfigEntryBase)Plugin.Rate).ConfigFile.Save();
							precise.SetTextWithoutNotify(((SettingUIElement<float>)(object)slider).CurrentChoice.ToString("F1", CultureInfo.InvariantCulture) + "x");
							((SettingsTabPanel)settings).CheckButtonsInteractability();
						}
						catch (Exception ex)
						{
							ManualLogSource modLog = Plugin.ModLog;
							bool flag = default(bool);
							BepInExErrorLogInterpolatedStringHandler val3 = new BepInExErrorLogInterpolatedStringHandler(27, 1, ref flag);
							if (flag)
							{
								((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Unable to save clock rate: ");
								((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<Exception>(ex);
							}
							modLog.LogError(val3);
						}
					});
					List<SettingUIElementBase> list = ((IEnumerable<SettingUIElementBase>)((SettingsTabPanel)settings)._elements).ToList();
					list.Add((SettingUIElementBase)(object)slider);
					((SettingsTabPanel)settings)._elements = Il2CppReferenceArray<SettingUIElementBase>.op_Implicit(list.ToArray());
					PlaceRow(val2, ((Component)settings.mouseSensitivity).gameObject);
					val2.SetActive(true);
					RegisterRow(val2);
					((TMP_Text)component).text = "CLOCK SPEED";
					slider.RefreshValueText();
					rows.Add(val2);
					settings.UpdateManualUINavigation();
					LayoutRebuilder.ForceRebuildLayoutImmediate(settings.scroll.content);
					Plugin.ModLog.LogInfo((object)"Added native Clock Speed slider to Settings > Gameplay.");
				}
				finally
				{
					Object.Destroy((Object)(object)val);
				}
			}
		}

		internal static void Attach(ControlsSettingsUI settings)
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Expected O, but got Unknown
			//IL_0047: 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_005c: Expected O, but got Unknown
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Expected O, but got Unknown
			if ((Object)(object)((Transform)settings.scroll.content).Find("Hvizeu.Wait") != (Object)null)
			{
				return;
			}
			if ((Object)(object)reference == (Object)null)
			{
				throw new InvalidOperationException("Native input asset is not ready for the Wait binding.");
			}
			if (waitText == null)
			{
				ScriptableObjectSingleton<LocObjectsDB>.Instance.AddNewObjWithGuid("hvizeu.slowdays.wait-label", (LocObjPlain)new LocStringSingle
				{
					Text = "WAIT"
				});
				LocObjRef<LocStringSingle> obj = new LocObjRef<LocStringSingle>(false);
				((LocObjRef)obj).locObjGuid = "hvizeu.slowdays.wait-label";
				waitText = obj;
			}
			GameObject val = new GameObject("SlowDays.BindingConstruction");
			val.SetActive(false);
			try
			{
				InputRebindUI val2 = null;
				Enumerator<InputRebindUI> enumerator = settings.controls.GetEnumerator();
				while (enumerator.MoveNext())
				{
					InputRebindUI current = enumerator.Current;
					Enumerator<InputBinding> enumerator2 = ((InputDisplayUI)current).action.actionReference.action.bindings.GetEnumerator();
					while (enumerator2.MoveNext())
					{
						string path = enumerator2.Current.path;
						if (path != null && path.StartsWith("<Keyboard>/"))
						{
							val2 = current;
							break;
						}
					}
					if ((Object)(object)val2 != (Object)null)
					{
						break;
					}
				}
				if ((Object)(object)val2 == (Object)null)
				{
					throw new InvalidOperationException("A native keyboard rebind row was not found.");
				}
				GameObject val3 = CloneRow(((Component)val2).gameObject, val.transform);
				((Object)val3).name = "Hvizeu.Wait";
				InputRebindUI component = val3.GetComponent<InputRebindUI>();
				ActionDisplay val4 = new ActionDisplay();
				val4.actionReference = reference;
				val4.description = ((InputDisplayUI)val2).action.description;
				val4.displayInputText = ((InputDisplayUI)val2).action.displayInputText;
				val4.compositeIndex = Il2CppStructArray<int>.op_Implicit(new int[1]);
				((InputDisplayUI)component).action = val4;
				component.actionDescription = "WAIT";
				component.locObjRef = waitText;
				component.OnSelected = null;
				component.OnSelected += Action<GameObject>.op_Implicit((Action<GameObject>)settings.Selected);
				PlaceRow(val3, ((Component)val2).gameObject);
				val3.SetActive(true);
				RegisterRow(val3);
				((TMP_Text)component.actionText).text = "WAIT";
				settings.controls.Add(component);
				settings.UpdateManualUINavigation();
				rows.Add(val3);
				LayoutRebuilder.ForceRebuildLayoutImmediate(settings.scroll.content);
				Plugin.ModLog.LogInfo((object)"Added native Wait rebinding row to Settings > Controls.");
			}
			finally
			{
				Object.Destroy((Object)(object)val);
			}
		}

		private static GameObject CloneRow(GameObject original, Transform staging)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			GameObject val = Object.Instantiate<GameObject>(original, staging, false);
			val.SetActive(false);
			int num = RestoreCanvasBehaviours(original.transform, val.transform, original.GetComponentInParent<CanvasBehaviourManager>());
			CopyGeometry(original.transform, val.transform);
			ManualLogSource modLog = Plugin.ModLog;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(89, 2, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Native Settings clone ");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(((Object)original).name);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": restored ");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(num);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" canvas-managed disabled components before registration.");
			}
			modLog.LogInfo(val2);
			return val;
		}

		private static int RestoreCanvasBehaviours(Transform source, Transform target, CanvasBehaviourManager manager)
		{
			if ((Object)(object)manager == (Object)null)
			{
				throw new InvalidOperationException("Native Settings canvas owner is missing.");
			}
			int num = 0;
			Il2CppArrayBase<Behaviour> components = ((Component)source).GetComponents<Behaviour>();
			Il2CppArrayBase<Behaviour> components2 = ((Component)target).GetComponents<Behaviour>();
			for (int i = 0; i < components.Length; i++)
			{
				if (!components[i].enabled && manager.canvasBehaviours.Contains(components[i]))
				{
					components2[i].enabled = true;
					num++;
				}
			}
			for (int j = 0; j < source.childCount; j++)
			{
				num += RestoreCanvasBehaviours(source.GetChild(j), target.GetChild(j), manager);
			}
			return num;
		}

		private static void RegisterRow(GameObject row)
		{
			CanvasBehaviourManager val = default(CanvasBehaviourManager);
			CanvasBehaviourManager.RegisterRuntimeChildren(row, ref val);
			if ((Object)(object)val == (Object)null)
			{
				throw new InvalidOperationException("Native Settings row was not registered with its canvas.");
			}
			canvasOwners[((Object)row).GetInstanceID()] = val;
		}

		private static void CopyGeometry(Transform source, Transform target)
		{
			CopyRect(((Component)source).GetComponent<RectTransform>(), ((Component)target).GetComponent<RectTransform>());
			for (int i = 0; i < source.childCount; i++)
			{
				CopyGeometry(source.GetChild(i), target.GetChild(i));
			}
		}

		private static void CopyRect(RectTransform source, RectTransform target)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: 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)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			((Transform)target).localScale = ((Transform)source).localScale;
			((Transform)target).localRotation = ((Transform)source).localRotation;
			target.anchorMin = source.anchorMin;
			target.anchorMax = source.anchorMax;
			target.pivot = source.pivot;
			target.sizeDelta = source.sizeDelta;
			target.anchoredPosition3D = source.anchoredPosition3D;
		}

		private static void PlaceRow(GameObject row, GameObject original)
		{
			row.transform.SetParent(original.transform.parent, false);
			CopyRect(original.GetComponent<RectTransform>(), row.GetComponent<RectTransform>());
			layoutChecks.Add(new RowCheck
			{
				Source = original,
				Row = row,
				RowId = ((Object)row).GetInstanceID()
			});
		}

		internal static void CheckVisibleLayouts()
		{
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Expected O, but got Unknown
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_025e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0263: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0317: Unknown result type (might be due to invalid IL or missing references)
			//IL_031c: Unknown result type (might be due to invalid IL or missing references)
			//IL_033f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0344: Unknown result type (might be due to invalid IL or missing references)
			//IL_028b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			for (int num2 = layoutChecks.Count - 1; num2 >= 0; num2--)
			{
				RowCheck rowCheck = layoutChecks[num2];
				if (!((Object)(object)rowCheck.Row != (Object)null))
				{
					canvasOwners.Remove(rowCheck.RowId);
					layoutChecks.RemoveAt(num2);
					num++;
				}
			}
			for (int num3 = rows.Count - 1; num3 >= 0; num3--)
			{
				if ((Object)(object)rows[num3] == (Object)null)
				{
					rows.RemoveAt(num3);
				}
			}
			if (num > 0)
			{
				ManualLogSource modLog = Plugin.ModLog;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(82, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Released bookkeeping for ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" destroyed native settings row(s); ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(rows.Count);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" live row(s) retained.");
				}
				modLog.LogInfo(val);
			}
			foreach (RowCheck layoutCheck in layoutChecks)
			{
				if ((Object)(object)layoutCheck.Row == (Object)null || (Object)(object)layoutCheck.Source == (Object)null || !canvasOwners.TryGetValue(((Object)layoutCheck.Row).GetInstanceID(), out CanvasBehaviourManager value) || (Object)(object)value == (Object)null)
				{
					continue;
				}
				if (!layoutCheck.Row.activeInHierarchy || !value.GetCanvasIsEnabled())
				{
					layoutCheck.VisibleFrame = -1;
					layoutCheck.Reported = false;
					continue;
				}
				if (layoutCheck.Reported)
				{
					continue;
				}
				if (layoutCheck.VisibleFrame < 0)
				{
					layoutCheck.VisibleFrame = Time.frameCount;
				}
				if (Time.frameCount - layoutCheck.VisibleFrame < 5)
				{
					continue;
				}
				layoutCheck.Reported = true;
				RectTransform component = layoutCheck.Source.GetComponent<RectTransform>();
				RectTransform component2 = layoutCheck.Row.GetComponent<RectTransform>();
				RectTransform component3 = ((Component)((Transform)component).GetChild(0)).GetComponent<RectTransform>();
				RectTransform component4 = ((Component)((Transform)component2).GetChild(0)).GetComponent<RectTransform>();
				Rect rect = component4.rect;
				float x = ((Transform)component4).TransformPoint(new Vector3(((Rect)(ref rect)).xMin, 0f, 0f)).x;
				rect = component3.rect;
				float x2 = ((Transform)component3).TransformPoint(new Vector3(((Rect)(ref rect)).xMin, 0f, 0f)).x;
				rect = component2.rect;
				int num4;
				if (((Rect)(ref rect)).width > 0f)
				{
					rect = component2.rect;
					float width = ((Rect)(ref rect)).width;
					rect = component.rect;
					if (Math.Abs(width - ((Rect)(ref rect)).width) < 2f)
					{
						rect = component4.rect;
						if (((Rect)(ref rect)).width > 50f)
						{
							num4 = ((Math.Abs(x - x2) < 2f) ? 1 : 0);
							goto IL_02b4;
						}
					}
				}
				num4 = 0;
				goto IL_02b4;
				IL_02b4:
				bool flag2 = (byte)num4 != 0;
				DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(75, 6);
				defaultInterpolatedStringHandler.AppendLiteral("Native Settings layout ");
				defaultInterpolatedStringHandler.AppendFormatted(((Object)layoutCheck.Row).name);
				defaultInterpolatedStringHandler.AppendLiteral(": width=");
				rect = component2.rect;
				defaultInterpolatedStringHandler.AppendFormatted(((Rect)(ref rect)).width, "0.0");
				defaultInterpolatedStringHandler.AppendLiteral(" native=");
				rect = component.rect;
				defaultInterpolatedStringHandler.AppendFormatted(((Rect)(ref rect)).width, "0.0");
				defaultInterpolatedStringHandler.AppendLiteral(", labelWidth=");
				rect = component4.rect;
				defaultInterpolatedStringHandler.AppendFormatted(((Rect)(ref rect)).width, "0.0");
				defaultInterpolatedStringHandler.AppendLiteral(", leftDelta=");
				defaultInterpolatedStringHandler.AppendFormatted(x - x2, "0.0");
				defaultInterpolatedStringHandler.AppendLiteral(", aligned=");
				defaultInterpolatedStringHandler.AppendFormatted(flag2);
				defaultInterpolatedStringHandler.AppendLiteral(".");
				string text = defaultInterpolatedStringHandler.ToStringAndClear();
				if (flag2)
				{
					Plugin.ModLog.LogInfo((object)text);
				}
				else
				{
					Plugin.ModLog.LogError((object)text);
				}
			}
		}

		private static TMP_InputField AddPreciseValue(SliderSettingUI setting)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: 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_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			TextMeshProUGUI valueText = setting.valueText;
			RectTransform rectTransform = ((TMP_Text)valueText).rectTransform;
			RectTransform val = new GameObject("Exact clock rate").AddComponent<RectTransform>();
			((Transform)val).SetParent(((Transform)rectTransform).parent, false);
			((Transform)val).SetSiblingIndex(((Transform)rectTransform).GetSiblingIndex());
			val.anchorMin = rectTransform.anchorMin;
			val.anchorMax = rectTransform.anchorMax;
			val.pivot = rectTransform.pivot;
			val.sizeDelta = rectTransform.sizeDelta;
			val.anchoredPosition = rectTransform.anchoredPosition;
			LayoutElement component = ((Component)rectTransform).GetComponent<LayoutElement>();
			LayoutElement val2 = ((Component)val).gameObject.AddComponent<LayoutElement>();
			Rect rect;
			float minWidth;
			if (!((Object)(object)component != (Object)null))
			{
				rect = rectTransform.rect;
				minWidth = ((Rect)(ref rect)).width;
			}
			else
			{
				minWidth = component.minWidth;
			}
			val2.minWidth = minWidth;
			float preferredWidth;
			if (!((Object)(object)component != (Object)null))
			{
				rect = rectTransform.rect;
				preferredWidth = ((Rect)(ref rect)).width;
			}
			else
			{
				preferredWidth = component.preferredWidth;
			}
			val2.preferredWidth = preferredWidth;
			float minHeight;
			if (!((Object)(object)component != (Object)null))
			{
				rect = rectTransform.rect;
				minHeight = ((Rect)(ref rect)).height;
			}
			else
			{
				minHeight = component.minHeight;
			}
			val2.minHeight = minHeight;
			float preferredHeight;
			if (!((Object)(object)component != (Object)null))
			{
				rect = rectTransform.rect;
				preferredHeight = ((Rect)(ref rect)).height;
			}
			else
			{
				preferredHeight = component.preferredHeight;
			}
			val2.preferredHeight = preferredHeight;
			if ((Object)(object)component != (Object)null)
			{
				val2.flexibleWidth = component.flexibleWidth;
				val2.flexibleHeight = component.flexibleHeight;
				val2.layoutPriority = component.layoutPriority;
			}
			((Transform)rectTransform).SetParent((Transform)(object)val, false);
			rectTransform.anchorMin = Vector2.zero;
			rectTransform.anchorMax = Vector2.one;
			Vector2 offsetMin = (rectTransform.offsetMax = Vector2.zero);
			rectTransform.offsetMin = offsetMin;
			TMP_InputField input = ((Component)val).gameObject.AddComponent<TMP_InputField>();
			input.textViewport = val;
			input.textComponent = (TMP_Text)(object)valueText;
			((Selectable)input).targetGraphic = (Graphic)(object)valueText;
			((Graphic)valueText).raycastTarget = true;
			input.contentType = (ContentType)0;
			input.lineType = (LineType)0;
			input.characterLimit = 16;
			input.richText = false;
			Navigation navigation = ((Selectable)input).navigation;
			navigation.mode = (Mode)0;
			((Selectable)input).navigation = navigation;
			input.SetTextWithoutNotify(Plugin.Rate.Value.ToString("F1", CultureInfo.InvariantCulture) + "x");
			((UnityEvent<string>)(object)input.onEndEdit).AddListener(UnityAction<string>.op_Implicit((Action<string>)delegate(string value)
			{
				//IL_0079: Unknown result type (might be due to invalid IL or missing references)
				//IL_007f: Expected O, but got Unknown
				try
				{
					if (TimePolicy.TryRate(value.Trim().TrimEnd('x', 'X'), out var value2))
					{
						setting.slider.value = TimePolicy.SnapRate(value2);
					}
					input.SetTextWithoutNotify(((SettingUIElement<float>)(object)setting).CurrentChoice.ToString("F1", CultureInfo.InvariantCulture) + "x");
				}
				catch (Exception ex)
				{
					ManualLogSource modLog = Plugin.ModLog;
					bool flag = default(bool);
					BepInExErrorLogInterpolatedStringHandler val3 = new BepInExErrorLogInterpolatedStringHandler(27, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Unable to edit clock rate: ");
						((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<Exception>(ex);
					}
					modLog.LogError(val3);
				}
			}));
			return input;
		}

		internal static void Shutdown()
		{
			if (deviceChanged != null)
			{
				InputSystem.onDeviceChange -= deviceChanged;
			}
			deviceChanged = null;
			controls.Clear();
			foreach (GameObject row in rows)
			{
				if ((Object)(object)row == (Object)null)
				{
					continue;
				}
				GameplaySettingsUI componentInParent = row.GetComponentInParent<GameplaySettingsUI>();
				if ((Object)(object)componentInParent != (Object)null)
				{
					((SettingsTabPanel)componentInParent)._elements = Il2CppReferenceArray<SettingUIElementBase>.op_Implicit(((IEnumerable<SettingUIElementBase>)((SettingsTabPanel)componentInParent)._elements).Where((SettingUIElementBase e) => (Object)(object)e != (Object)null && (Object)(object)((Component)e).gameObject != (Object)(object)row).ToArray());
				}
				ControlsSettingsUI componentInParent2 = row.GetComponentInParent<ControlsSettingsUI>();
				if ((Object)(object)componentInParent2 != (Object)null)
				{
					componentInParent2.controls.Remove(row.GetComponent<InputRebindUI>());
				}
				if (canvasOwners.TryGetValue(((Object)row).GetInstanceID(), out CanvasBehaviourManager value) && (Object)(object)value != (Object)null)
				{
					CanvasBehaviourManager.UnregisterRuntimeChildren(row.transform, value);
				}
				Object.Destroy((Object)(object)row);
			}
			rows.Clear();
			canvasOwners.Clear();
			layoutChecks.Clear();
			if (action != null && (Object)(object)owner != (Object)null)
			{
				List<InputAction> list = new List<InputAction>();
				Enumerator<InputActionMap> enumerator2 = owner.actionMaps.GetEnumerator();
				while (enumerator2.MoveNext())
				{
					Enumerator<InputAction> enumerator3 = enumerator2.Current.actions.GetEnumerator();
					while (enumerator3.MoveNext())
					{
						InputAction current = enumerator3.Current;
						if (current.enabled && current != action)
						{
							list.Add(current);
						}
					}
				}
				owner.Disable();
				try
				{
					InputActionSetupExtensions.RemoveAction(action);
				}
				finally
				{
					foreach (InputAction item in list)
					{
						item.Enable();
					}
				}
			}
			if ((Object)(object)reference != (Object)null)
			{
				Object.Destroy((Object)(object)reference);
			}
			action = null;
			reference = null;
			owner = null;
		}
	}
	internal sealed class PhoneDelayClock
	{
		private bool initialized;

		private int lastEnd;

		private int lastNow;

		private double elapsed;

		internal bool Ready(int now, int ended, float rate, float deltaSeconds, bool paused, int nativeDelay, bool dialogueActive = false)
		{
			if (dialogueActive)
			{
				elapsed = 0.0;
				initialized = true;
				lastEnd = ended;
				lastNow = now;
				return false;
			}
			rate = (float.IsFinite(rate) ? Math.Clamp(rate, 0f, 2f) : 1f);
			double num = ((rate > 0f) ? rate : 1f);
			if (!initialized || ended != lastEnd || now < lastNow)
			{
				elapsed = Math.Max(0.0, (double)now - (double)ended) / num;
				initialized = true;
			}
			else
			{
				double num2 = Math.Max(0.0, (double)now - (double)lastNow);
				double num3 = ((!paused && float.IsFinite(deltaSeconds)) ? (Math.Max(0f, deltaSeconds) * 60f) : 0f);
				elapsed += num3;
				if ((paused && num2 > 0.0) || num2 > Math.Max(2.0, num3 * num + 1.0))
				{
					elapsed += Math.Max(0.0, num2 / num - num3);
				}
			}
			lastEnd = ended;
			lastNow = now;
			return elapsed > (double)nativeDelay;
		}
	}
	[HarmonyPatch(typeof(DialogueTreeProgressManager), "Update")]
	internal static class PhoneDelayPatch
	{
		private static nint owner;

		private static PhoneDelayClock clock = new PhoneDelayClock();

		internal static void Clear()
		{
			owner = 0;
			clock = new PhoneDelayClock();
		}

		private static void Prefix(DialogueTreeProgressManager __instance, out int __state)
		{
			__state = __instance.phoneCallDelay;
			if (owner != ((Il2CppObjectBase)__instance).Pointer)
			{
				Clear();
				owner = ((Il2CppObjectBase)__instance).Pointer;
			}
			bool flag = clock.Ready(TimeOfDayManager.TotalGameSeconds, __instance._lastDialogueEndTime, Plugin.Rate.Value, Time.deltaTime, (Object)(object)Singleton<TimeOfDayManager>.Instance == (Object)null || Singleton<TimeOfDayManager>.Instance.IsPaused, __state, __instance.IsInDialogue);
			if (Plugin.Rate.Value != 1f)
			{
				__instance.phoneCallDelay = (flag ? (-1) : int.MaxValue);
			}
		}

		private static void Finalizer(DialogueTreeProgressManager __instance, int __state)
		{
			__instance.phoneCallDelay = __state;
		}
	}
	[HarmonyPatch(typeof(DialogueTreeProgressManager), "InitializeInternal")]
	internal static class ResetPhoneDelayPatch
	{
		private static void Postfix()
		{
			PhoneDelayPatch.Clear();
		}
	}
	internal static class PlacementCosts
	{
		internal static float Read(int area, bool bound, Func<int, float> agentCost, Func<int, float> worldCost)
		{
			if (!bound)
			{
				return worldCost(area);
			}
			return agentCost(area);
		}
	}
	internal readonly record struct PlacementCapsule(Vector3 Lower, Vector3 Upper, float Radius)
	{
		internal PlacementCapsule Offset(Vector3 delta)
		{
			return new PlacementCapsule(Lower + delta, Upper + delta, Radius);
		}

		internal bool Overlaps(PlacementCapsule other)
		{
			float num = Math.Max(0f, Math.Max(other.Lower.Y - Upper.Y, Lower.Y - other.Upper.Y));
			float num2 = Lower.X - other.Lower.X;
			float num3 = Lower.Z - other.Lower.Z;
			float num4 = Radius + other.Radius + 0.04f;
			return num2 * num2 + num * num + num3 * num3 < num4 * num4;
		}
	}
	internal sealed class PlacementReservations
	{
		private readonly Dictionary<nint, PlacementCapsule> positions = new Dictionary<IntPtr, PlacementCapsule>();

		internal void Reserve(nint character, PlacementCapsule volume)
		{
			positions[character] = volume;
		}

		internal void Release(nint character)
		{
			positions.Remove(character);
		}

		internal bool Overlaps(PlacementCapsule candidate)
		{
			foreach (PlacementCapsule value in positions.Values)
			{
				if (candidate.Overlaps(value))
				{
					return true;
				}
			}
			return false;
		}
	}
	internal static class PlacementSearch
	{
		internal const float Range = 3.2f;

		internal static bool CanRetainOrigin(Vector3 origin, Vector3? projected, Func<Vector3, bool> clear)
		{
			if (projected.HasValue && (projected.Value - origin).LengthSquared() < 0.0001f)
			{
				return clear(origin);
			}
			return false;
		}

		internal static Vector3? Find(Vector3 origin, Func<Vector3, Vector3?> project, Func<Vector3, bool> clear)
		{
			Vector3? result = null;
			foreach (byte item in FindSteps(origin, project, clear, delegate(Vector3? value)
			{
				result = value;
			}))
			{
				_ = item;
			}
			return result;
		}

		internal static IEnumerable<byte> FindSteps(Vector3 origin, Func<Vector3, Vector3?> project, Func<Vector3, bool> clear, Action<Vector3?> completed)
		{
			Vector3? best = null;
			float score = float.PositiveInfinity;
			for (int pass = 0; pass < 2; pass++)
			{
				if (best.HasValue)
				{
					break;
				}
				for (int ring = pass; ring <= 8; ring++)
				{
					for (int spoke = 0; spoke < ((ring == 0) ? 1 : 16); spoke++)
					{
						yield return 0;
						float x = ((float)spoke + (float)pass * 0.5f) * ((float)Math.PI / 8f);
						float num = (float)ring * 0.4f - (float)pass * 0.2f;
						Vector3? vector = project(origin + new Vector3(MathF.Cos(x) * num, 0f, MathF.Sin(x) * num));
						if (vector.HasValue)
						{
							Vector3 vector2 = vector.Value - origin;
							float num2 = vector2.LengthSquared();
							if (!(MathF.Abs(vector2.Y) > 0.5f) && !(num2 > 10.240001f) && !(num2 >= score) && clear(vector.Value))
							{
								best = vector;
								score = num2;
							}
						}
					}
				}
			}
			completed(best);
		}
	}
	[BepInPlugin("hvizeu.nivalis.slowdays", "Nivalis Slow Days", "2.0.10")]
	[BepInProcess("Nivalis Nights.exe")]
	public sealed class Plugin : BasePlugin
	{
		internal static ManualLogSource ModLog;

		internal static ConfigEntry<float> Rate;

		internal static ConfigEntry<bool> BalanceArrivals;

		internal static ConfigEntry<Key> MenuKey;

		internal static ConfigEntry<string> BindingPath;

		internal static ConfigEntry<string> GamepadBindingPath;

		private readonly Harmony harmony = new Harmony("hvizeu.nivalis.slowdays");

		public override void Load()
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Expected O, but got Unknown
			ModLog = ((BasePlugin)this).Log;
			Rate = ((BasePlugin)this).Config.Bind<float>("Time", "ClockRate", 0.3f, new ConfigDescription("Natural clock speed, rounded to tenths: 1 = original, 0.5 = half, 0.1 = tenth, 0 = frozen. Sleep and waiting keep their targets.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>()));
			BalanceArrivals = ((BasePlugin)this).Config.Bind<bool>("Balance", "ScaleCustomerArrivals", true, "Stop new restaurant visits while the clock is frozen, except during an explicit wait. At positive rates, native needs, schedules and visit/search cooldowns follow game time once. No sales-history forecast, first-day exemption or daily income cap. Prices, stock consumption, hourly pay and animation speed retain native rules.");
			MenuKey = ((BasePlugin)this).Config.Bind<Key>("Controls", "TimeMenuKey", (Key)34, "Legacy shortcut, migrated to WaitBinding. Use Settings > Controls to rebind Wait.");
			BindingPath = ((BasePlugin)this).Config.Bind<string>("Controls", "WaitBinding", "<Keyboard>/" + ((object)MenuKey.Value/*cast due to .constrained prefix*/).ToString().ToLowerInvariant(), "Wait shortcut, managed by the native Settings > Controls rebinding row.");
			GamepadBindingPath = ((BasePlugin)this).Config.Bind<string>("Controls", "WaitGamepadBinding", "<Gamepad>/leftTrigger", "Controller Wait shortcut (default LT/L2). Rebind WAIT in Settings > Controls while using a controller.");
			float num = TimePolicy.SnapRate(Rate.Value);
			if (Rate.Value != num)
			{
				Rate.Value = num;
				((BasePlugin)this).Config.Save();
			}
			try
			{
				harmony.PatchAll(typeof(Plugin).Assembly);
				((BasePlugin)this).AddComponent<TimeController>();
			}
			catch
			{
				harmony.UnpatchSelf();
				throw;
			}
			ManualLogSource log = ((BasePlugin)this).Log;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(266, 4, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Better Time 2.0.10 loaded (Steam build 25680465 bindings). Clock rate ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(Rate.Value, "F1");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; balanced customer arrivals=");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(BalanceArrivals.Value);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; Wait binding ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(BindingPath.Value);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; controller Wait binding ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(GamepadBindingPath.Value);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(". Native needs and visit/search cooldowns follow game time once. No additional admission multiplier or sales-history forecast.");
			}
			log.LogInfo(val);
		}

		public override bool Unload()
		{
			TimeController? current = TimeController.Current;
			if ((current != null && current.Busy) || HourlyWork.Pending)
			{
				return false;
			}
			TimeController.Current?.Shutdown();
			NativeSettings.Shutdown();
			PhoneDelayPatch.Clear();
			harmony.UnpatchSelf();
			return true;
		}
	}
	[HarmonyPatch(typeof(TimeOfDayManager), "Update")]
	internal static class ClockUpdatePatch
	{
		internal struct TickState
		{
			public float Original;

			public bool Applied;
		}

		[HarmonyPrefix]
		private static void Prefix(TimeOfDayManager __instance, out TickState __state)
		{
			__state = new TickState
			{
				Original = __instance.timeTickMultiplier
			};
			float value = Plugin.Rate.Value;
			__instance.timeTickMultiplier = __state.Original * (float.IsFinite(value) ? Math.Clamp(value, 0f, 2f) : 1f);
			__state.Applied = true;
		}

		[HarmonyFinalizer]
		private static void Finalizer(TimeOfDayManager __instance, TickState __state)
		{
			if (__state.Applied)
			{
				__instance.timeTickMultiplier = __state.Original;
			}
		}
	}
	[HarmonyPatch(typeof(VenueManager), "OnHourTick")]
	internal static class HourlyPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(VenueManager __instance)
		{
			return !HourlyWork.Start(__instance);
		}
	}
	[HarmonyPatch(typeof(GameplaySettingsUI), "BeforeDisplay")]
	internal static class SettingsEntryPatch
	{
		[HarmonyPostfix]
		private static void Postfix(GameplaySettingsUI __instance)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			try
			{
				NativeSettings.Attach(__instance);
			}
			catch (Exception ex)
			{
				ManualLogSource modLog = Plugin.ModLog;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(43, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Unable to add Slow Days gameplay settings: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
				}
				modLog.LogError(val);
			}
		}
	}
	[HarmonyPatch(typeof(ControlsSettingsUI), "Start")]
	internal static class ControlsEntryPatch
	{
		[HarmonyPostfix]
		private static void Postfix(ControlsSettingsUI __instance)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			try
			{
				NativeSettings.Attach(__instance);
			}
			catch (Exception ex)
			{
				ManualLogSource modLog = Plugin.ModLog;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(35, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Unable to add native Wait binding: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
				}
				modLog.LogError(val);
			}
		}
	}
	[HarmonyPatch(typeof(PlayerInputManager), "LoadBindings")]
	internal static class RestoreWaitBindingPatch
	{
		[HarmonyPrefix]
		private static void Prefix(PlayerInputManagerSave save)
		{
			WaitBindingPersistencePatch.RemoveOwnOverride(save);
		}

		[HarmonyPostfix]
		private static void Postfix()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			try
			{
				NativeSettings.RestoreBinding();
			}
			catch (Exception ex)
			{
				ManualLogSource modLog = Plugin.ModLog;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(49, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Unable to restore Wait shortcut after save load: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
				}
				modLog.LogError(val);
			}
		}
	}
	[HarmonyPatch(typeof(InputRebindUI), "UpdateText")]
	internal static class WaitBindingLabelPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(InputRebindUI __instance)
		{
			if (((Object)((Component)__instance).gameObject).name != "Hvizeu.Wait")
			{
				return true;
			}
			((TMP_Text)__instance.actionText).text = "WAIT";
			return false;
		}
	}
	[HarmonyPatch(typeof(PlayerInputManager), "InitializeInternal")]
	internal static class RegisterWaitInputPatch
	{
		[HarmonyPrefix]
		private static void Prefix(ISavePacket packet)
		{
			if (packet != null)
			{
				WaitBindingPersistencePatch.RemoveOwnOverride(((Il2CppObjectBase)packet).TryCast<PlayerInputManagerSave>());
			}
		}

		[HarmonyPostfix]
		private static void Postfix(PlayerInputManager __instance)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			try
			{
				NativeSettings.InitializeInput(__instance);
			}
			catch (Exception ex)
			{
				ManualLogSource modLog = Plugin.ModLog;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(94, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Wait input registration failed; vanilla input was left enabled/disabled as owned by the game: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
				}
				modLog.LogError(val);
			}
		}
	}
	[HarmonyPatch(typeof(PlayerInputManager), "SaveBindings")]
	internal static class WaitBindingPersistencePatch
	{
		[HarmonyPostfix]
		private static void Postfix(PlayerInputManagerSave save)
		{
			NativeSettings.SaveBinding();
			RemoveOwnOverride(save);
		}

		internal static void RemoveOwnOverride(PlayerInputManagerSave? save)
		{
			if (save != null)
			{
				string bindingJsonString = save.BindingJsonString;
				string text = BindingJson.WithoutWait(bindingJsonString);
				if (!(text == bindingJsonString))
				{
					save.BindingJsonString = text;
					Plugin.ModLog.LogInfo((object)"Kept Wait override in mod config; removed its entry from native binding packet. Other bindings retained.");
				}
			}
		}
	}
	[HarmonyPatch(typeof(Debug), "LogException", new Type[] { typeof(Exception) })]
	internal static class ObserveWaitNativeException
	{
		[HarmonyPrefix]
		private static void Prefix(Exception exception)
		{
			if (WaitFaults.Active)
			{
				WaitFaults.ObserveException(((exception != null) ? ((Object)exception).ToString() : null) ?? "Native exception", "Unity Debug.LogException");
			}
		}
	}
	public sealed class TimeController : MonoBehaviour
	{
		internal static TimeController? Current;

		private TimeMenu? menu;

		private AgentGhostSimulator? simulator;

		private WaitPacer? pacer;

		private WaitCrowdRefresh? crowdRefresh;

		private string? completionMessage;

		private float handoffStarted;

		private IEnumerator<byte>? presentationSteps;

		private bool closeAfterHandoff;

		private float nextSettingsCheck;

		private float nextHudCheck;

		private int simulationTicks;

		private float waitStarted;

		private bool quitting;

		private readonly List<OverrideLock> locks = new List<OverrideLock>();

		private OverrideLock? saveLock;

		private bool busy;

		private bool cancel;

		private bool enabledMod = true;

		private bool reopenPlayerMenu;

		private bool uiFailed;

		private int openedFrame;

		private int start;

		private int target;

		private int expectedTime;

		private int faultSequence;

		private float lastRefresh;

		private float taskStarted;

		private WaitLedger before;

		private string status = "Choose your pace. Stay until the city closes.";

		[HideFromIl2Cpp]
		internal bool Busy => busy;

		public TimeController(IntPtr pointer)
			: base(pointer)
		{
		}

		public void Awake()
		{
			Current = this;
		}

		[HideFromIl2Cpp]
		internal static bool GameplayReady()
		{
			if (Singleton<GameSceneManager>.InstanceExist() && Singleton<GameSceneManager>.Instance.IsGame && Singleton<GameSceneManager>.Instance.IsGameplayInitialized && !Singleton<GameSceneManager>.Instance.IsLoading && !GameSceneManager.IsUnloadingGameplay && Singleton<TimeOfDayManager>.InstanceExist() && Singleton<PlayerManager>.InstanceExist())
			{
				Player localPlayer = Singleton<PlayerManager>.Instance.LocalPlayer;
				if ((Object)(object)((localPlayer != null) ? localPlayer.Character : null) != (Object)null)
				{
					if (Singleton<ManagersBootstrap>.InstanceExist())
					{
						return !Singleton<ManagersBootstrap>.Instance.IsLoadingSaveFile;
					}
					return true;
				}
			}
			return false;
		}

		[HideFromIl2Cpp]
		private static string? BlockReason()
		{
			if (HourlyWork.NeedsUnpausedDrain)
			{
				return "The previous venue update is recovering. Return to gameplay briefly.";
			}
			if (!GameplayReady())
			{
				return "Load a save and return to normal gameplay.";
			}
			if (Singleton<DialogueTreeProgressManager>.InstanceExist() && Singleton<DialogueTreeProgressManager>.Instance.IsInDialogue)
			{
				return "Finish the conversation first.";
			}
			Player localPlayer = Singleton<PlayerManager>.Instance.LocalPlayer;
			if (localPlayer.IsHoldingObject)
			{
				return "Put down the object you are carrying first.";
			}
			if ((Object)(object)localPlayer.Character.DrivenBoat != (Object)null)
			{
				return "Leave your vehicle before waiting.";
			}
			if (!Singleton<VenueManager>.InstanceExist() || !Singleton<VenueManager>.Instance.RuntimeVenueDataIsInitialized)
			{
				return "The city's businesses are still loading.";
			}
			return null;
		}

		public void Update()
		{
			if (!enabledMod)
			{
				return;
			}
			HourlyWork.Poll();
			try
			{
				if (GameSceneManager.IsUnloadingGameplay || (Singleton<GameSceneManager>.InstanceExist() && Singleton<GameSceneManager>.Instance.IsLoading) || (Singleton<ManagersBootstrap>.InstanceExist() && Singleton<ManagersBootstrap>.Instance.IsLoadingSaveFile))
				{
					if (menu != null)
					{
						CloseForSceneChange();
					}
					return;
				}
				if (Time.unscaledTime >= nextSettingsCheck)
				{
					nextSettingsCheck = Time.unscaledTime + 0.25f;
					NativeSettings.SaveBinding();
					NativeSettings.CheckVisibleLayouts();
				}
				if (menu == null && !uiFailed && Time.unscaledTime >= nextHudCheck)
				{
					nextHudCheck = Time.unscaledTime + 0.5f;
					if (GameplayReady())
					{
						WorldStateDisplayUI val = Object.FindObjectOfType<WorldStateDisplayUI>();
						if ((Object)(object)val != (Object)null)
						{
							AttachMenu(val);
						}
					}
				}
				if (menu == null)
				{
					return;
				}
				if (busy)
				{
					TickWait();
				}
				if (Application.isFocused && Time.frameCount > openedFrame + 1)
				{
					if (menu.Visible)
					{
						Keyboard current = Keyboard.current;
						if ((current != null && ((ButtonControl)current.escapeKey).wasPressedThisFrame) || Singleton<PlayerInputManager>.Instance.Input.MenuControls.Cancel.WasPressedThisFrame())
						{
							if (busy)
							{
								cancel = true;
							}
							else
							{
								Close();
							}
						}
						else if (!menu.Editing && NativeSettings.Pressed)
						{
							if (busy)
							{
								cancel = true;
							}
							else
							{
								Close();
							}
						}
					}
					else if (NativeSettings.Pressed && GameplayReady() && !Singleton<PlayerInputManager>.Instance.PreventGameplayMenuShortcuts.Value && !Singleton<PlayerInputManager>.Instance.PreventAllMenuShortcuts.Value && Singleton<PlayerManager>.Instance.LocalPlayer.Character.Controller.CanMove && !Singleton<TimeOfDayManager>.Instance.IsPaused)
					{
						Open(fromPlayerMenu: false);
					}
				}
				if (menu.Visible)
				{
					menu.EnsureControllerSelection();
					if (Time.unscaledTime - lastRefresh > 0.15f)
					{
						Refresh();
					}
				}
			}
			catch (Exception ex)
			{
				Fail(ex);
			}
		}

		[HideFromIl2Cpp]
		internal void Fail(Exception ex)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			ManualLogSource modLog = Plugin.ModLog;
			bool flag = default(bool);
			BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(19, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Time & Wait error: ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
			}
			modLog.LogError(val);
			cancel = true;
			if (HourlyWork.NeedsUnpausedDrain)
			{
				closeAfterHandoff = true;
				reopenPlayerMenu = false;
			}
			if (!busy)
			{
				status = "Waiting stopped after an error. Progress is retained; see the BepInEx log.";
				if (closeAfterHandoff)
				{
					closeAfterHandoff = false;
					Close();
				}
				Refresh();
			}
			else if (HourlyWork.Pending && !HourlyWork.NeedsUnpausedDrain)
			{
				status = "An error occurred. Finishing the active venue update before stopping.";
			}
			else if (completionMessage == null)
			{
				Finish("Waiting stopped after an error. Progress is retained; see the BepInEx log.");
			}
			else if (presentationSteps == null)
			{
				BeginHandoff();
			}
			else
			{
				presentationSteps.Dispose();
				presentationSteps = null;
				WaitPresentation.Abandon();
				FinishImmediate("Waiting stopped after an error. Progress is retained; see the BepInEx log.");
			}
		}

		[HideFromIl2Cpp]
		internal void AttachMenu(WorldStateDisplayUI hud)
		{
			if (uiFailed)
			{
				return;
			}
			try
			{
				if (menu == null)
				{
					menu = new TimeMenu(this, hud);
				}
			}
			catch
			{
				uiFailed = true;
				throw;
			}
		}

		[HideFromIl2Cpp]
		internal void Open(bool fromPlayerMenu)
		{
			if (menu == null || menu.Visible)
			{
				return;
			}
			string text = BlockReason();
			if (text != null)
			{
				Plugin.ModLog.LogInfo((object)text);
				return;
			}
			reopenPlayerMenu = fromPlayerMenu;
			if (fromPlayerMenu)
			{
				((UIPanel)InGameMenuUi.Instance).Hide();
			}
			try
			{
				locks.Add(Singleton<PlayerInputManager>.Instance.PreventAllMenuShortcuts.Override((Object)(object)this));
				PlayerCharacter character = Singleton<PlayerManager>.Instance.LocalPlayer.Character;
				locks.Add(TimeOfDayManager.Pause((Object)(object)this));
				locks.Add(character.Controller.DisableMovement((Object)(object)this));
				locks.Add(character.Controller.LockCamera((Object)(object)this));
				locks.Add(character.Interaction.DisableInteractions((Object)(object)this));
				openedFrame = Time.frameCount;
				menu.Show();
				status = (TimePolicy.InCurfew(TimeOfDayManager.TotalGameSeconds) ? "Curfew is in effect. Go to bed and sleep; waiting resumes at 08:00." : ((Plugin.Rate.Value == 0f) ? "Clock frozen: waiting simulates at normal speed." : "Businesses continue serving customers while you wait."));
				Refresh();
			}
			catch
			{
				Close();
				throw;
			}
		}

		[HideFromIl2Cpp]
		internal void Close()
		{
			if (busy)
			{
				cancel = true;
				return;
			}
			openedFrame = Time.frameCount;
			menu?.Hide();
			ReleaseLocks();
			if (reopenPlayerMenu && GameplayReady() && (Object)(object)InGameMenuUi.Instance != (Object)null)
			{
				((UIWindow)InGameMenuUi.Instance).Reopen();
			}
			reopenPlayerMenu = false;
		}

		[HideFromIl2Cpp]
		private void ReleaseLocks()
		{
			OverrideLock? obj = saveLock;
			if (obj != null)
			{
				obj.Release();
			}
			saveLock = null;
			foreach (OverrideLock @lock in locks)
			{
				if (!@lock.IsReleased)
				{
					@lock.Release();
				}
			}
			locks.Clear();
		}

		[HideFromIl2Cpp]
		internal void BeginWait()
		{
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Expected O, but got Unknown
			if (busy || menu == null)
			{
				return;
			}
			string text = BlockReason();
			if (text != null)
			{
				status = text;
				Refresh();
				return;
			}
			if (!double.TryParse(menu.HoursText.Replace(',', '.'), NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var result) || !double.IsFinite(result) || result <= 0.0 || result > 24.0)
			{
				status = "Enter a duration greater than 0 and no more than 24 hours.";
				Refresh();
				return;
			}
			start = TimeOfDayManager.TotalGameSeconds;
			target = TimePolicy.Target(start, result);
			if (target <= start)
			{
				status = (TimePolicy.InCurfew(start) ? "Waiting is unavailable during curfew (02:00-08:00). Go to bed and sleep." : "Choose a duration of at least one game second.");
				Refresh();
				return;
			}
			simulator = Object.FindObjectOfType<AgentGhostSimulator>();
			if ((Object)(object)simulator == (Object)null || !simulator._isInitialized)
			{
				status = "The customer simulation is not ready. Return to gameplay and try again.";
				Refresh();
				return;
			}
			if (!((IEnumerable<GhostSimulator>)simulator.simulators).Any((GhostSimulator x) => (Object)(object)((Il2CppObjectBase)x).TryCast<AgentViewSimulator>() != (Object)null) || !((IEnumerable<GhostSimulator>)simulator.simulators).Any((GhostSimulator x) => (Object)(object)((Il2CppObjectBase)x).TryCast<AgentStateUpdateSimulator>() != (Object)null))
			{
				status = "Required native movement/needs simulators are unavailable. Waiting was not started.";
				Refresh();
				return;
			}
			TimeStamp lastRecordedTime = simulator._lastRecordedTime;
			if (((TimeStamp)(ref lastRecordedTime)).TotalGameSeconds != start)
			{
				status = "The city clock is synchronising. Return to gameplay briefly and try again.";
				Refresh();
				return;
			}
			pacer = new WaitPacer(Singleton<TimeOfDayManager>.Instance.timeTickMultiplier, Plugin.Rate.Value);
			saveLock = Singleton<PlayerInputManager>.Instance.PreventSaving.Override((Object)(object)this);
			before = WaitLedger.Read();
			completionMessage = null;
			closeAfterHandoff = false;
			simulationTicks = 0;
			waitStarted = Time.unscaledTime;
			expectedTime = start;
			faultSequence = HourlyWork.FaultSequence;
			cancel = false;
			busy = true;
			WaitSimulation.DrainLifecycle();
			WaitPresentation.Begin();
			taskStarted = Time.unscaledTime;
			ManualLogSource modLog = Plugin.ModLog;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(270, 4, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Wait started: ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(start);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" -> ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(target);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; natural clock rate=");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(Plugin.Rate.Value);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; native baseline=");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(Singleton<TimeOfDayManager>.Instance.timeTickMultiplier);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; <=5 game-second and <=0.25 action-second steps; actions and loaded commands honor positive clock rate (0 uses 1x); needs/offscreen movement use game seconds / 60. Native menu selection and transactions retained.");
			}
			modLog.LogInfo(val);
			Refresh();
		}

		[HideFromIl2Cpp]
		private void TickWait()
		{
			if (completionMessage != null)
			{
				if (presentationSteps != null)
				{
					long timestamp = Stopwatch.GetTimestamp();
					for (int i = 0; i < 128; i++)
					{
						if (!presentationSteps.MoveNext())
						{
							presentationSteps.Dispose();
							presentationSteps = null;
							FinishImmediate(completionMessage);
							break;
						}
						if ((double)(Stopwatch.GetTimestamp() - timestamp) / (double)Stopwatch.Frequency >= 0.004)
						{
							break;
						}
					}
				}
				else if (crowdRefresh.Poll())
				{
					BeginHandoff();
				}
				else if (Time.unscaledTime - handoffStarted > 30f)
				{
					throw new TimeoutException("Arrival crowd refresh did not finish within 30 seconds. See native logs; no further time was advanced.");
				}
				return;
			}
			if (HourlyWork.NeedsUnpausedDrain)
			{
				closeAfterHandoff = true;
				reopenPlayerMenu = false;
				Finish("Waiting stopped so the active venue update can recover in normal gameplay. See the BepInEx log.");
				return;
			}
			if (HourlyWork.Pending)
			{
				status = ((Time.unscaledTime - taskStarted > 30f) ? "A venue update is taking longer than expected. Waiting is paused; Cancel stops after it finishes." : HourlyWork.ProgressText);
				return;
			}
			if (HourlyWork.FaultSequence != faultSequence)
			{
				Finish("A venue update failed. Waiting stopped; see the BepInEx log.");
				return;
			}
			if (cancel)
			{
				Finish("Waiting cancelled. Time already passed is retained.");
				return;
			}
			string text = BlockReason();
			if (text != null)
			{
				Finish(text);
				return;
			}
			int totalGameSeconds = TimeOfDayManager.TotalGameSeconds;
			if (totalGameSeconds != expectedTime)
			{
				Finish("Another game event changed the clock. Waiting stopped.");
				return;
			}
			if (totalGameSeconds >= target)
			{
				Finish(TimePolicy.InCurfew(totalGameSeconds) ? "Curfew has begun. Go to bed and sleep." : "Wait complete.");
				return;
			}
			if ((Object)(object)simulator == (Object)null || !simulator._isInitialized)
			{
				Finish("Customer simulation became unavailable. Waiting stopped.");
				return;
			}
			long timestamp2 = Stopwatch.GetTimestamp();
			for (int j = 0; j < 512; j++)
			{
				(float, int, float) tuple = pacer.Next(totalGameSeconds, target);
				expectedTime = checked(totalGameSeconds + tuple.Item2);
				WaitSimulation.Advance(simulator, Singleton<TimeOfDayManager>.Instance, tuple.Item1, tuple.Item2, tuple.Item3);
				simulationTicks++;
				totalGameSeconds = TimeOfDayManager.TotalGameSeconds;
				if (totalGameSeconds != expectedTime)
				{
					Finish("Another game event changed the clock. Waiting stopped.");
					return;
				}
				if (totalGameSeconds >= target || HourlyWork.Pending || HourlyWork.FaultSequence != faultSequence || (double)(Stopwatch.GetTimestamp() - timestamp2) / (double)Stopwatch.Frequency >= 0.024)
				{
					break;
				}
			}
			taskStarted = Time.unscaledTime;
			status = "Waiting  " + TimePolicy.Clock(totalGameSeconds) + "  >  " + TimePolicy.Clock(target);
		}

		[HideFromIl2Cpp]
		private void Finish(string message)
		{
			if (!busy || !GameplayReady())
			{
				FinishImmediate(message);
			}
			else if (completionMessage == null)
			{
				completionMessage = message;
				crowdRefresh = new WaitCrowdRefresh();
				handoffStarted = Time.unscaledTime;
				status = "Updating the city for your arrival...";
				Refresh();
			}
		}

		[HideFromIl2Cpp]
		private void BeginHandoff()
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			crowdRefresh?.Abandon();
			crowdRefresh = null;
			try
			{
				if ((Object)(object)simulator != (Object)null && simulator._isInitialized)
				{
					WaitSimulation.SyncViews(simulator);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource modLog = Plugin.ModLog;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(63, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Wait view synchronization failed; recovering NPC presentation: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
				}
				modLog.LogError(val);
				completionMessage = "Waiting stopped after a view synchronization error. See the BepInEx log.";
			}
			presentationSteps = WaitPresentation.ResumeSteps().GetEnumerator();
			status = "Restoring character positions and animations...";
		}

		[HideFromIl2Cpp]
		private void FinishImmediate(string message)
		{
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Expected O, but got Unknown
			crowdRefresh?.Abandon();
			crowdRefresh = null;
			completionMessage = null;
			bool flag = busy;
			busy = false;
			cancel = false;
			OverrideLock? obj = saveLock;
			if (obj != null)
			{
				obj.Release();
			}
			saveLock = null;
			status = message;
			try
			{
				if (flag && GameplayReady())
				{
					WaitLedger waitLedger = WaitLedger.Read().Since(before);
					status += $"\nCash in: {StringHelper.PriceToString(waitLedger.Gain, false)}   Out: {StringHelper.PriceToString(checked(-waitLedger.Loss), false)}   Net: {StringHelper.PriceToString(waitLedger.NetCash, true)}\nMeals: {waitLedger.Meals}   Visits: {waitLedger.Visits}. Stock costs excluded; not profit.";
					ManualLogSource modLog = Plugin.ModLog;
					bool flag2 = default(bool);
					BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(256, 14, ref flag2);
					if (flag2)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(message);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" Clock=");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(TimeOfDayManager.TotalGameSeconds);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; meals=");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(waitLedger.Meals);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; visits=");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(waitLedger.Visits);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; income=");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(waitLedger.Gain);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; expenses=");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(waitLedger.Loss);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; mealSales=");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(waitLedger.MealSales);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; shopping=");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(waitLedger.Shopping);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; staffPay=");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(waitLedger.StaffPay);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; otherIncome=");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(waitLedger.OtherIncome);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; otherExpenses=");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(waitLedger.OtherExpenses);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; netCash=");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(waitLedger.NetCash);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; actionTicks=");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(simulationTicks);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; wallSeconds=");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(Time.unscaledTime - waitStarted, "F2");
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(". Amounts are cents; shopping includes all shop purchases; net cash is not profit or ingredient cost of sales.");
					}
					modLog.LogInfo(val);
				}
				else if (flag)
				{
					WaitPresentation.Abandon();
				}
			}
			finally
			{
				if (closeAfterHandoff)
				{
					closeAfterHandoff = false;
					Close();
				}
			}
			Refresh();
		}

		[HideFromIl2Cpp]
		private void Refresh()
		{
			lastRefresh = Time.unscaledTime;
			menu?.Refresh(status, busy, start, target);
		}

		[HideFromIl2Cpp]
		private void CloseForSceneChange()
		{
			presentationSteps?.Dispose();
			presentationSteps = null;
			closeAfterHandoff = false;
			crowdRefresh?.Abandon();
			crowdRefresh = null;
			completionMessage = null;
			WaitPresentation.Abandon();
			if (busy)
			{
				Plugin.ModLog.LogWarning((object)"Scene transition interrupted waiting; no additional time will be advanced.");
			}
			busy = false;
			cancel = false;
			reopenPlayerMenu = false;
			uiFailed = false;
			menu?.Dispose();
			menu = null;
			simulator = null;
			ReleaseLocks();
		}

		[HideFromIl2Cpp]
		internal void Shutdown()
		{
			CloseForSceneChange();
			enabledMod = false;
			Current = null;
		}

		public void OnApplicationQuit()
		{
			quitting = true;
		}

		public void OnDestroy()
		{
			if (!((Object)(object)Current != (Object)(object)this))
			{
				if (quitting)
				{
					Current = null;
				}
				else
				{
					Shutdown();
				}
			}
		}
	}
	internal sealed class TimeMenu : IDisposable
	{
		private readonly TimeController controller;

		private readonly WorldStateDisplayUI source;

		private readonly GameObject root;

		private readonly UIPanel panel;

		private readonly TextMeshProUGUI textStyle;

		private readonly TMP_InputField hours;

		private readonly TextMeshProUGUI destination;

		private readonly TextMeshProUGUI available;

		private readonly TextMeshProUGUI status;

		private readonly TextMeshProUGUI progress;

		private readonly TextMeshProUGUI waitLabel;

		private readonly TextMeshProUGUI hudTime;

		private readonly TextMeshProUGUI hudDay;

		private readonly TextMeshProUGUI hudMoney;

		private readonly RectTransform hourHand;

		private readonly RectTransform minuteHand;

		private readonly Button wait;

		private readonly Button minus;

		private readonly Button plus;

		private readonly Button close;

		private GameObject? previousSelection;

		private int shownFrame;

		private readonly Texture2D clockTexture;

		private readonly Sprite clockSprite;

		private readonly Sprite? panelSprite;

		private readonly Sprite? buttonSprite;

		private readonly Sprite? outlineSprite;

		private readonly Image nativeFrame;

		private readonly Image dimmer;

		private readonly Image progressFill;

		private readonly List<(TextMeshProUGUI Source, TextMeshProUGUI Copy)> hudLabels = new List<(TextMeshProUGUI, TextMeshProUGUI)>();

		private bool disposed;

		private static readonly Color Amber = new Color(0.82f, 0.67f, 0.43f, 1f);

		private static readonly Color Blue = new Color(0.32f, 0.61f, 0.87f, 1f);

		private static readonly Color Muted = new Color(0.63f, 0.61f, 0.57f, 1f);

		internal bool Visible
		{
			get
			{
				if (!disposed)
				{
					return panel.IsVisible;
				}
				return false;
			}
		}

		internal bool Editing => hours.isFocused;

		internal string HoursText => hours.text;

		internal TimeMenu(TimeController controller, WorldStateDisplayUI source)
		{
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Expected O, but got Unknown
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_029c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0345: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_0411: Unknown result type (might be due to invalid IL or missing references)
			//IL_0548: Unknown result type (might be due to invalid IL or missing references)
			//IL_0601: Unknown result type (might be due to invalid IL or missing references)
			//IL_0646: Unknown result type (might be due to invalid IL or missing references)
			//IL_0673: Unknown result type (might be due to invalid IL or missing references)
			//IL_06a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_06c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_070a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0714: Expected O, but got Unknown
			//IL_078a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0799: Unknown result type (might be due to invalid IL or missing references)
			//IL_07e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0816: Unknown result type (might be due to invalid IL or missing references)
			//IL_0845: Unknown result type (might be due to invalid IL or missing references)
			//IL_0864: Unknown result type (might be due to invalid IL or missing references)
			//IL_0896: Unknown result type (might be due to invalid IL or missing references)
			//IL_08c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0900: Unknown result type (might be due to invalid IL or missing references)
			//IL_0935: Unknown result type (might be due to invalid IL or missing references)
			//IL_0964: Unknown result type (might be due to invalid IL or missing references)
			//IL_0969: Unknown result type (might be due to invalid IL or missing references)
			//IL_096a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0971: Unknown result type (might be due to invalid IL or missing references)
			//IL_098d: Unknown result type (might be due to invalid IL or missing references)
			//IL_09ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b0e: Unknown result type (might be due to invalid IL or missing references)
			TimeMenu timeMenu = this;
			this.controller = controller;
			this.source = source;
			textStyle = source.dayTMP;
			nativeFrame = ((Component)((Component)source).transform.Find("NavigationGraphic")).GetComponent<Image>();
			Il2CppArrayBase<Sprite> obj = Resources.FindObjectsOfTypeAll<Sprite>();
			Dictionary<string, Sprite> art = new Dictionary<string, Sprite>(StringComparer.Ordinal);
			foreach (Sprite item in obj)
			{
				if (!((Object)(object)item == (Object)null))
				{
					string name = ((Object)item).name;
					bool flag;
					switch (name)
					{
					case "9S_HUD_Panel":
					case "9S_ButtonResponse":
					case "9S_Square-2-Outline":
					case "9s_PopupFrame":
					case "9S_TitleFrame_Filled":
						flag = true;
						break;
					default:
						flag = false;
						break;
					}
					if (flag)
					{
						art.TryAdd(name, item);
					}
					if (art.Count == 5)
					{
						break;
					}
				}
			}
			panelSprite = Art("9S_HUD_Panel");
			buttonSprite = Art("9S_ButtonResponse");
			outlineSprite = Art("9S_Square-2-Outline");
			root = new GameObject("Hvizeu.Wait");
			root.SetActive(false);
			Object.DontDestroyOnLoad((Object)(object)root);
			try
			{
				Canvas obj2 = root.AddComponent<Canvas>();
				obj2.renderMode = (RenderMode)0;
				obj2.sortingOrder = 30000;
				CanvasScaler obj3 = root.AddComponent<CanvasScaler>();
				obj3.uiScaleMode = (ScaleMode)1;
				obj3.referenceResolution = new Vector2(1920f, 1080f);
				obj3.screenMatchMode = (ScreenMatchMode)1;
				root.AddComponent<GraphicRaycaster>();
				CanvasGroup canvasGroup = root.AddComponent<CanvasGroup>();
				panel = root.AddComponent<UIPanel>();
				panel._canvasGroup = canvasGroup;
				panel._startVisible = false;
				panel.requiresMouse = true;
				UIPanel obj4 = panel;
				bool flag = (panel.pauseTimeCompletely = true);
				obj4.pauseTimeWhenOpen = flag;
				UIPanel obj5 = panel;
				flag = (panel.closeWithPause = false);
				obj5.closeWithCancel = flag;
				dimmer = Box(root.transform, "Dimmer", 0f, 0f, 1920f, 1080f, new Color(0f, 0f, 0f, 0.55f));
				((Graphic)dimmer).rectTransform.anchorMin = Vector2.zero;
				((Graphic)dimmer).rectTransform.anchorMax = Vector2.one;
				RectTransform rectTransform = ((Graphic)dimmer).rectTransform;
				Vector2 offsetMin = (((Graphic)dimmer).rectTransform.offsetMax = Vector2.zero);
				rectTransform.offsetMin = offsetMin;
				RectTransform parent = Rect(root.transform, "Wait composition", 0f, 0f, 1080f, 720f);
				Image obj6 = Box((Transform)(object)parent, "Native popup frame", 0f, 0f, 1080f, 720f, Color.white);
				obj6.sprite = Art("9s_PopupFrame") ?? panelSprite ?? nativeFrame.sprite;
				obj6.type = (Type)1;
				obj6.pixelsPerUnitMultiplier = 2f;
				((Graphic)obj6).raycastTarget = false;
				Image val = Box((Transform)(object)parent, "Native title frame", 0f, 305f, 670f, 102f, Color.white);
				val.sprite = Art("9S_TitleFrame_Filled") ?? nativeFrame.sprite;
				val.preserveAspect = true;
				((Graphic)val).raycastTarget = false;
				Label(((Component)val).transform, "WAIT", 0f, 4f, 520f, 48f, 30f, Amber);
				RectTransform parent2 = Rect((Transform)(object)parent, "Native world state strip", 0f, -20f, 800f, 160f);
				string[] array = new string[5] { "NavigationGraphic", "TimeDisplay", "MoneyWrapper", "Date", "TimerIcon" };
				foreach (string text in array)
				{
					CopyVisualTree(((Il2CppObjectBase)((Component)source).transform.Find(text)).Cast<RectTransform>(), (Transform)(object)parent2);
				}
				hudTime = hudLabels.Single<(TextMeshProUGUI, TextMeshProUGUI)>(((TextMeshProUGUI Source, TextMeshProUGUI Copy) x) => (Object)(object)x.Source == (Object)(object)source.timeTMP).Item2;
				hudDay = hudLabels.Single<(TextMeshProUGUI, TextMeshProUGUI)>(((TextMeshProUGUI Source, TextMeshProUGUI Copy) x) => (Object)(object)x.Source == (Object)(object)source.dayTMP).Item2;
				hudMoney = hudLabels.Single<(TextMeshProUGUI, TextMeshProUGUI)>(((TextMeshProUGUI Source, TextMeshProUGUI Copy) x) => (Object)(object)x.Source == (Object)(object)source.moneyDisplay.valueText).Item2;
				RectTransform parent3 = Wing((Transform)(object)parent, "Duration", -300f, 115f);
				Label((Transform)(object)parent3, "WAIT FOR", 0f, 49f, 210f, 30f, 21f, Amber);
				hours = Field((Transform)(object)parent3, 0f, -5f, 110f, 58f, "1");
				minus = Button((Transform)(object)parent3, "-", -94f, -5f, 52f, 52f, delegate
				{
					timeMenu.Adjust(-0.25);
				});
				plus = Button((Transform)(object)parent3, "+", 94f, -5f, 52f, 52f, delegate
				{
					timeMenu.Adjust(0.25);
				});
				Label((Transform)(object)parent3, "HOURS", 0f, -51f, 210f, 25f, 19f, Muted);
				RectTransform parent4 = Wing((Transform)(object)parent, "Arrival", 300f, 115f);
				Label((Transform)(object)parent4, "ARRIVE AT", 0f, 49f, 210f, 30f, 21f, Amber);
				destination = Label((Transform)(object)parent4, "--:--", 0f, -5f, 220f, 64f, 48f, Blue);
				Label((Transform)(object)parent4, "CURFEW  02:00 - 08:00", 0f, -51f, 232f, 28f, 17f, Muted);
				Image val2 = Box((Transform)(object)parent, "Clock face", 0f, 132f, 240f, 240f, Color.white);
				using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("NivalisSlowDays.Assets.clock-face.png") ?? throw new InvalidOperationException("Embedded clock art is missing."))
				{
					using MemoryStream memoryStream = new MemoryStream();
					stream.CopyTo(memoryStream);
					clockTexture = new Texture2D(2, 2, (TextureFormat)4, false);
					if (!ImageConversion.LoadImage(clockTexture, Il2CppStructArray<byte>.op_Implicit(memoryStream.ToArray()), false))
					{
						throw new InvalidOperationException("Clock art could not be decoded.");
					}
				}
				((Texture)clockTexture).filterMode = (FilterMode)1;
				clockSprite = Sprite.Create(clockTexture, new Rect(0f, 0f, (float)((Texture)clockTexture).width, (float)((Texture)clockTexture).height), new Vector2(0.5f, 0.5f), 100f);
				val2.sprite = clockSprite;
				val2.preserveAspect = true;
				((Graphic)val2).raycastTarget = false;
				hourHand = Hand(((Component)val2).transform, "Hour hand", 6f, 58f, Amber);
				minuteHand = Hand(((Component)val2).transform, "Minute hand", 3f, 82f, new Color(0.85f, 0.84f, 0.79f));
				Image obj7 = Box(((Component)val2).transform, "Hub", 0f, 0f, 10f, 10f, Amber);
				((Transform)((Graphic)obj7).rectTransform).lo