Decompiled source of WhatCurfew v1.2.0

WhatCurfew_Il2cpp.dll

Decompiled 2 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppScheduleOne.GameTime;
using Il2CppScheduleOne.Law;
using Il2CppScheduleOne.ObjectScripts;
using Il2CppScheduleOne.Persistence;
using Il2CppScheduleOne.UI;
using Il2CppTMPro;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
using WhatCurfew;
using WhatCurfew.Features;
using WhatCurfew.Patches;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: MelonInfo(typeof(Core), "WhatCurfew", "1.2.0", "HazDS", null)]
[assembly: MelonGame("TVGS", "Schedule I")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("WhatCurfew_Il2cpp")]
[assembly: AssemblyConfiguration("Il2cpp")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+e00c68090d19a1081be3397485311771842c66a7")]
[assembly: AssemblyProduct("WhatCurfew_Il2cpp")]
[assembly: AssemblyTitle("WhatCurfew_Il2cpp")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace WhatCurfew
{
	public class Core : MelonMod
	{
		private static Harmony _harmony;

		public override void OnInitializeMelon()
		{
			Config.Initialize();
			DiscoController.Initialize();
			MelonLogger.Msg("WhatCurfew v1.2.0 loaded!");
			ApplyPatches();
		}

		private void ApplyPatches()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			try
			{
				_harmony = new Harmony("com.whatcurfew.patches");
				Type typeFromHandle = typeof(CurfewManager);
				PatchMethod(typeFromHandle, "MinPass", "MinPass_Prefix");
				PatchMethod(typeFromHandle, "OnUncappedMinPass", "MinPass_Prefix");
				PatchEnableRPC(typeFromHandle);
				PatchVMSBoard();
				PatchHUD();
			}
			catch (Exception ex)
			{
				MelonLogger.Error("Failed to apply patches: " + ex.Message);
			}
		}

		private void PatchMethod(Type targetType, string methodName, string prefixMethodName)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			MethodInfo method = targetType.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (!(method == null))
			{
				MethodInfo method2 = typeof(CurfewPatches).GetMethod(prefixMethodName, BindingFlags.Static | BindingFlags.Public);
				if (!(method2 == null))
				{
					_harmony.Patch((MethodBase)method, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
		}

		private void PatchEnableRPC(Type curfewManagerType)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Expected O, but got Unknown
			MethodInfo method = curfewManagerType.GetMethod("RpcLogic___Enable_328543758", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (!(method == null))
			{
				MethodInfo method2 = typeof(CurfewPatches).GetMethod("Enable_Prefix", BindingFlags.Static | BindingFlags.Public);
				if (!(method2 == null))
				{
					_harmony.Patch((MethodBase)method, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
		}

		private void PatchVMSBoard()
		{
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Expected O, but got Unknown
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Expected O, but got Unknown
			Type typeFromHandle = typeof(VMSBoard);
			MethodInfo method = typeFromHandle.GetMethod("SetText", new Type[2]
			{
				typeof(string),
				typeof(Color)
			});
			if (method != null)
			{
				MethodInfo method2 = typeof(CurfewPatches).GetMethod("VMSBoard_SetText_Prefix", BindingFlags.Static | BindingFlags.Public);
				if (method2 != null)
				{
					_harmony.Patch((MethodBase)method, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
			MethodInfo method3 = typeFromHandle.GetMethod("SetText", new Type[1] { typeof(string) });
			if (method3 != null)
			{
				MethodInfo method4 = typeof(CurfewPatches).GetMethod("VMSBoard_SetText_StringOnly_Prefix", BindingFlags.Static | BindingFlags.Public);
				if (method4 != null)
				{
					_harmony.Patch((MethodBase)method3, new HarmonyMethod(method4), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
		}

		private void PatchHUD()
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			Type typeFromHandle = typeof(HUD);
			MethodInfo method = typeFromHandle.GetMethod("Update", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (!(method == null))
			{
				MethodInfo method2 = typeof(HUDPatches).GetMethod("Update_Postfix", BindingFlags.Static | BindingFlags.Public);
				if (!(method2 == null))
				{
					_harmony.Patch((MethodBase)method, (HarmonyMethod)null, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
		}

		public override void OnSceneWasLoaded(int buildIndex, string sceneName)
		{
			if (sceneName == "Menu")
			{
				DiscoController.Reset();
			}
		}
	}
	public static class Config
	{
		private static MelonPreferences_Category _category;

		private static MelonPreferences_Entry<bool> _enabled;

		private static MelonPreferences_Entry<bool> _curfewCustomTime;

		private static MelonPreferences_Entry<string> _curfewStartTime;

		private static MelonPreferences_Entry<string> _curfewEndTime;

		private static MelonPreferences_Entry<string> _vmsBoardMessage;

		private static MelonPreferences_Entry<string> _vmsBoardColor;

		private static MelonPreferences_Entry<bool> _discoMode;

		private static MelonPreferences_Entry<float> _discoSpeed;

		public static readonly Dictionary<string, Color32> ColorOptions = new Dictionary<string, Color32>
		{
			{
				"Green",
				new Color32((byte)100, byte.MaxValue, (byte)100, byte.MaxValue)
			},
			{
				"Yellow",
				new Color32(byte.MaxValue, (byte)215, (byte)50, byte.MaxValue)
			},
			{
				"Red",
				new Color32(byte.MaxValue, (byte)85, (byte)60, byte.MaxValue)
			},
			{
				"Blue",
				new Color32((byte)100, (byte)150, byte.MaxValue, byte.MaxValue)
			},
			{
				"Cyan",
				new Color32((byte)100, byte.MaxValue, byte.MaxValue, byte.MaxValue)
			},
			{
				"Purple",
				new Color32((byte)200, (byte)100, byte.MaxValue, byte.MaxValue)
			},
			{
				"Orange",
				new Color32(byte.MaxValue, (byte)165, (byte)50, byte.MaxValue)
			},
			{
				"White",
				new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue)
			}
		};

		public static bool Enabled => _enabled?.Value ?? true;

		public static bool CurfewCustomTime => _curfewCustomTime?.Value ?? false;

		public static string CurfewStartTimeStr => _curfewStartTime?.Value ?? "21:00";

		public static string CurfewEndTimeStr => _curfewEndTime?.Value ?? "5:00";

		public static string VMSBoardMessage => _vmsBoardMessage?.Value ?? "NO CURFEW\nENJOY THE NIGHT";

		public static string VMSBoardColorName => _vmsBoardColor?.Value ?? "Green";

		public static bool DiscoMode => _discoMode?.Value ?? false;

		public static float DiscoSpeed => _discoSpeed?.Value ?? 0.5f;

		public static int CurfewStart => ParseTimeString(CurfewStartTimeStr, 2100);

		public static int CurfewEnd => ParseTimeString(CurfewEndTimeStr, 500);

		public static int HourBeforeCurfew => AddMinutes(CurfewStart, -60);

		public static int WarningTime => AddMinutes(CurfewStart, -30);

		public static int HardCurfewStart => AddMinutes(CurfewStart, 15);

		public static string CustomCurfewTonightText => "CURFEW TONIGHT\n" + FormatGameTimeTo12Hr(CurfewStart) + " - " + FormatGameTimeTo12Hr(CurfewEnd);

		public static string CustomCurfewActiveText => "CURFEW ACTIVE\nUNTIL " + FormatGameTimeTo12Hr(CurfewEnd);

		public static Color32 VMSBoardColor
		{
			get
			{
				//IL_0024: Unknown result type (might be due to invalid IL or missing references)
				//IL_0029: Unknown result type (might be due to invalid IL or missing references)
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				//IL_0017: 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)
				if (ColorOptions.TryGetValue(VMSBoardColorName, out var value))
				{
					return value;
				}
				return ColorOptions["Green"];
			}
		}

		public static event Action<bool> OnDiscoModeChanged;

		public static int ParseTimeString(string time, int fallback)
		{
			if (string.IsNullOrEmpty(time))
			{
				return fallback;
			}
			string[] array = time.Split(':');
			if (array.Length != 2)
			{
				return fallback;
			}
			if (!int.TryParse(array[0], out var result) || !int.TryParse(array[1], out var result2))
			{
				return fallback;
			}
			if (result < 0 || result > 23 || result2 < 0 || result2 > 59)
			{
				return fallback;
			}
			return result * 100 + result2;
		}

		public static int AddMinutes(int gameTime, int minutes)
		{
			int num = gameTime / 100;
			int num2 = gameTime % 100;
			int num3 = num * 60 + num2 + minutes;
			if (num3 < 0)
			{
				num3 += 1440;
			}
			num3 %= 1440;
			return num3 / 60 * 100 + num3 % 60;
		}

		public static string FormatGameTimeTo12Hr(int gameTime)
		{
			int num = gameTime / 100;
			int num2 = gameTime % 100;
			string text = ((num >= 12) ? "PM" : "AM");
			if (num == 0)
			{
				num = 12;
			}
			else if (num > 12)
			{
				num -= 12;
			}
			if (num2 == 0)
			{
				return $"{num}{text}";
			}
			return $"{num}:{num2:00}{text}";
		}

		public static void Initialize()
		{
			_category = MelonPreferences.CreateCategory("WhatCurfew", "WhatCurfew Settings");
			_enabled = _category.CreateEntry<bool>("Enabled", true, "Enable Mod", "Master switch for the mod. When disabled, vanilla curfew behavior is restored.", false, false, (ValueValidator)null, (string)null);
			_curfewCustomTime = _category.CreateEntry<bool>("CurfewCustomTime", false, "Custom Curfew Times", "When enabled, curfew uses configurable start/end times instead of being fully disabled.", false, false, (ValueValidator)null, (string)null);
			_curfewStartTime = _category.CreateEntry<string>("CurfewStartTime", "21:00", "Curfew Start Time", "When curfew begins in 24-hour format (e.g. 21:00 for 9PM, 23:30 for 11:30PM). Only used in Custom mode.", false, false, (ValueValidator)null, (string)null);
			_curfewEndTime = _category.CreateEntry<string>("CurfewEndTime", "5:00", "Curfew End Time", "When curfew ends in 24-hour format (e.g. 5:00 for 5AM, 3:30 for 3:30AM). Only used in Custom mode.", false, false, (ValueValidator)null, (string)null);
			_vmsBoardMessage = _category.CreateEntry<string>("VMSBoardMessage", "NO CURFEW\nENJOY THE NIGHT", "VMS Board Message", "Custom message for VMS boards in Disabled mode. Use \\n for new lines.", false, false, (ValueValidator)null, (string)null);
			_vmsBoardColor = _category.CreateEntry<string>("VMSBoardColor", "Green", "VMS Board Color", "Color of the VMS board text. Options: Green, Yellow, Red, Blue, Cyan, Purple, Orange, White", false, false, (ValueValidator)null, (string)null);
			_discoMode = _category.CreateEntry<bool>("DiscoMode", false, "Disco Mode", "When enabled, VMS board colors cycle through all available colors.", false, false, (ValueValidator)null, (string)null);
			_discoSpeed = _category.CreateEntry<float>("DiscoSpeed", 0.5f, "Disco Speed", "Seconds between color changes in disco mode (0.1 to 2.0).", false, false, (ValueValidator)null, (string)null);
			((MelonEventBase<LemonAction<bool, bool>>)(object)_enabled.OnEntryValueChanged).Subscribe((LemonAction<bool, bool>)delegate(bool oldVal, bool newVal)
			{
				MelonLogger.Msg("Mod " + (newVal ? "enabled" : "disabled"));
				CurfewPatches.OnEnabledChanged(newVal);
				DiscoController.OnModEnabledChanged(newVal);
			}, 0, false);
			((MelonEventBase<LemonAction<bool, bool>>)(object)_curfewCustomTime.OnEntryValueChanged).Subscribe((LemonAction<bool, bool>)delegate(bool oldVal, bool newVal)
			{
				MelonLogger.Msg("Custom curfew times " + (newVal ? "enabled" : "disabled"));
				if (Enabled)
				{
					CurfewPatches.OnCurfewModeChanged(newVal);
				}
			}, 0, false);
			((MelonEventBase<LemonAction<string, string>>)(object)_curfewStartTime.OnEntryValueChanged).Subscribe((LemonAction<string, string>)delegate(string oldVal, string newVal)
			{
				MelonLogger.Msg("Curfew start time changed to: " + newVal);
				if (Enabled && CurfewCustomTime)
				{
					CurfewPatches.RefreshAllBoards();
				}
			}, 0, false);
			((MelonEventBase<LemonAction<string, string>>)(object)_curfewEndTime.OnEntryValueChanged).Subscribe((LemonAction<string, string>)delegate(string oldVal, string newVal)
			{
				MelonLogger.Msg("Curfew end time changed to: " + newVal);
				if (Enabled && CurfewCustomTime)
				{
					CurfewPatches.RefreshAllBoards();
				}
			}, 0, false);
			((MelonEventBase<LemonAction<string, string>>)(object)_vmsBoardMessage.OnEntryValueChanged).Subscribe((LemonAction<string, string>)delegate(string oldVal, string newVal)
			{
				MelonLogger.Msg("VMS message changed to: " + newVal);
				if (Enabled && !CurfewCustomTime)
				{
					CurfewPatches.RefreshAllBoards();
				}
			}, 0, false);
			((MelonEventBase<LemonAction<string, string>>)(object)_vmsBoardColor.OnEntryValueChanged).Subscribe((LemonAction<string, string>)delegate(string oldVal, string newVal)
			{
				MelonLogger.Msg("VMS color changed to: " + newVal);
				if (Enabled && !DiscoMode && !CurfewCustomTime)
				{
					CurfewPatches.RefreshAllBoards();
				}
			}, 0, false);
			((MelonEventBase<LemonAction<bool, bool>>)(object)_discoMode.OnEntryValueChanged).Subscribe((LemonAction<bool, bool>)delegate(bool oldVal, bool newVal)
			{
				Config.OnDiscoModeChanged?.Invoke(newVal);
			}, 0, false);
			((MelonEventBase<LemonAction<float, float>>)(object)_discoSpeed.OnEntryValueChanged).Subscribe((LemonAction<float, float>)delegate(float oldVal, float newVal)
			{
				MelonLogger.Msg($"Disco speed changed to: {newVal}s");
			}, 0, false);
			MelonLogger.Msg($"Configuration loaded. CustomCurfewTime: {CurfewCustomTime}, Enabled: {Enabled}");
		}
	}
}
namespace WhatCurfew.Features
{
	public static class DiscoController
	{
		[CompilerGenerated]
		private sealed class <DiscoLoop>d__9 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			private Color32 <currentColor>5__1;

			private float <delay>5__2;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <DiscoLoop>d__9(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0033: Unknown result type (might be due to invalid IL or missing references)
				//IL_0039: Unknown result type (might be due to invalid IL or missing references)
				//IL_007c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0086: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if (_isRunning)
				{
					<currentColor>5__1 = _colorList[_currentColorIndex];
					CurfewPatches.RefreshAllBoardsWithColor(<currentColor>5__1);
					_currentColorIndex = (_currentColorIndex + 1) % _colorList.Count;
					<delay>5__2 = Mathf.Clamp(Config.DiscoSpeed, 0.1f, 2f);
					<>2__current = (object)new WaitForSeconds(<delay>5__2);
					<>1__state = 1;
					return true;
				}
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private static object _discoCoroutine;

		private static int _currentColorIndex;

		private static List<Color32> _colorList;

		private static bool _isRunning;

		public static void Initialize()
		{
			_colorList = new List<Color32>(Config.ColorOptions.Values);
			_currentColorIndex = 0;
			Config.OnDiscoModeChanged += OnDiscoModeChanged;
			if (Config.DiscoMode && Config.Enabled)
			{
				StartDisco();
			}
		}

		private static void OnDiscoModeChanged(bool enabled)
		{
			if (enabled && Config.Enabled)
			{
				StartDisco();
				return;
			}
			StopDisco();
			if (Config.Enabled)
			{
				CurfewPatches.RefreshAllBoards();
			}
		}

		public static void OnModEnabledChanged(bool enabled)
		{
			if (enabled && Config.DiscoMode)
			{
				StartDisco();
			}
			else
			{
				StopDisco();
			}
		}

		private static void StartDisco()
		{
			if (!_isRunning)
			{
				_isRunning = true;
				_discoCoroutine = MelonCoroutines.Start(DiscoLoop());
				MelonLogger.Msg("Disco mode started!");
			}
		}

		private static void StopDisco()
		{
			if (_isRunning)
			{
				_isRunning = false;
				_discoCoroutine = null;
				MelonLogger.Msg("Disco mode stopped.");
			}
		}

		[IteratorStateMachine(typeof(<DiscoLoop>d__9))]
		private static IEnumerator DiscoLoop()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <DiscoLoop>d__9(0);
		}

		public static void Reset()
		{
			_isRunning = false;
			_discoCoroutine = null;
			_currentColorIndex = 0;
		}
	}
}
namespace WhatCurfew.Patches
{
	public static class CurfewPatches
	{
		private static readonly Dictionary<int, (VMSBoard board, string text, Color color)> _trackedBoards = new Dictionary<int, (VMSBoard, string, Color)>();

		private static readonly string[] CurfewMessages = new string[3] { "CURFEW TONIGHT", "CURFEW ACTIVE", "CURFEW SOON" };

		private static bool _reflectionInitialized;

		private static PropertyInfo _cmInstanceProp;

		private static PropertyInfo _cmIsEnabledProp;

		private static PropertyInfo _cmIsActiveProp;

		private static PropertyInfo _cmIsHardProp;

		private static PropertyInfo _tmInstanceProp;

		private static PropertyInfo _tmCurrentTimeProp;

		private static PropertyInfo _tmElapsedDaysProp;

		private static PropertyInfo _tmIsSleepProp;

		private static PropertyInfo _lmInstanceProp;

		private static PropertyInfo _lmTimeSinceLoadedProp;

		private static void InitReflectionCache()
		{
			if (!_reflectionInitialized)
			{
				_reflectionInitialized = true;
				Type typeFromHandle = typeof(CurfewManager);
				_cmInstanceProp = FindStaticProperty(typeFromHandle, "Instance");
				_cmIsEnabledProp = typeFromHandle.GetProperty("IsEnabled");
				_cmIsActiveProp = typeFromHandle.GetProperty("IsCurrentlyActive");
				_cmIsHardProp = typeFromHandle.GetProperty("IsHardCurfewActive");
				Type typeFromHandle2 = typeof(TimeManager);
				_tmInstanceProp = FindStaticProperty(typeFromHandle2, "Instance");
				_tmCurrentTimeProp = typeFromHandle2.GetProperty("CurrentTime");
				_tmElapsedDaysProp = typeFromHandle2.GetProperty("ElapsedDays");
				_tmIsSleepProp = typeFromHandle2.GetProperty("IsSleepInProgress");
				Type typeFromHandle3 = typeof(LoadManager);
				_lmInstanceProp = FindStaticProperty(typeFromHandle3, "Instance");
				_lmTimeSinceLoadedProp = typeFromHandle3.GetProperty("TimeSinceGameLoaded");
			}
		}

		private static PropertyInfo FindStaticProperty(Type type, string name)
		{
			Type type2 = type;
			while (type2 != null)
			{
				PropertyInfo property = type2.GetProperty(name, BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.Public);
				if (property != null)
				{
					return property;
				}
				type2 = type2.BaseType;
			}
			return null;
		}

		private static CurfewManager GetCurfewManagerInstance()
		{
			InitReflectionCache();
			object? obj = _cmInstanceProp?.GetValue(null);
			return (CurfewManager)((obj is CurfewManager) ? obj : null);
		}

		private static bool IsTimeInRange(int time, int min, int max)
		{
			if (max > min)
			{
				return time >= min && time <= max;
			}
			return time >= min || time <= max;
		}

		private static int GetMinSum(int gameTime)
		{
			return gameTime / 100 * 60 + gameTime % 100;
		}

		private static float GetTimeSinceLoaded()
		{
			try
			{
				object obj = _lmInstanceProp?.GetValue(null);
				if (obj != null && _lmTimeSinceLoadedProp != null)
				{
					return (float)_lmTimeSinceLoadedProp.GetValue(obj);
				}
			}
			catch
			{
			}
			return float.MaxValue;
		}

		private static void SetBoardsText(CurfewManager instance, string text)
		{
			if (instance.VMSBoards == null)
			{
				return;
			}
			foreach (VMSBoard item in (Il2CppArrayBase<VMSBoard>)(object)instance.VMSBoards)
			{
				if ((Object)(object)item != (Object)null && (Object)(object)item.Label != (Object)null)
				{
					((TMP_Text)item.Label).text = text;
				}
			}
		}

		private static void SetBoardsTextAndColor(CurfewManager instance, string text, Color color)
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			if (instance.VMSBoards == null)
			{
				return;
			}
			foreach (VMSBoard item in (Il2CppArrayBase<VMSBoard>)(object)instance.VMSBoards)
			{
				if ((Object)(object)item != (Object)null && (Object)(object)item.Label != (Object)null)
				{
					((TMP_Text)item.Label).text = text;
					((Graphic)item.Label).color = color;
				}
			}
		}

		public static void RefreshAllBoards()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			string text;
			Color32 vMSBoardColor = default(Color32);
			if (Config.CurfewCustomTime)
			{
				text = Config.CustomCurfewTonightText;
				((Color32)(ref vMSBoardColor))..ctor(byte.MaxValue, (byte)215, (byte)50, byte.MaxValue);
			}
			else
			{
				text = Config.VMSBoardMessage;
				vMSBoardColor = Config.VMSBoardColor;
			}
			RefreshAllBoardsWithTextAndColor(text, vMSBoardColor);
		}

		public static void RefreshAllBoardsWithColor(Color32 color)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			string text = (Config.CurfewCustomTime ? Config.CustomCurfewTonightText : Config.VMSBoardMessage);
			RefreshAllBoardsWithTextAndColor(text, color);
		}

		private static void RefreshAllBoardsWithTextAndColor(string text, Color32 color)
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			CleanupDestroyedBoards();
			foreach (KeyValuePair<int, (VMSBoard, string, Color)> trackedBoard in _trackedBoards)
			{
				VMSBoard item = trackedBoard.Value.Item1;
				if ((Object)(object)item != (Object)null && (Object)(object)item.Label != (Object)null)
				{
					((TMP_Text)item.Label).text = text;
					((Graphic)item.Label).color = Color32.op_Implicit(color);
				}
			}
		}

		public static void RestoreAllBoards()
		{
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			CleanupDestroyedBoards();
			List<(VMSBoard, string, Color)> list = new List<(VMSBoard, string, Color)>();
			foreach (KeyValuePair<int, (VMSBoard, string, Color)> trackedBoard in _trackedBoards)
			{
				list.Add(trackedBoard.Value);
			}
			foreach (var (val, text, color) in list)
			{
				if ((Object)(object)val != (Object)null && (Object)(object)val.Label != (Object)null)
				{
					((TMP_Text)val.Label).text = text;
					((Graphic)val.Label).color = color;
				}
			}
		}

		private static void CleanupDestroyedBoards()
		{
			List<int> list = new List<int>();
			foreach (KeyValuePair<int, (VMSBoard, string, Color)> trackedBoard in _trackedBoards)
			{
				if ((Object)(object)trackedBoard.Value.Item1 == (Object)null)
				{
					list.Add(trackedBoard.Key);
				}
			}
			foreach (int item in list)
			{
				_trackedBoards.Remove(item);
			}
		}

		public static void OnEnabledChanged(bool enabled)
		{
			if (enabled)
			{
				RefreshAllBoards();
				return;
			}
			RestoreAllBoards();
			RestoreCurfewState();
		}

		public static void OnCurfewModeChanged(bool customTime)
		{
			InitReflectionCache();
			CurfewManager curfewManagerInstance = GetCurfewManagerInstance();
			if ((Object)(object)curfewManagerInstance == (Object)null)
			{
				return;
			}
			if (customTime)
			{
				_cmIsEnabledProp?.SetValue(curfewManagerInstance, true);
				try
				{
					UnityEvent onCurfewEnabled = curfewManagerInstance.onCurfewEnabled;
					if (onCurfewEnabled != null)
					{
						onCurfewEnabled.Invoke();
					}
				}
				catch
				{
				}
			}
			else
			{
				bool flag = _cmIsActiveProp != null && (bool)_cmIsActiveProp.GetValue(curfewManagerInstance);
				_cmIsEnabledProp?.SetValue(curfewManagerInstance, false);
				_cmIsActiveProp?.SetValue(curfewManagerInstance, false);
				_cmIsHardProp?.SetValue(curfewManagerInstance, false);
				if (flag)
				{
					try
					{
						UnityEvent onCurfewEnd = curfewManagerInstance.onCurfewEnd;
						if (onCurfewEnd != null)
						{
							onCurfewEnd.Invoke();
						}
					}
					catch
					{
					}
				}
			}
			RefreshAllBoards();
		}

		private static void RestoreCurfewState()
		{
			try
			{
				InitReflectionCache();
				CurfewManager curfewManagerInstance = GetCurfewManagerInstance();
				if ((Object)(object)curfewManagerInstance != (Object)null)
				{
					_cmIsEnabledProp?.SetValue(curfewManagerInstance, true);
					_cmIsActiveProp?.SetValue(curfewManagerInstance, false);
					_cmIsHardProp?.SetValue(curfewManagerInstance, false);
				}
			}
			catch
			{
			}
		}

		private static bool IsCurfewMessage(string text)
		{
			if (string.IsNullOrEmpty(text))
			{
				return false;
			}
			string[] curfewMessages = CurfewMessages;
			foreach (string value in curfewMessages)
			{
				if (text.Contains(value))
				{
					return true;
				}
			}
			return false;
		}

		public static bool MinPass_Prefix(CurfewManager __instance)
		{
			if (!Config.Enabled)
			{
				return true;
			}
			if (Config.CurfewCustomTime)
			{
				return HandleCustomCurfew(__instance);
			}
			try
			{
				InitReflectionCache();
				_cmIsEnabledProp?.SetValue(__instance, false);
				_cmIsActiveProp?.SetValue(__instance, false);
				_cmIsHardProp?.SetValue(__instance, false);
			}
			catch
			{
			}
			return false;
		}

		private static bool HandleCustomCurfew(CurfewManager __instance)
		{
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				InitReflectionCache();
				_cmIsEnabledProp?.SetValue(__instance, true);
				object obj = _tmInstanceProp?.GetValue(null);
				if (obj == null)
				{
					return false;
				}
				int num = (int)_tmCurrentTimeProp.GetValue(obj);
				int curfewStart = Config.CurfewStart;
				int curfewEnd = Config.CurfewEnd;
				int hourBeforeCurfew = Config.HourBeforeCurfew;
				int warningTime = Config.WarningTime;
				int hardCurfewStart = Config.HardCurfewStart;
				bool flag = (bool)(_cmIsActiveProp?.GetValue(__instance) ?? ((object)false));
				bool flag2 = (bool)(_cmIsHardProp?.GetValue(__instance) ?? ((object)false));
				if (IsTimeInRange(num, hourBeforeCurfew, curfewStart))
				{
					int num2 = GetMinSum(curfewStart) - GetMinSum(num);
					if (num2 < 0)
					{
						num2 += 1440;
					}
					SetBoardsText(__instance, $"CURFEW SOON\n{num2} MINS");
				}
				if (num == warningTime)
				{
					UnityEvent onCurfewWarning = __instance.onCurfewWarning;
					if (onCurfewWarning != null)
					{
						onCurfewWarning.Invoke();
					}
					if ((int)(_tmElapsedDaysProp?.GetValue(obj) ?? ((object)1)) == 0)
					{
						UnityEvent onCurfewHint = __instance.onCurfewHint;
						if (onCurfewHint != null)
						{
							onCurfewHint.Invoke();
						}
					}
					__instance.CurfewWarningSound.Play();
				}
				if (!flag && IsTimeInRange(num, curfewStart, curfewEnd))
				{
					_cmIsActiveProp?.SetValue(__instance, true);
					UnityEvent onCurfewStart = __instance.onCurfewStart;
					if (onCurfewStart != null)
					{
						onCurfewStart.Invoke();
					}
					bool flag3 = (bool)(_tmIsSleepProp?.GetValue(obj) ?? ((object)false));
					float timeSinceLoaded = GetTimeSinceLoaded();
					if (!flag3 && timeSinceLoaded > 3f && !__instance.CurfewAlarmSound.isPlaying)
					{
						__instance.CurfewAlarmSound.Play();
					}
					SetBoardsTextAndColor(__instance, Config.CustomCurfewActiveText, Color32.op_Implicit(new Color32(byte.MaxValue, (byte)85, (byte)60, byte.MaxValue)));
				}
				if (!flag2 && IsTimeInRange(num, hardCurfewStart, curfewEnd))
				{
					_cmIsHardProp?.SetValue(__instance, true);
					UnityEvent onCurfewHardStart = __instance.onCurfewHardStart;
					if (onCurfewHardStart != null)
					{
						onCurfewHardStart.Invoke();
					}
				}
				if (flag && IsTimeInRange(num, curfewEnd, curfewStart))
				{
					_cmIsActiveProp?.SetValue(__instance, false);
					_cmIsHardProp?.SetValue(__instance, false);
					UnityEvent onCurfewEnd = __instance.onCurfewEnd;
					if (onCurfewEnd != null)
					{
						onCurfewEnd.Invoke();
					}
					SetBoardsText(__instance, Config.CustomCurfewTonightText);
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Error("Custom curfew error: " + ex.Message);
			}
			return false;
		}

		public static bool Enable_Prefix(CurfewManager __instance)
		{
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			if (!Config.Enabled)
			{
				return true;
			}
			try
			{
				string text;
				Color32 vMSBoardColor = default(Color32);
				if (Config.CurfewCustomTime)
				{
					text = Config.CustomCurfewTonightText;
					((Color32)(ref vMSBoardColor))..ctor(byte.MaxValue, (byte)215, (byte)50, byte.MaxValue);
					InitReflectionCache();
					_cmIsEnabledProp?.SetValue(__instance, true);
					UnityEvent onCurfewEnabled = __instance.onCurfewEnabled;
					if (onCurfewEnabled != null)
					{
						onCurfewEnabled.Invoke();
					}
				}
				else
				{
					text = Config.VMSBoardMessage;
					vMSBoardColor = Config.VMSBoardColor;
				}
				if (__instance.VMSBoards != null)
				{
					foreach (VMSBoard item in (Il2CppArrayBase<VMSBoard>)(object)__instance.VMSBoards)
					{
						if ((Object)(object)item != (Object)null)
						{
							((Component)item).gameObject.SetActive(true);
							if ((Object)(object)item.Label != (Object)null)
							{
								((TMP_Text)item.Label).text = text;
								((Graphic)item.Label).color = Color32.op_Implicit(vMSBoardColor);
							}
							int instanceID = ((Object)item).GetInstanceID();
							_trackedBoards[instanceID] = (item, "CURFEW TONIGHT\n9PM - 5AM", Color32.op_Implicit(new Color32(byte.MaxValue, (byte)215, (byte)50, byte.MaxValue)));
						}
					}
				}
			}
			catch
			{
			}
			return false;
		}

		public static bool IsCurrentlyActive_Prefix(ref bool __result)
		{
			if (!Config.Enabled)
			{
				return true;
			}
			__result = false;
			return false;
		}

		public static bool IsHardCurfewActive_Prefix(ref bool __result)
		{
			if (!Config.Enabled)
			{
				return true;
			}
			__result = false;
			return false;
		}

		public static bool IsEnabled_Prefix(ref bool __result)
		{
			if (!Config.Enabled)
			{
				return true;
			}
			__result = false;
			return false;
		}

		public static void VMSBoard_SetText_Prefix(VMSBoard __instance, ref string text, ref Color col)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: 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)
			if (!IsCurfewMessage(text))
			{
				return;
			}
			int instanceID = ((Object)__instance).GetInstanceID();
			_trackedBoards[instanceID] = (__instance, text, col);
			if (Config.Enabled)
			{
				if (Config.CurfewCustomTime)
				{
					text = Config.CustomCurfewTonightText;
					return;
				}
				text = Config.VMSBoardMessage;
				col = Color32.op_Implicit(Config.VMSBoardColor);
			}
		}

		public static bool VMSBoard_SetText_StringOnly_Prefix(VMSBoard __instance, ref string text)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: 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_00c0: Unknown result type (might be due to invalid IL or missing references)
			if (IsCurfewMessage(text))
			{
				int instanceID = ((Object)__instance).GetInstanceID();
				Color32 val = default(Color32);
				((Color32)(ref val))..ctor(byte.MaxValue, (byte)215, (byte)50, byte.MaxValue);
				_trackedBoards[instanceID] = (__instance, text, Color32.op_Implicit(val));
				if (!Config.Enabled)
				{
					return true;
				}
				string text2;
				Color32 vMSBoardColor = default(Color32);
				if (Config.CurfewCustomTime)
				{
					text2 = Config.CustomCurfewTonightText;
					((Color32)(ref vMSBoardColor))..ctor(byte.MaxValue, (byte)215, (byte)50, byte.MaxValue);
				}
				else
				{
					text2 = Config.VMSBoardMessage;
					vMSBoardColor = Config.VMSBoardColor;
				}
				if ((Object)(object)__instance.Label != (Object)null)
				{
					((TMP_Text)__instance.Label).text = text2;
					((Graphic)__instance.Label).color = Color32.op_Implicit(vMSBoardColor);
				}
				return false;
			}
			return true;
		}
	}
	public static class HUDPatches
	{
		private static bool _reflectionInitialized;

		private static PropertyInfo _cmInstanceExistsProp;

		private static PropertyInfo _cmInstanceProp;

		private static PropertyInfo _cmIsActiveProp;

		private static PropertyInfo _cmIsEnabledProp;

		private static PropertyInfo _tmInstanceProp;

		private static PropertyInfo _tmCurrentTimeProp;

		private static void InitReflectionCache()
		{
			if (!_reflectionInitialized)
			{
				_reflectionInitialized = true;
				Type typeFromHandle = typeof(CurfewManager);
				_cmInstanceExistsProp = FindStaticProperty(typeFromHandle, "InstanceExists");
				_cmInstanceProp = FindStaticProperty(typeFromHandle, "Instance");
				_cmIsActiveProp = typeFromHandle.GetProperty("IsCurrentlyActive");
				_cmIsEnabledProp = typeFromHandle.GetProperty("IsEnabled");
				Type typeFromHandle2 = typeof(TimeManager);
				_tmInstanceProp = FindStaticProperty(typeFromHandle2, "Instance");
				_tmCurrentTimeProp = typeFromHandle2.GetProperty("CurrentTime");
			}
		}

		private static PropertyInfo FindStaticProperty(Type type, string name)
		{
			Type type2 = type;
			while (type2 != null)
			{
				PropertyInfo property = type2.GetProperty(name, BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.Public);
				if (property != null)
				{
					return property;
				}
				type2 = type2.BaseType;
			}
			return null;
		}

		public static void Update_Postfix(HUD __instance)
		{
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			if (!Config.Enabled || !Config.CurfewCustomTime || (Object)(object)__instance.CurfewPrompt == (Object)null || !((Component)__instance.CurfewPrompt).gameObject.activeSelf)
			{
				return;
			}
			try
			{
				InitReflectionCache();
				object obj = _cmInstanceProp?.GetValue(null);
				if (obj == null)
				{
					return;
				}
				bool flag = (bool)(_cmIsActiveProp?.GetValue(obj) ?? ((object)false));
				bool flag2 = (bool)(_cmIsEnabledProp?.GetValue(obj) ?? ((object)false));
				if (flag)
				{
					((TMP_Text)__instance.CurfewPrompt).text = "Police curfew in effect until " + Config.FormatGameTimeTo12Hr(Config.CurfewEnd);
				}
				else
				{
					if (!flag2)
					{
						return;
					}
					object obj2 = _tmInstanceProp?.GetValue(null);
					if (obj2 != null)
					{
						int time = (int)_tmCurrentTimeProp.GetValue(obj2);
						if (IsTimeInRange(time, Config.WarningTime, Config.CurfewEnd))
						{
							((TMP_Text)__instance.CurfewPrompt).text = "Police curfew starting soon";
							((Graphic)__instance.CurfewPrompt).color = Color32.op_Implicit(new Color32(byte.MaxValue, (byte)182, (byte)88, (byte)60));
							((Component)__instance.CurfewPrompt).gameObject.SetActive(true);
						}
						else
						{
							((Component)__instance.CurfewPrompt).gameObject.SetActive(false);
						}
					}
				}
			}
			catch
			{
			}
		}

		private static bool IsTimeInRange(int time, int min, int max)
		{
			if (max > min)
			{
				return time >= min && time <= max;
			}
			return time >= min || time <= max;
		}
	}
}
namespace WhatCurfew.Utils
{
	public static class Constants
	{
		public static class Game
		{
			public const string GAME_STUDIO = "TVGS";

			public const string GAME_NAME = "Schedule I";
		}

		public const string MOD_NAME = "WhatCurfew";

		public const string MOD_VERSION = "1.2.0";

		public const string MOD_AUTHOR = "HazDS";

		public const string MOD_DESCRIPTION = "Disable or customize curfew times in Schedule I.";

		public const string PREFERENCES_CATEGORY = "WhatCurfew";
	}
}

WhatCurfew_Mono.dll

Decompiled 2 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using HarmonyLib;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using ScheduleOne.GameTime;
using ScheduleOne.Law;
using ScheduleOne.ObjectScripts;
using ScheduleOne.Persistence;
using ScheduleOne.UI;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
using WhatCurfew;
using WhatCurfew.Features;
using WhatCurfew.Patches;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: MelonInfo(typeof(Core), "WhatCurfew", "1.2.0", "HazDS", null)]
[assembly: MelonGame("TVGS", "Schedule I")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("WhatCurfew_Mono")]
[assembly: AssemblyConfiguration("Mono")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+e00c68090d19a1081be3397485311771842c66a7")]
[assembly: AssemblyProduct("WhatCurfew_Mono")]
[assembly: AssemblyTitle("WhatCurfew_Mono")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace WhatCurfew
{
	public class Core : MelonMod
	{
		private static Harmony _harmony;

		public override void OnInitializeMelon()
		{
			Config.Initialize();
			DiscoController.Initialize();
			MelonLogger.Msg("WhatCurfew v1.2.0 loaded!");
			ApplyPatches();
		}

		private void ApplyPatches()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			try
			{
				_harmony = new Harmony("com.whatcurfew.patches");
				Type typeFromHandle = typeof(CurfewManager);
				PatchMethod(typeFromHandle, "MinPass", "MinPass_Prefix");
				PatchMethod(typeFromHandle, "OnUncappedMinPass", "MinPass_Prefix");
				PatchEnableRPC(typeFromHandle);
				PatchVMSBoard();
				PatchHUD();
			}
			catch (Exception ex)
			{
				MelonLogger.Error("Failed to apply patches: " + ex.Message);
			}
		}

		private void PatchMethod(Type targetType, string methodName, string prefixMethodName)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			MethodInfo method = targetType.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (!(method == null))
			{
				MethodInfo method2 = typeof(CurfewPatches).GetMethod(prefixMethodName, BindingFlags.Static | BindingFlags.Public);
				if (!(method2 == null))
				{
					_harmony.Patch((MethodBase)method, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
		}

		private void PatchEnableRPC(Type curfewManagerType)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Expected O, but got Unknown
			MethodInfo method = curfewManagerType.GetMethod("RpcLogic___Enable_328543758", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (!(method == null))
			{
				MethodInfo method2 = typeof(CurfewPatches).GetMethod("Enable_Prefix", BindingFlags.Static | BindingFlags.Public);
				if (!(method2 == null))
				{
					_harmony.Patch((MethodBase)method, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
		}

		private void PatchVMSBoard()
		{
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Expected O, but got Unknown
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Expected O, but got Unknown
			Type typeFromHandle = typeof(VMSBoard);
			MethodInfo method = typeFromHandle.GetMethod("SetText", new Type[2]
			{
				typeof(string),
				typeof(Color)
			});
			if (method != null)
			{
				MethodInfo method2 = typeof(CurfewPatches).GetMethod("VMSBoard_SetText_Prefix", BindingFlags.Static | BindingFlags.Public);
				if (method2 != null)
				{
					_harmony.Patch((MethodBase)method, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
			MethodInfo method3 = typeFromHandle.GetMethod("SetText", new Type[1] { typeof(string) });
			if (method3 != null)
			{
				MethodInfo method4 = typeof(CurfewPatches).GetMethod("VMSBoard_SetText_StringOnly_Prefix", BindingFlags.Static | BindingFlags.Public);
				if (method4 != null)
				{
					_harmony.Patch((MethodBase)method3, new HarmonyMethod(method4), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
		}

		private void PatchHUD()
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			Type typeFromHandle = typeof(HUD);
			MethodInfo method = typeFromHandle.GetMethod("Update", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (!(method == null))
			{
				MethodInfo method2 = typeof(HUDPatches).GetMethod("Update_Postfix", BindingFlags.Static | BindingFlags.Public);
				if (!(method2 == null))
				{
					_harmony.Patch((MethodBase)method, (HarmonyMethod)null, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
		}

		public override void OnSceneWasLoaded(int buildIndex, string sceneName)
		{
			if (sceneName == "Menu")
			{
				DiscoController.Reset();
			}
		}
	}
	public static class Config
	{
		private static MelonPreferences_Category _category;

		private static MelonPreferences_Entry<bool> _enabled;

		private static MelonPreferences_Entry<bool> _curfewCustomTime;

		private static MelonPreferences_Entry<string> _curfewStartTime;

		private static MelonPreferences_Entry<string> _curfewEndTime;

		private static MelonPreferences_Entry<string> _vmsBoardMessage;

		private static MelonPreferences_Entry<string> _vmsBoardColor;

		private static MelonPreferences_Entry<bool> _discoMode;

		private static MelonPreferences_Entry<float> _discoSpeed;

		public static readonly Dictionary<string, Color32> ColorOptions = new Dictionary<string, Color32>
		{
			{
				"Green",
				new Color32((byte)100, byte.MaxValue, (byte)100, byte.MaxValue)
			},
			{
				"Yellow",
				new Color32(byte.MaxValue, (byte)215, (byte)50, byte.MaxValue)
			},
			{
				"Red",
				new Color32(byte.MaxValue, (byte)85, (byte)60, byte.MaxValue)
			},
			{
				"Blue",
				new Color32((byte)100, (byte)150, byte.MaxValue, byte.MaxValue)
			},
			{
				"Cyan",
				new Color32((byte)100, byte.MaxValue, byte.MaxValue, byte.MaxValue)
			},
			{
				"Purple",
				new Color32((byte)200, (byte)100, byte.MaxValue, byte.MaxValue)
			},
			{
				"Orange",
				new Color32(byte.MaxValue, (byte)165, (byte)50, byte.MaxValue)
			},
			{
				"White",
				new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue)
			}
		};

		public static bool Enabled => _enabled?.Value ?? true;

		public static bool CurfewCustomTime => _curfewCustomTime?.Value ?? false;

		public static string CurfewStartTimeStr => _curfewStartTime?.Value ?? "21:00";

		public static string CurfewEndTimeStr => _curfewEndTime?.Value ?? "5:00";

		public static string VMSBoardMessage => _vmsBoardMessage?.Value ?? "NO CURFEW\nENJOY THE NIGHT";

		public static string VMSBoardColorName => _vmsBoardColor?.Value ?? "Green";

		public static bool DiscoMode => _discoMode?.Value ?? false;

		public static float DiscoSpeed => _discoSpeed?.Value ?? 0.5f;

		public static int CurfewStart => ParseTimeString(CurfewStartTimeStr, 2100);

		public static int CurfewEnd => ParseTimeString(CurfewEndTimeStr, 500);

		public static int HourBeforeCurfew => AddMinutes(CurfewStart, -60);

		public static int WarningTime => AddMinutes(CurfewStart, -30);

		public static int HardCurfewStart => AddMinutes(CurfewStart, 15);

		public static string CustomCurfewTonightText => "CURFEW TONIGHT\n" + FormatGameTimeTo12Hr(CurfewStart) + " - " + FormatGameTimeTo12Hr(CurfewEnd);

		public static string CustomCurfewActiveText => "CURFEW ACTIVE\nUNTIL " + FormatGameTimeTo12Hr(CurfewEnd);

		public static Color32 VMSBoardColor
		{
			get
			{
				//IL_0024: Unknown result type (might be due to invalid IL or missing references)
				//IL_0029: Unknown result type (might be due to invalid IL or missing references)
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				//IL_0017: 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)
				if (ColorOptions.TryGetValue(VMSBoardColorName, out var value))
				{
					return value;
				}
				return ColorOptions["Green"];
			}
		}

		public static event Action<bool> OnDiscoModeChanged;

		public static int ParseTimeString(string time, int fallback)
		{
			if (string.IsNullOrEmpty(time))
			{
				return fallback;
			}
			string[] array = time.Split(':');
			if (array.Length != 2)
			{
				return fallback;
			}
			if (!int.TryParse(array[0], out var result) || !int.TryParse(array[1], out var result2))
			{
				return fallback;
			}
			if (result < 0 || result > 23 || result2 < 0 || result2 > 59)
			{
				return fallback;
			}
			return result * 100 + result2;
		}

		public static int AddMinutes(int gameTime, int minutes)
		{
			int num = gameTime / 100;
			int num2 = gameTime % 100;
			int num3 = num * 60 + num2 + minutes;
			if (num3 < 0)
			{
				num3 += 1440;
			}
			num3 %= 1440;
			return num3 / 60 * 100 + num3 % 60;
		}

		public static string FormatGameTimeTo12Hr(int gameTime)
		{
			int num = gameTime / 100;
			int num2 = gameTime % 100;
			string text = ((num >= 12) ? "PM" : "AM");
			if (num == 0)
			{
				num = 12;
			}
			else if (num > 12)
			{
				num -= 12;
			}
			if (num2 == 0)
			{
				return $"{num}{text}";
			}
			return $"{num}:{num2:00}{text}";
		}

		public static void Initialize()
		{
			_category = MelonPreferences.CreateCategory("WhatCurfew", "WhatCurfew Settings");
			_enabled = _category.CreateEntry<bool>("Enabled", true, "Enable Mod", "Master switch for the mod. When disabled, vanilla curfew behavior is restored.", false, false, (ValueValidator)null, (string)null);
			_curfewCustomTime = _category.CreateEntry<bool>("CurfewCustomTime", false, "Custom Curfew Times", "When enabled, curfew uses configurable start/end times instead of being fully disabled.", false, false, (ValueValidator)null, (string)null);
			_curfewStartTime = _category.CreateEntry<string>("CurfewStartTime", "21:00", "Curfew Start Time", "When curfew begins in 24-hour format (e.g. 21:00 for 9PM, 23:30 for 11:30PM). Only used in Custom mode.", false, false, (ValueValidator)null, (string)null);
			_curfewEndTime = _category.CreateEntry<string>("CurfewEndTime", "5:00", "Curfew End Time", "When curfew ends in 24-hour format (e.g. 5:00 for 5AM, 3:30 for 3:30AM). Only used in Custom mode.", false, false, (ValueValidator)null, (string)null);
			_vmsBoardMessage = _category.CreateEntry<string>("VMSBoardMessage", "NO CURFEW\nENJOY THE NIGHT", "VMS Board Message", "Custom message for VMS boards in Disabled mode. Use \\n for new lines.", false, false, (ValueValidator)null, (string)null);
			_vmsBoardColor = _category.CreateEntry<string>("VMSBoardColor", "Green", "VMS Board Color", "Color of the VMS board text. Options: Green, Yellow, Red, Blue, Cyan, Purple, Orange, White", false, false, (ValueValidator)null, (string)null);
			_discoMode = _category.CreateEntry<bool>("DiscoMode", false, "Disco Mode", "When enabled, VMS board colors cycle through all available colors.", false, false, (ValueValidator)null, (string)null);
			_discoSpeed = _category.CreateEntry<float>("DiscoSpeed", 0.5f, "Disco Speed", "Seconds between color changes in disco mode (0.1 to 2.0).", false, false, (ValueValidator)null, (string)null);
			((MelonEventBase<LemonAction<bool, bool>>)(object)_enabled.OnEntryValueChanged).Subscribe((LemonAction<bool, bool>)delegate(bool oldVal, bool newVal)
			{
				MelonLogger.Msg("Mod " + (newVal ? "enabled" : "disabled"));
				CurfewPatches.OnEnabledChanged(newVal);
				DiscoController.OnModEnabledChanged(newVal);
			}, 0, false);
			((MelonEventBase<LemonAction<bool, bool>>)(object)_curfewCustomTime.OnEntryValueChanged).Subscribe((LemonAction<bool, bool>)delegate(bool oldVal, bool newVal)
			{
				MelonLogger.Msg("Custom curfew times " + (newVal ? "enabled" : "disabled"));
				if (Enabled)
				{
					CurfewPatches.OnCurfewModeChanged(newVal);
				}
			}, 0, false);
			((MelonEventBase<LemonAction<string, string>>)(object)_curfewStartTime.OnEntryValueChanged).Subscribe((LemonAction<string, string>)delegate(string oldVal, string newVal)
			{
				MelonLogger.Msg("Curfew start time changed to: " + newVal);
				if (Enabled && CurfewCustomTime)
				{
					CurfewPatches.RefreshAllBoards();
				}
			}, 0, false);
			((MelonEventBase<LemonAction<string, string>>)(object)_curfewEndTime.OnEntryValueChanged).Subscribe((LemonAction<string, string>)delegate(string oldVal, string newVal)
			{
				MelonLogger.Msg("Curfew end time changed to: " + newVal);
				if (Enabled && CurfewCustomTime)
				{
					CurfewPatches.RefreshAllBoards();
				}
			}, 0, false);
			((MelonEventBase<LemonAction<string, string>>)(object)_vmsBoardMessage.OnEntryValueChanged).Subscribe((LemonAction<string, string>)delegate(string oldVal, string newVal)
			{
				MelonLogger.Msg("VMS message changed to: " + newVal);
				if (Enabled && !CurfewCustomTime)
				{
					CurfewPatches.RefreshAllBoards();
				}
			}, 0, false);
			((MelonEventBase<LemonAction<string, string>>)(object)_vmsBoardColor.OnEntryValueChanged).Subscribe((LemonAction<string, string>)delegate(string oldVal, string newVal)
			{
				MelonLogger.Msg("VMS color changed to: " + newVal);
				if (Enabled && !DiscoMode && !CurfewCustomTime)
				{
					CurfewPatches.RefreshAllBoards();
				}
			}, 0, false);
			((MelonEventBase<LemonAction<bool, bool>>)(object)_discoMode.OnEntryValueChanged).Subscribe((LemonAction<bool, bool>)delegate(bool oldVal, bool newVal)
			{
				Config.OnDiscoModeChanged?.Invoke(newVal);
			}, 0, false);
			((MelonEventBase<LemonAction<float, float>>)(object)_discoSpeed.OnEntryValueChanged).Subscribe((LemonAction<float, float>)delegate(float oldVal, float newVal)
			{
				MelonLogger.Msg($"Disco speed changed to: {newVal}s");
			}, 0, false);
			MelonLogger.Msg($"Configuration loaded. CustomCurfewTime: {CurfewCustomTime}, Enabled: {Enabled}");
		}
	}
}
namespace WhatCurfew.Features
{
	public static class DiscoController
	{
		[CompilerGenerated]
		private sealed class <DiscoLoop>d__9 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			private Color32 <currentColor>5__1;

			private float <delay>5__2;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <DiscoLoop>d__9(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0033: Unknown result type (might be due to invalid IL or missing references)
				//IL_0039: Unknown result type (might be due to invalid IL or missing references)
				//IL_007c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0086: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if (_isRunning)
				{
					<currentColor>5__1 = _colorList[_currentColorIndex];
					CurfewPatches.RefreshAllBoardsWithColor(<currentColor>5__1);
					_currentColorIndex = (_currentColorIndex + 1) % _colorList.Count;
					<delay>5__2 = Mathf.Clamp(Config.DiscoSpeed, 0.1f, 2f);
					<>2__current = (object)new WaitForSeconds(<delay>5__2);
					<>1__state = 1;
					return true;
				}
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private static object _discoCoroutine;

		private static int _currentColorIndex;

		private static List<Color32> _colorList;

		private static bool _isRunning;

		public static void Initialize()
		{
			_colorList = new List<Color32>(Config.ColorOptions.Values);
			_currentColorIndex = 0;
			Config.OnDiscoModeChanged += OnDiscoModeChanged;
			if (Config.DiscoMode && Config.Enabled)
			{
				StartDisco();
			}
		}

		private static void OnDiscoModeChanged(bool enabled)
		{
			if (enabled && Config.Enabled)
			{
				StartDisco();
				return;
			}
			StopDisco();
			if (Config.Enabled)
			{
				CurfewPatches.RefreshAllBoards();
			}
		}

		public static void OnModEnabledChanged(bool enabled)
		{
			if (enabled && Config.DiscoMode)
			{
				StartDisco();
			}
			else
			{
				StopDisco();
			}
		}

		private static void StartDisco()
		{
			if (!_isRunning)
			{
				_isRunning = true;
				_discoCoroutine = MelonCoroutines.Start(DiscoLoop());
				MelonLogger.Msg("Disco mode started!");
			}
		}

		private static void StopDisco()
		{
			if (_isRunning)
			{
				_isRunning = false;
				_discoCoroutine = null;
				MelonLogger.Msg("Disco mode stopped.");
			}
		}

		[IteratorStateMachine(typeof(<DiscoLoop>d__9))]
		private static IEnumerator DiscoLoop()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <DiscoLoop>d__9(0);
		}

		public static void Reset()
		{
			_isRunning = false;
			_discoCoroutine = null;
			_currentColorIndex = 0;
		}
	}
}
namespace WhatCurfew.Patches
{
	public static class CurfewPatches
	{
		private static readonly Dictionary<int, (VMSBoard board, string text, Color color)> _trackedBoards = new Dictionary<int, (VMSBoard, string, Color)>();

		private static readonly string[] CurfewMessages = new string[3] { "CURFEW TONIGHT", "CURFEW ACTIVE", "CURFEW SOON" };

		private static bool _reflectionInitialized;

		private static PropertyInfo _cmInstanceProp;

		private static PropertyInfo _cmIsEnabledProp;

		private static PropertyInfo _cmIsActiveProp;

		private static PropertyInfo _cmIsHardProp;

		private static PropertyInfo _tmInstanceProp;

		private static PropertyInfo _tmCurrentTimeProp;

		private static PropertyInfo _tmElapsedDaysProp;

		private static PropertyInfo _tmIsSleepProp;

		private static PropertyInfo _lmInstanceProp;

		private static PropertyInfo _lmTimeSinceLoadedProp;

		private static void InitReflectionCache()
		{
			if (!_reflectionInitialized)
			{
				_reflectionInitialized = true;
				Type typeFromHandle = typeof(CurfewManager);
				_cmInstanceProp = FindStaticProperty(typeFromHandle, "Instance");
				_cmIsEnabledProp = typeFromHandle.GetProperty("IsEnabled");
				_cmIsActiveProp = typeFromHandle.GetProperty("IsCurrentlyActive");
				_cmIsHardProp = typeFromHandle.GetProperty("IsHardCurfewActive");
				Type typeFromHandle2 = typeof(TimeManager);
				_tmInstanceProp = FindStaticProperty(typeFromHandle2, "Instance");
				_tmCurrentTimeProp = typeFromHandle2.GetProperty("CurrentTime");
				_tmElapsedDaysProp = typeFromHandle2.GetProperty("ElapsedDays");
				_tmIsSleepProp = typeFromHandle2.GetProperty("IsSleepInProgress");
				Type typeFromHandle3 = typeof(LoadManager);
				_lmInstanceProp = FindStaticProperty(typeFromHandle3, "Instance");
				_lmTimeSinceLoadedProp = typeFromHandle3.GetProperty("TimeSinceGameLoaded");
			}
		}

		private static PropertyInfo FindStaticProperty(Type type, string name)
		{
			Type type2 = type;
			while (type2 != null)
			{
				PropertyInfo property = type2.GetProperty(name, BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.Public);
				if (property != null)
				{
					return property;
				}
				type2 = type2.BaseType;
			}
			return null;
		}

		private static CurfewManager GetCurfewManagerInstance()
		{
			InitReflectionCache();
			object? obj = _cmInstanceProp?.GetValue(null);
			return (CurfewManager)((obj is CurfewManager) ? obj : null);
		}

		private static bool IsTimeInRange(int time, int min, int max)
		{
			if (max > min)
			{
				return time >= min && time <= max;
			}
			return time >= min || time <= max;
		}

		private static int GetMinSum(int gameTime)
		{
			return gameTime / 100 * 60 + gameTime % 100;
		}

		private static float GetTimeSinceLoaded()
		{
			try
			{
				object obj = _lmInstanceProp?.GetValue(null);
				if (obj != null && _lmTimeSinceLoadedProp != null)
				{
					return (float)_lmTimeSinceLoadedProp.GetValue(obj);
				}
			}
			catch
			{
			}
			return float.MaxValue;
		}

		private static void SetBoardsText(CurfewManager instance, string text)
		{
			if (instance.VMSBoards == null)
			{
				return;
			}
			VMSBoard[] vMSBoards = instance.VMSBoards;
			foreach (VMSBoard val in vMSBoards)
			{
				if ((Object)(object)val != (Object)null && (Object)(object)val.Label != (Object)null)
				{
					((TMP_Text)val.Label).text = text;
				}
			}
		}

		private static void SetBoardsTextAndColor(CurfewManager instance, string text, Color color)
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			if (instance.VMSBoards == null)
			{
				return;
			}
			VMSBoard[] vMSBoards = instance.VMSBoards;
			foreach (VMSBoard val in vMSBoards)
			{
				if ((Object)(object)val != (Object)null && (Object)(object)val.Label != (Object)null)
				{
					((TMP_Text)val.Label).text = text;
					((Graphic)val.Label).color = color;
				}
			}
		}

		public static void RefreshAllBoards()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			string text;
			Color32 vMSBoardColor = default(Color32);
			if (Config.CurfewCustomTime)
			{
				text = Config.CustomCurfewTonightText;
				((Color32)(ref vMSBoardColor))..ctor(byte.MaxValue, (byte)215, (byte)50, byte.MaxValue);
			}
			else
			{
				text = Config.VMSBoardMessage;
				vMSBoardColor = Config.VMSBoardColor;
			}
			RefreshAllBoardsWithTextAndColor(text, vMSBoardColor);
		}

		public static void RefreshAllBoardsWithColor(Color32 color)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			string text = (Config.CurfewCustomTime ? Config.CustomCurfewTonightText : Config.VMSBoardMessage);
			RefreshAllBoardsWithTextAndColor(text, color);
		}

		private static void RefreshAllBoardsWithTextAndColor(string text, Color32 color)
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			CleanupDestroyedBoards();
			foreach (KeyValuePair<int, (VMSBoard, string, Color)> trackedBoard in _trackedBoards)
			{
				VMSBoard item = trackedBoard.Value.Item1;
				if ((Object)(object)item != (Object)null && (Object)(object)item.Label != (Object)null)
				{
					((TMP_Text)item.Label).text = text;
					((Graphic)item.Label).color = Color32.op_Implicit(color);
				}
			}
		}

		public static void RestoreAllBoards()
		{
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			CleanupDestroyedBoards();
			List<(VMSBoard, string, Color)> list = new List<(VMSBoard, string, Color)>();
			foreach (KeyValuePair<int, (VMSBoard, string, Color)> trackedBoard in _trackedBoards)
			{
				list.Add(trackedBoard.Value);
			}
			foreach (var (val, text, color) in list)
			{
				if ((Object)(object)val != (Object)null && (Object)(object)val.Label != (Object)null)
				{
					((TMP_Text)val.Label).text = text;
					((Graphic)val.Label).color = color;
				}
			}
		}

		private static void CleanupDestroyedBoards()
		{
			List<int> list = new List<int>();
			foreach (KeyValuePair<int, (VMSBoard, string, Color)> trackedBoard in _trackedBoards)
			{
				if ((Object)(object)trackedBoard.Value.Item1 == (Object)null)
				{
					list.Add(trackedBoard.Key);
				}
			}
			foreach (int item in list)
			{
				_trackedBoards.Remove(item);
			}
		}

		public static void OnEnabledChanged(bool enabled)
		{
			if (enabled)
			{
				RefreshAllBoards();
				return;
			}
			RestoreAllBoards();
			RestoreCurfewState();
		}

		public static void OnCurfewModeChanged(bool customTime)
		{
			InitReflectionCache();
			CurfewManager curfewManagerInstance = GetCurfewManagerInstance();
			if ((Object)(object)curfewManagerInstance == (Object)null)
			{
				return;
			}
			if (customTime)
			{
				_cmIsEnabledProp?.SetValue(curfewManagerInstance, true);
				try
				{
					UnityEvent onCurfewEnabled = curfewManagerInstance.onCurfewEnabled;
					if (onCurfewEnabled != null)
					{
						onCurfewEnabled.Invoke();
					}
				}
				catch
				{
				}
			}
			else
			{
				bool flag = _cmIsActiveProp != null && (bool)_cmIsActiveProp.GetValue(curfewManagerInstance);
				_cmIsEnabledProp?.SetValue(curfewManagerInstance, false);
				_cmIsActiveProp?.SetValue(curfewManagerInstance, false);
				_cmIsHardProp?.SetValue(curfewManagerInstance, false);
				if (flag)
				{
					try
					{
						UnityEvent onCurfewEnd = curfewManagerInstance.onCurfewEnd;
						if (onCurfewEnd != null)
						{
							onCurfewEnd.Invoke();
						}
					}
					catch
					{
					}
				}
			}
			RefreshAllBoards();
		}

		private static void RestoreCurfewState()
		{
			try
			{
				InitReflectionCache();
				CurfewManager curfewManagerInstance = GetCurfewManagerInstance();
				if ((Object)(object)curfewManagerInstance != (Object)null)
				{
					_cmIsEnabledProp?.SetValue(curfewManagerInstance, true);
					_cmIsActiveProp?.SetValue(curfewManagerInstance, false);
					_cmIsHardProp?.SetValue(curfewManagerInstance, false);
				}
			}
			catch
			{
			}
		}

		private static bool IsCurfewMessage(string text)
		{
			if (string.IsNullOrEmpty(text))
			{
				return false;
			}
			string[] curfewMessages = CurfewMessages;
			foreach (string value in curfewMessages)
			{
				if (text.Contains(value))
				{
					return true;
				}
			}
			return false;
		}

		public static bool MinPass_Prefix(CurfewManager __instance)
		{
			if (!Config.Enabled)
			{
				return true;
			}
			if (Config.CurfewCustomTime)
			{
				return HandleCustomCurfew(__instance);
			}
			try
			{
				InitReflectionCache();
				_cmIsEnabledProp?.SetValue(__instance, false);
				_cmIsActiveProp?.SetValue(__instance, false);
				_cmIsHardProp?.SetValue(__instance, false);
			}
			catch
			{
			}
			return false;
		}

		private static bool HandleCustomCurfew(CurfewManager __instance)
		{
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				InitReflectionCache();
				_cmIsEnabledProp?.SetValue(__instance, true);
				object obj = _tmInstanceProp?.GetValue(null);
				if (obj == null)
				{
					return false;
				}
				int num = (int)_tmCurrentTimeProp.GetValue(obj);
				int curfewStart = Config.CurfewStart;
				int curfewEnd = Config.CurfewEnd;
				int hourBeforeCurfew = Config.HourBeforeCurfew;
				int warningTime = Config.WarningTime;
				int hardCurfewStart = Config.HardCurfewStart;
				bool flag = (bool)(_cmIsActiveProp?.GetValue(__instance) ?? ((object)false));
				bool flag2 = (bool)(_cmIsHardProp?.GetValue(__instance) ?? ((object)false));
				if (IsTimeInRange(num, hourBeforeCurfew, curfewStart))
				{
					int num2 = GetMinSum(curfewStart) - GetMinSum(num);
					if (num2 < 0)
					{
						num2 += 1440;
					}
					SetBoardsText(__instance, $"CURFEW SOON\n{num2} MINS");
				}
				if (num == warningTime)
				{
					UnityEvent onCurfewWarning = __instance.onCurfewWarning;
					if (onCurfewWarning != null)
					{
						onCurfewWarning.Invoke();
					}
					if ((int)(_tmElapsedDaysProp?.GetValue(obj) ?? ((object)1)) == 0)
					{
						UnityEvent onCurfewHint = __instance.onCurfewHint;
						if (onCurfewHint != null)
						{
							onCurfewHint.Invoke();
						}
					}
					__instance.CurfewWarningSound.Play();
				}
				if (!flag && IsTimeInRange(num, curfewStart, curfewEnd))
				{
					_cmIsActiveProp?.SetValue(__instance, true);
					UnityEvent onCurfewStart = __instance.onCurfewStart;
					if (onCurfewStart != null)
					{
						onCurfewStart.Invoke();
					}
					bool flag3 = (bool)(_tmIsSleepProp?.GetValue(obj) ?? ((object)false));
					float timeSinceLoaded = GetTimeSinceLoaded();
					if (!flag3 && timeSinceLoaded > 3f && !__instance.CurfewAlarmSound.isPlaying)
					{
						__instance.CurfewAlarmSound.Play();
					}
					SetBoardsTextAndColor(__instance, Config.CustomCurfewActiveText, Color32.op_Implicit(new Color32(byte.MaxValue, (byte)85, (byte)60, byte.MaxValue)));
				}
				if (!flag2 && IsTimeInRange(num, hardCurfewStart, curfewEnd))
				{
					_cmIsHardProp?.SetValue(__instance, true);
					UnityEvent onCurfewHardStart = __instance.onCurfewHardStart;
					if (onCurfewHardStart != null)
					{
						onCurfewHardStart.Invoke();
					}
				}
				if (flag && IsTimeInRange(num, curfewEnd, curfewStart))
				{
					_cmIsActiveProp?.SetValue(__instance, false);
					_cmIsHardProp?.SetValue(__instance, false);
					UnityEvent onCurfewEnd = __instance.onCurfewEnd;
					if (onCurfewEnd != null)
					{
						onCurfewEnd.Invoke();
					}
					SetBoardsText(__instance, Config.CustomCurfewTonightText);
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Error("Custom curfew error: " + ex.Message);
			}
			return false;
		}

		public static bool Enable_Prefix(CurfewManager __instance)
		{
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			if (!Config.Enabled)
			{
				return true;
			}
			try
			{
				string text;
				Color32 vMSBoardColor = default(Color32);
				if (Config.CurfewCustomTime)
				{
					text = Config.CustomCurfewTonightText;
					((Color32)(ref vMSBoardColor))..ctor(byte.MaxValue, (byte)215, (byte)50, byte.MaxValue);
					InitReflectionCache();
					_cmIsEnabledProp?.SetValue(__instance, true);
					UnityEvent onCurfewEnabled = __instance.onCurfewEnabled;
					if (onCurfewEnabled != null)
					{
						onCurfewEnabled.Invoke();
					}
				}
				else
				{
					text = Config.VMSBoardMessage;
					vMSBoardColor = Config.VMSBoardColor;
				}
				if (__instance.VMSBoards != null)
				{
					VMSBoard[] vMSBoards = __instance.VMSBoards;
					foreach (VMSBoard val in vMSBoards)
					{
						if ((Object)(object)val != (Object)null)
						{
							((Component)val).gameObject.SetActive(true);
							if ((Object)(object)val.Label != (Object)null)
							{
								((TMP_Text)val.Label).text = text;
								((Graphic)val.Label).color = Color32.op_Implicit(vMSBoardColor);
							}
							int instanceID = ((Object)val).GetInstanceID();
							_trackedBoards[instanceID] = (val, "CURFEW TONIGHT\n9PM - 5AM", Color32.op_Implicit(new Color32(byte.MaxValue, (byte)215, (byte)50, byte.MaxValue)));
						}
					}
				}
			}
			catch
			{
			}
			return false;
		}

		public static bool IsCurrentlyActive_Prefix(ref bool __result)
		{
			if (!Config.Enabled)
			{
				return true;
			}
			__result = false;
			return false;
		}

		public static bool IsHardCurfewActive_Prefix(ref bool __result)
		{
			if (!Config.Enabled)
			{
				return true;
			}
			__result = false;
			return false;
		}

		public static bool IsEnabled_Prefix(ref bool __result)
		{
			if (!Config.Enabled)
			{
				return true;
			}
			__result = false;
			return false;
		}

		public static void VMSBoard_SetText_Prefix(VMSBoard __instance, ref string text, ref Color col)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: 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)
			if (!IsCurfewMessage(text))
			{
				return;
			}
			int instanceID = ((Object)__instance).GetInstanceID();
			_trackedBoards[instanceID] = (__instance, text, col);
			if (Config.Enabled)
			{
				if (Config.CurfewCustomTime)
				{
					text = Config.CustomCurfewTonightText;
					return;
				}
				text = Config.VMSBoardMessage;
				col = Color32.op_Implicit(Config.VMSBoardColor);
			}
		}

		public static bool VMSBoard_SetText_StringOnly_Prefix(VMSBoard __instance, ref string text)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: 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_00c0: Unknown result type (might be due to invalid IL or missing references)
			if (IsCurfewMessage(text))
			{
				int instanceID = ((Object)__instance).GetInstanceID();
				Color32 val = default(Color32);
				((Color32)(ref val))..ctor(byte.MaxValue, (byte)215, (byte)50, byte.MaxValue);
				_trackedBoards[instanceID] = (__instance, text, Color32.op_Implicit(val));
				if (!Config.Enabled)
				{
					return true;
				}
				string text2;
				Color32 vMSBoardColor = default(Color32);
				if (Config.CurfewCustomTime)
				{
					text2 = Config.CustomCurfewTonightText;
					((Color32)(ref vMSBoardColor))..ctor(byte.MaxValue, (byte)215, (byte)50, byte.MaxValue);
				}
				else
				{
					text2 = Config.VMSBoardMessage;
					vMSBoardColor = Config.VMSBoardColor;
				}
				if ((Object)(object)__instance.Label != (Object)null)
				{
					((TMP_Text)__instance.Label).text = text2;
					((Graphic)__instance.Label).color = Color32.op_Implicit(vMSBoardColor);
				}
				return false;
			}
			return true;
		}
	}
	public static class HUDPatches
	{
		private static bool _reflectionInitialized;

		private static PropertyInfo _cmInstanceExistsProp;

		private static PropertyInfo _cmInstanceProp;

		private static PropertyInfo _cmIsActiveProp;

		private static PropertyInfo _cmIsEnabledProp;

		private static PropertyInfo _tmInstanceProp;

		private static PropertyInfo _tmCurrentTimeProp;

		private static void InitReflectionCache()
		{
			if (!_reflectionInitialized)
			{
				_reflectionInitialized = true;
				Type typeFromHandle = typeof(CurfewManager);
				_cmInstanceExistsProp = FindStaticProperty(typeFromHandle, "InstanceExists");
				_cmInstanceProp = FindStaticProperty(typeFromHandle, "Instance");
				_cmIsActiveProp = typeFromHandle.GetProperty("IsCurrentlyActive");
				_cmIsEnabledProp = typeFromHandle.GetProperty("IsEnabled");
				Type typeFromHandle2 = typeof(TimeManager);
				_tmInstanceProp = FindStaticProperty(typeFromHandle2, "Instance");
				_tmCurrentTimeProp = typeFromHandle2.GetProperty("CurrentTime");
			}
		}

		private static PropertyInfo FindStaticProperty(Type type, string name)
		{
			Type type2 = type;
			while (type2 != null)
			{
				PropertyInfo property = type2.GetProperty(name, BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.Public);
				if (property != null)
				{
					return property;
				}
				type2 = type2.BaseType;
			}
			return null;
		}

		public static void Update_Postfix(HUD __instance)
		{
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			if (!Config.Enabled || !Config.CurfewCustomTime || (Object)(object)__instance.CurfewPrompt == (Object)null || !((Component)__instance.CurfewPrompt).gameObject.activeSelf)
			{
				return;
			}
			try
			{
				InitReflectionCache();
				object obj = _cmInstanceProp?.GetValue(null);
				if (obj == null)
				{
					return;
				}
				bool flag = (bool)(_cmIsActiveProp?.GetValue(obj) ?? ((object)false));
				bool flag2 = (bool)(_cmIsEnabledProp?.GetValue(obj) ?? ((object)false));
				if (flag)
				{
					((TMP_Text)__instance.CurfewPrompt).text = "Police curfew in effect until " + Config.FormatGameTimeTo12Hr(Config.CurfewEnd);
				}
				else
				{
					if (!flag2)
					{
						return;
					}
					object obj2 = _tmInstanceProp?.GetValue(null);
					if (obj2 != null)
					{
						int time = (int)_tmCurrentTimeProp.GetValue(obj2);
						if (IsTimeInRange(time, Config.WarningTime, Config.CurfewEnd))
						{
							((TMP_Text)__instance.CurfewPrompt).text = "Police curfew starting soon";
							((Graphic)__instance.CurfewPrompt).color = Color32.op_Implicit(new Color32(byte.MaxValue, (byte)182, (byte)88, (byte)60));
							((Component)__instance.CurfewPrompt).gameObject.SetActive(true);
						}
						else
						{
							((Component)__instance.CurfewPrompt).gameObject.SetActive(false);
						}
					}
				}
			}
			catch
			{
			}
		}

		private static bool IsTimeInRange(int time, int min, int max)
		{
			if (max > min)
			{
				return time >= min && time <= max;
			}
			return time >= min || time <= max;
		}
	}
}
namespace WhatCurfew.Utils
{
	public static class Constants
	{
		public static class Game
		{
			public const string GAME_STUDIO = "TVGS";

			public const string GAME_NAME = "Schedule I";
		}

		public const string MOD_NAME = "WhatCurfew";

		public const string MOD_VERSION = "1.2.0";

		public const string MOD_AUTHOR = "HazDS";

		public const string MOD_DESCRIPTION = "Disable or customize curfew times in Schedule I.";

		public const string PREFERENCES_CATEGORY = "WhatCurfew";
	}
}