Decompiled source of LumenControl v0.5.0

LumenControl.dll

Decompiled 8 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using JG224.LumenControl.Core;
using JG224.LumenControl.Networking;
using JG224.ModCore.API;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("LumenControl")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.5.0.0")]
[assembly: AssemblyInformationalVersion("0.5.0")]
[assembly: AssemblyProduct("LumenControl")]
[assembly: AssemblyTitle("LumenControl")]
[assembly: AssemblyVersion("0.5.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace JG224.LumenControl
{
	internal sealed class LumenControlConfig
	{
		private readonly ConfigFile _file;

		private readonly List<Tuple<ConfigEntryBase, ConfigScope>> _entries = new List<Tuple<ConfigEntryBase, ConfigScope>>();

		private readonly HashSet<string> _reportedInvalidTimes = new HashSet<string>(StringComparer.Ordinal);

		private byte[] _cachedPolicy;

		internal ConfigEntry<bool> Enabled { get; }

		internal ConfigEntry<string> LightsOnTime { get; }

		internal ConfigEntry<string> LightsOffTime { get; }

		internal ConfigEntry<bool> DebugLogging { get; }

		internal ConfigEntry<bool> RespectManualOff { get; }

		internal ConfigEntry<string> IncludedPrefabs { get; }

		internal ConfigEntry<string> ExcludedPrefabs { get; }

		internal ConfigEntry<string> ExcludedLightIds { get; }

		private LumenControlConfig(ConfigFile file)
		{
			_file = file;
			Enabled = Add<bool>(file.Bind<bool>("Lumen", "Enabled", true, "Master switch for scheduled fuel-free decorative lights."), (ConfigScope)2);
			LightsOnTime = Add<string>(file.Bind<string>("Lumen", "LightsOnTime", "17:30", "Start of the free lights-on window in HH:mm 24-hour time."), (ConfigScope)2);
			LightsOffTime = Add<string>(file.Bind<string>("Lumen", "LightsOffTime", "09:00", "End of the free lights-on window in HH:mm 24-hour time."), (ConfigScope)2);
			RespectManualOff = Add<bool>(file.Bind<bool>("Lumen", "RespectManualOff", false, "Keep manually extinguished lights off during the free-fuel window."), (ConfigScope)2);
			IncludedPrefabs = Add<string>(file.Bind<string>("Lumen", "IncludedPrefabs", "", "Additional exact Fireplace prefab names, comma separated (maximum 2048 characters)."), (ConfigScope)2);
			ExcludedPrefabs = Add<string>(file.Bind<string>("Lumen", "ExcludedPrefabs", "", "Exact prefab names excluded from scheduling, comma separated (maximum 2048 characters)."), (ConfigScope)2);
			ExcludedLightIds = Add<string>(file.Bind<string>("Lumen", "ExcludedLightIds", "", "Individual placed-light ZDO IDs to exclude, comma separated. Aim at a light and use lumen_lightid to identify it. Maximum 2048 characters."), (ConfigScope)2);
			DebugLogging = Add<bool>(file.Bind<bool>("Diagnostics", "DebugLogging", false, "Enable verbose LumenControl diagnostics."), (ConfigScope)5);
		}

		internal byte[] PolicyBytes()
		{
			return _cachedPolicy ?? (_cachedPolicy = CreatePolicy().Serialize());
		}

		internal static LumenControlConfig Load(BaseUnityPlugin plugin, string configDirectory, ManualLogSource log)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			if (!Directory.Exists(configDirectory))
			{
				Directory.CreateDirectory(configDirectory);
			}
			string text = LegacyLumenConfigRules.FindImportSource(Directory.GetFiles(configDirectory, "*.cfg", SearchOption.TopDirectoryOnly));
			LumenControlConfig lumenControlConfig = new LumenControlConfig(PluginConfigFiles.Attach(plugin, new ConfigFile(Path.Combine(configDirectory, "jg224.LumenControl.cfg"), true, plugin.Info.Metadata)));
			if (text != null)
			{
				lumenControlConfig.ImportLegacy(text, log);
			}
			return lumenControlConfig;
		}

		internal LumenPolicy CreatePolicy()
		{
			return new LumenPolicy
			{
				Enabled = Enabled.Value,
				LightsOnMinutes = ParseTimeOrDefault(LightsOnTime, 1050),
				LightsOffMinutes = ParseTimeOrDefault(LightsOffTime, 540),
				RespectManualOff = RespectManualOff.Value,
				IncludedPrefabs = IncludedPrefabs.Value,
				ExcludedPrefabs = ExcludedPrefabs.Value,
				ExcludedLightIds = ExcludedLightIds.Value
			};
		}

		internal IEnumerable<IDisposable> RegisterMetadata(ICoreServices services, ModuleId owner)
		{
			//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)
			foreach (Tuple<ConfigEntryBase, ConfigScope> pair in _entries)
			{
				yield return services.Configuration.Register(new ConfigSettingDescriptor(owner, pair.Item1.Definition.Section, pair.Item1.Definition.Key, pair.Item2, (Func<string>)(() => Convert.ToString(pair.Item1.BoxedValue, CultureInfo.InvariantCulture)), 1));
			}
		}

		private ushort ParseTimeOrDefault(ConfigEntry<string> entry, int fallback)
		{
			if (ClockRules.TryParseTime(entry.Value, out var minutes))
			{
				return minutes;
			}
			string item = ((object)((ConfigEntryBase)entry).Definition)?.ToString() + "=" + entry.Value;
			if (_reportedInvalidTimes.Add(item))
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)(((object)((ConfigEntryBase)entry).Definition)?.ToString() + " must use HH:mm; using " + ClockRules.FormatTime(fallback) + "."));
				}
			}
			return (ushort)fallback;
		}

		private void ImportLegacy(string path, ManualLogSource log)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			try
			{
				ConfigFile val = new ConfigFile(path, false);
				Enabled.Value = val.Bind<bool>("Lumen", "Enabled", Enabled.Value, (ConfigDescription)null).Value;
				LightsOnTime.Value = val.Bind<string>("Lumen", "LightsOnTime", LightsOnTime.Value, (ConfigDescription)null).Value;
				LightsOffTime.Value = val.Bind<string>("Lumen", "LightsOffTime", LightsOffTime.Value, (ConfigDescription)null).Value;
				_file.Save();
				if (log != null)
				{
					log.LogInfo((object)("Imported Lumen settings from " + Path.GetFileName(path) + "."));
				}
			}
			catch (Exception ex)
			{
				if (log != null)
				{
					log.LogWarning((object)("Could not import GeneralTweaks Lumen settings; using defaults. " + ex.Message));
				}
			}
		}

		private ConfigEntry<T> Add<T>(ConfigEntry<T> entry, ConfigScope scope)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			_entries.Add(Tuple.Create<ConfigEntryBase, ConfigScope>((ConfigEntryBase)(object)entry, scope));
			entry.SettingChanged += delegate
			{
				_cachedPolicy = null;
				_reportedInvalidTimes.Clear();
			};
			return entry;
		}
	}
	[BepInPlugin("jg224.LumenControl", "LumenControl", "0.5.0")]
	[BepInDependency("com.jg224.modcore", "0.5.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "jg224.LumenControl";

		public const string PluginName = "LumenControl";

		public const string PluginVersion = "0.5.0";

		public const string ModCoreGuid = "com.jg224.modcore";

		public const string GeneralTweaksGuid = "JG224.GeneralTweaks";

		public const int ProtocolVersion = 2;

		public static readonly ModuleId ModuleId = new ModuleId("lumencontrol");

		private readonly List<IDisposable> _registrations = new List<IDisposable>();

		private Harmony _harmony;

		private PolicyNetwork _network;

		private bool _active;

		private bool _shutDown;

		internal static ManualLogSource Log { get; private set; }

		internal static LumenControlConfig Settings { get; private set; }

		internal static LumenPolicy Policy { get; private set; } = new LumenPolicy();

		internal static ICoreServices Core { get; private set; }

		internal static bool HasPolicy { get; private set; }

		private void Awake()
		{
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Expected O, but got Unknown
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: 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)
			Log = ((BaseUnityPlugin)this).Logger;
			Settings = LumenControlConfig.Load((BaseUnityPlugin)(object)this, Paths.ConfigPath, ((BaseUnityPlugin)this).Logger);
			try
			{
				if (!ModCoreApi.IsAvailable)
				{
					throw new InvalidOperationException("ModCore did not initialize before LumenControl.");
				}
				Core = ModCoreApi.Services;
				RegisterWithCore();
				if (TryGetLegacyOwner(out var version))
				{
					string text = "GeneralTweaks " + version?.ToString() + " still contains Lumen; LumenControl is paused to prevent duplicate lighting hooks.";
					Core.Modules.SetState(ModuleId, (ModuleRuntimeState)3, text);
					((BaseUnityPlugin)this).Logger.LogWarning((object)(text + " Update GeneralTweaks to 3.0.0 or newer."));
					return;
				}
				_network = new PolicyNetwork(Core, Settings);
				_harmony = new Harmony("jg224.LumenControl");
				_harmony.PatchAll(Assembly.GetExecutingAssembly());
				_active = true;
				Core.Modules.SetState(ModuleId, (ModuleRuntimeState)2, "Server-owned decorative-light schedule ready.");
				Game.isModded = true;
				((BaseUnityPlugin)this).Logger.LogInfo((object)("LumenControl 0.5.0 loaded; policy schema " + 2 + ", protocol " + 2 + "."));
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("LumenControl failed to initialize safely: " + ex));
				if (Core != null)
				{
					Core.Modules.SetState(ModuleId, (ModuleRuntimeState)5, ex.Message);
				}
				Shutdown();
				throw;
			}
		}

		private void Update()
		{
			if (_active)
			{
				_network?.Tick(Time.unscaledTimeAsDouble);
				HasPolicy = _network?.HasPolicy ?? false;
			}
		}

		private void OnDestroy()
		{
			Shutdown();
		}

		internal static void ApplyPolicy(LumenPolicy policy, string source)
		{
			if (policy != null && !Policy.Equals(policy))
			{
				Policy = policy;
				Debug("Applied " + source + " policy.");
			}
		}

		private unsafe void RegisterWithCore()
		{
			//IL_0029: 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_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Expected O, but got Unknown
			//IL_00b5: 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_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Expected O, but got Unknown
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Expected O, but got Unknown
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			SemanticVersion val = default(SemanticVersion);
			if (!SemanticVersion.TryParse("0.5.0", ref val))
			{
				throw new InvalidOperationException("LumenControl has invalid release version metadata.");
			}
			_registrations.Add(Core.Modules.Register(new ModuleDescriptor(ModuleId, "jg224.LumenControl", "LumenControl", val, 2, (ModuleSide)3, (ModuleRequirement)4, 0uL, 1, 1)));
			_registrations.Add(Core.Commands.Register(new CommandDescriptor(ModuleId, "lumen_lightid", "Aim at a placed light to read its ID for the server's ExcludedLightIds setting.", false, (TimeSpan?)null, Array.Empty<string>()), (Func<CommandContext, CommandResult>)delegate
			{
				//IL_0062: Unknown result type (might be due to invalid IL or missing references)
				//IL_0067: Unknown result type (might be due to invalid IL or missing references)
				GameObject val2 = (Object.op_Implicit((Object)(object)Player.m_localPlayer) ? ((Humanoid)Player.m_localPlayer).GetHoverObject() : null);
				ZNetView val3 = (Object.op_Implicit((Object)(object)val2) ? val2.GetComponentInParent<ZNetView>() : null);
				if (!Object.op_Implicit((Object)(object)(Object.op_Implicit((Object)(object)val3) ? ((Component)val3).GetComponent<Fireplace>() : null)) || !val3.IsValid())
				{
					return CommandResult.Failure("Aim at a placed light first.");
				}
				ZDOID uid = val3.GetZDO().m_uid;
				return CommandResult.Success("Light ID: " + ((object)(*(ZDOID*)(&uid))/*cast due to .constrained prefix*/).ToString() + "; prefab: " + ((Object)((Component)val3).gameObject).name);
			}));
			foreach (IDisposable item in Settings.RegisterMetadata(Core, ModuleId))
			{
				_registrations.Add(item);
			}
			_registrations.Add(Core.Namespaces.Register(ModuleId, (NamespaceKind)5, "jg224.lumencontrol.net.", 1, Array.Empty<string>()));
			_registrations.Add(Core.Namespaces.Register(ModuleId, (NamespaceKind)9, "jg224.lumencontrol.", 1, Array.Empty<string>()));
			_registrations.Add(Core.Compatibility.Register(new CompatibilityRule("jg224.LumenControl", "TastyChickenLegs.NoSmokeStayLit", (CompatibilityRuleKind)2, (CompatibilitySeverity)2, "Both mods schedule decorative lights; remove one implementation.", "lumen")));
			_registrations.Add(Core.Compatibility.Register(new CompatibilityRule("jg224.LumenControl", "jg224.lumencore", (CompatibilityRuleKind)2, (CompatibilitySeverity)2, "LumenCore overlaps LumenControl scheduled decorative lights.", "lumen")));
			_registrations.Add(Core.Lifecycle.Subscribe(ModuleId, (LifecycleEventKind)9, (Action<LifecycleEvent>)delegate
			{
				ResetRuntime();
			}, 0));
			_registrations.Add(Core.Lifecycle.Subscribe(ModuleId, (LifecycleEventKind)3, (Action<LifecycleEvent>)delegate
			{
				ResetRuntime();
			}, 0));
		}

		private static bool TryGetLegacyOwner(out Version version)
		{
			version = null;
			if (!Chainloader.PluginInfos.TryGetValue("JG224.GeneralTweaks", out var value))
			{
				return false;
			}
			version = value.Metadata.Version;
			if (version != null)
			{
				return version.CompareTo(new Version(3, 0, 0)) < 0;
			}
			return false;
		}

		private void ResetRuntime()
		{
			HasPolicy = false;
		}

		private void Shutdown()
		{
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			if (_shutDown)
			{
				return;
			}
			_shutDown = true;
			_active = false;
			HasPolicy = false;
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			_harmony = null;
			_network?.Dispose();
			_network = null;
			for (int num = _registrations.Count - 1; num >= 0; num--)
			{
				try
				{
					_registrations[num].Dispose();
				}
				catch (Exception ex)
				{
					ManualLogSource logger = ((BaseUnityPlugin)this).Logger;
					if (logger != null)
					{
						logger.LogWarning((object)("Registration cleanup failed: " + ex.Message));
					}
				}
			}
			_registrations.Clear();
			if (Core != null)
			{
				Core.Metrics.RemoveOwner(ModuleId);
			}
			Core = null;
			Settings = null;
			Log = null;
		}

		internal static void Debug(string message)
		{
			LumenControlConfig settings = Settings;
			if (settings != null && settings.DebugLogging.Value)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogDebug((object)message);
				}
			}
		}
	}
}
namespace JG224.LumenControl.Patches
{
	internal static class LumenRuntime
	{
		internal static bool IsEligible(Fireplace fireplace)
		{
			if (!Object.op_Implicit((Object)(object)fireplace) || !Plugin.HasPolicy)
			{
				return false;
			}
			Piece componentInParent = ((Component)fireplace).GetComponentInParent<Piece>();
			ZNetView component = ((Component)fireplace).GetComponent<ZNetView>();
			if (Object.op_Implicit((Object)(object)componentInParent) && componentInParent.IsPlacedByPlayer() && Object.op_Implicit((Object)(object)component) && component.IsValid())
			{
				return Plugin.Policy.Includes(((Object)((Component)componentInParent).gameObject).name, ((object)Unsafe.As<ZDOID, ZDOID>(ref component.GetZDO().m_uid)/*cast due to .constrained prefix*/).ToString());
			}
			return false;
		}

		internal static bool IsFreeWindow()
		{
			if (Plugin.HasPolicy)
			{
				LumenPolicy policy = Plugin.Policy;
				if (policy != null && policy.Enabled && Object.op_Implicit((Object)(object)EnvMan.instance))
				{
					return LumenSchedule.IsFreeWindow(ClockRules.DayMinutes(EnvMan.instance.GetDayFraction()), Plugin.Policy.LightsOnMinutes, Plugin.Policy.LightsOffMinutes);
				}
			}
			return false;
		}

		internal static bool IsUnderWater(Fireplace fireplace, bool checkWater, ref WaterVolume previousWater)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			if (!checkWater)
			{
				return false;
			}
			return Floating.IsUnderWater(Object.op_Implicit((Object)(object)fireplace.m_enabledObject) ? fireplace.m_enabledObject.transform.position : ((Component)fireplace).transform.position, ref previousWater);
		}

		internal static void EnsureOn(Fireplace fireplace)
		{
			if (Plugin.Policy.RespectManualOff)
			{
				return;
			}
			ZNetView component = ((Component)fireplace).GetComponent<ZNetView>();
			if (Object.op_Implicit((Object)(object)component) && component.IsValid() && component.IsOwner())
			{
				ZDO zDO = component.GetZDO();
				if (zDO != null && zDO.GetInt(ZDOVars.s_state, 1) != 1)
				{
					zDO.Set(ZDOVars.s_state, 1, false);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Fireplace), "UpdateFireplace")]
	internal static class LumenUpdatePatch
	{
		internal sealed class State : InfiniteFuelState
		{
			internal State(bool original)
				: base(original)
			{
			}
		}

		[HarmonyPrefix]
		private static void Prefix(Fireplace __instance, bool ___m_blocked, bool ___m_wet, bool ___m_checkWaterLevel, ref WaterVolume ___m_previousWaterVolume, out State __state)
		{
			__state = new State(__instance.m_infiniteFuel);
			if (!(!LumenRuntime.IsEligible(__instance) || !LumenRuntime.IsFreeWindow() || ___m_blocked || ___m_wet) && !LumenRuntime.IsUnderWater(__instance, ___m_checkWaterLevel, ref ___m_previousWaterVolume))
			{
				LumenRuntime.EnsureOn(__instance);
				__instance.m_infiniteFuel = true;
				__state.MarkApplied();
			}
		}

		[HarmonyPostfix]
		private static void Postfix(Fireplace __instance, State __state)
		{
			Restore(__instance, __state);
		}

		[HarmonyFinalizer]
		private static Exception Finalizer(Exception __exception, Fireplace __instance, State __state)
		{
			Restore(__instance, __state);
			return __exception;
		}

		private static void Restore(Fireplace fireplace, State state)
		{
			if (Object.op_Implicit((Object)(object)fireplace) && state != null && state.TryRestore(fireplace.m_infiniteFuel, out var restored))
			{
				fireplace.m_infiniteFuel = restored;
			}
		}
	}
	[HarmonyPatch(typeof(Fireplace), "IsBurning")]
	internal static class LumenBurningPatch
	{
		[HarmonyPostfix]
		private static void Postfix(Fireplace __instance, ref bool __result, bool ___m_blocked, bool ___m_wet, bool ___m_checkWaterLevel, ref WaterVolume ___m_previousWaterVolume)
		{
			if (!(__result || !LumenRuntime.IsEligible(__instance) || !LumenRuntime.IsFreeWindow() || ___m_blocked || ___m_wet) && !LumenRuntime.IsUnderWater(__instance, ___m_checkWaterLevel, ref ___m_previousWaterVolume))
			{
				ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
				if (Object.op_Implicit((Object)(object)component) && component.IsValid() && component.GetZDO().GetInt(ZDOVars.s_state, 1) == 1)
				{
					__result = true;
				}
			}
		}
	}
	[HarmonyPatch(typeof(Fireplace), "Interact")]
	internal static class LumenManualTogglePatch
	{
		[HarmonyPrefix]
		[HarmonyPriority(0)]
		private static bool Prefix(Fireplace __instance, Humanoid user, bool hold, bool alt, ref bool __result, bool __runOriginal)
		{
			if (!__runOriginal || !Object.op_Implicit((Object)(object)__instance) || hold || alt || !__instance.m_canTurnOff || !LumenRuntime.IsEligible(__instance) || !LumenRuntime.IsFreeWindow())
			{
				return true;
			}
			if (!Plugin.Policy.RespectManualOff)
			{
				LumenRuntime.EnsureOn(__instance);
				__result = true;
				return false;
			}
			ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
			if (!Object.op_Implicit((Object)(object)user) || (Object)(object)user != (Object)(object)Player.m_localPlayer || !Object.op_Implicit((Object)(object)component) || !component.IsValid() || !ManualToggleRules.ShouldToggleWithoutFuel(Plugin.Policy.RespectManualOff, eligible: true, freeWindow: true, __instance.m_canTurnOff, hold, alt, component.GetZDO().GetFloat(ZDOVars.s_fuel, 0f)))
			{
				return true;
			}
			if (!component.HasOwner())
			{
				component.ClaimOwnership();
			}
			component.InvokeRPC("RPC_ToggleOn", Array.Empty<object>());
			__result = true;
			return false;
		}
	}
}
namespace JG224.LumenControl.Networking
{
	internal sealed class LumenPolicy : IEquatable<LumenPolicy>
	{
		internal const int SchemaVersion = 2;

		internal const int MaximumBytes = 25000;

		internal bool Enabled = true;

		internal ushort LightsOnMinutes = 1050;

		internal ushort LightsOffMinutes = 540;

		internal bool RespectManualOff;

		internal string IncludedPrefabs = string.Empty;

		internal string ExcludedPrefabs = string.Empty;

		internal string ExcludedLightIds = string.Empty;

		private HashSet<string> _included;

		private HashSet<string> _excluded;

		private HashSet<string> _lights;

		internal bool Includes(string prefab, string lightId)
		{
			if (_included == null)
			{
				_included = Entries(IncludedPrefabs);
				_excluded = Entries(ExcludedPrefabs);
				_lights = Entries(ExcludedLightIds);
			}
			string text = prefab.Replace("(Clone)", string.Empty).Trim();
			if (!_excluded.Contains(text) && !_lights.Contains(lightId))
			{
				if (!PrefabRules.IsDecorativeLight(text))
				{
					return _included.Contains(text);
				}
				return true;
			}
			return false;
		}

		private static HashSet<string> Entries(string text)
		{
			return new HashSet<string>(Array.ConvertAll(text.Split(new char[1] { ',' }), (string value) => value.Trim()), StringComparer.OrdinalIgnoreCase);
		}

		internal byte[] Serialize()
		{
			using MemoryStream memoryStream = new MemoryStream();
			using BinaryWriter binaryWriter = new BinaryWriter(memoryStream);
			binaryWriter.Write((byte)2);
			binaryWriter.Write(Enabled);
			binaryWriter.Write(LightsOnMinutes);
			binaryWriter.Write(LightsOffMinutes);
			binaryWriter.Write(RespectManualOff);
			binaryWriter.Write(IncludedPrefabs);
			binaryWriter.Write(ExcludedPrefabs);
			binaryWriter.Write(ExcludedLightIds);
			binaryWriter.Flush();
			return memoryStream.ToArray();
		}

		internal static bool TryDeserialize(byte[] bytes, out LumenPolicy policy, out string error)
		{
			policy = null;
			error = string.Empty;
			if (bytes == null || bytes.Length == 0 || bytes.Length > 25000)
			{
				error = "Policy payload size is invalid.";
				return false;
			}
			try
			{
				using MemoryStream memoryStream = new MemoryStream(bytes, writable: false);
				using BinaryReader binaryReader = new BinaryReader(memoryStream);
				int num = binaryReader.ReadByte();
				if (num != 2)
				{
					error = "Unsupported LumenControl policy schema " + num + ".";
					return false;
				}
				LumenPolicy lumenPolicy = new LumenPolicy
				{
					Enabled = binaryReader.ReadBoolean(),
					LightsOnMinutes = binaryReader.ReadUInt16(),
					LightsOffMinutes = binaryReader.ReadUInt16()
				};
				lumenPolicy.RespectManualOff = binaryReader.ReadBoolean();
				lumenPolicy.IncludedPrefabs = binaryReader.ReadString();
				lumenPolicy.ExcludedPrefabs = binaryReader.ReadString();
				lumenPolicy.ExcludedLightIds = binaryReader.ReadString();
				if (lumenPolicy.IncludedPrefabs.Length > 2048 || lumenPolicy.ExcludedPrefabs.Length > 2048 || lumenPolicy.ExcludedLightIds.Length > 2048)
				{
					error = "Light selection lists are limited to 2048 characters each.";
					return false;
				}
				if (memoryStream.Position != memoryStream.Length)
				{
					error = "Policy payload contains trailing data.";
					return false;
				}
				if (lumenPolicy.LightsOnMinutes >= 1440 || lumenPolicy.LightsOffMinutes >= 1440)
				{
					error = "Lumen schedule must use valid 24-hour times.";
					return false;
				}
				policy = lumenPolicy;
				return true;
			}
			catch (Exception ex)
			{
				error = "Malformed LumenControl policy: " + ex.Message;
				return false;
			}
		}

		public bool Equals(LumenPolicy other)
		{
			if (other != null && Enabled == other.Enabled && LightsOnMinutes == other.LightsOnMinutes && LightsOffMinutes == other.LightsOffMinutes && RespectManualOff == other.RespectManualOff && IncludedPrefabs == other.IncludedPrefabs && ExcludedPrefabs == other.ExcludedPrefabs)
			{
				return ExcludedLightIds == other.ExcludedLightIds;
			}
			return false;
		}

		public override bool Equals(object obj)
		{
			return Equals(obj as LumenPolicy);
		}

		public override int GetHashCode()
		{
			return ((((Enabled ? 1 : 0) * 397) ^ LightsOnMinutes) * 397) ^ LightsOffMinutes;
		}
	}
	internal sealed class PolicyNetwork : IDisposable
	{
		private readonly AuthoritativePolicyChannel _channel;

		internal bool HasPolicy => _channel.HasPolicy;

		internal PolicyNetwork(ICoreServices core, LumenControlConfig config)
		{
			//IL_0008: 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_0089: Expected O, but got Unknown
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Expected O, but got Unknown
			_channel = new AuthoritativePolicyChannel(core, new PolicyDescriptor(Plugin.ModuleId, 2, 25000, (Func<byte[], string>)((byte[] bytes) => (!LumenPolicy.TryDeserialize(bytes, out var policy, out var _)) ? error : string.Empty)), 2, (ushort)1, (ushort)2, (Func<byte[]>)config.PolicyBytes, (Action<byte[]>)delegate(byte[] bytes)
			{
				LumenPolicy.TryDeserialize(bytes, out policy, out error);
				Plugin.ApplyPolicy(policy, "server");
			}, (Action<string>)delegate(string error)
			{
				Plugin.Log.LogWarning((object)error);
			});
		}

		internal void Tick(double now)
		{
			_channel.Tick(now, Object.op_Implicit((Object)(object)ZNet.instance), Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer());
		}

		internal void ResetConnection()
		{
			_channel.Reset();
		}

		public void Dispose()
		{
			_channel.Dispose();
		}
	}
}
namespace JG224.LumenControl.Core
{
	internal static class ClockRules
	{
		internal static int DayMinutes(float dayFraction)
		{
			return (int)Math.Floor((dayFraction - (float)Math.Floor(dayFraction)) * 1440f) % 1440;
		}

		internal static string FormatTime(int minutes)
		{
			minutes = (minutes % 1440 + 1440) % 1440;
			return (minutes / 60).ToString("00", CultureInfo.InvariantCulture) + ":" + (minutes % 60).ToString("00", CultureInfo.InvariantCulture);
		}

		internal static bool TryParseTime(string value, out ushort minutes)
		{
			minutes = 0;
			if (string.IsNullOrWhiteSpace(value))
			{
				return false;
			}
			string[] array = value.Trim().Split(new char[1] { ':' });
			if (array.Length != 2 || !int.TryParse(array[0], NumberStyles.None, CultureInfo.InvariantCulture, out var result) || !int.TryParse(array[1], NumberStyles.None, CultureInfo.InvariantCulture, out var result2) || result < 0 || result > 23 || result2 < 0 || result2 > 59)
			{
				return false;
			}
			minutes = (ushort)(result * 60 + result2);
			return true;
		}
	}
	internal static class LumenSchedule
	{
		internal static bool IsFreeWindow(int currentMinutes, int onMinutes, int offMinutes)
		{
			currentMinutes = (currentMinutes % 1440 + 1440) % 1440;
			if (onMinutes == offMinutes)
			{
				return true;
			}
			if (onMinutes < offMinutes)
			{
				if (currentMinutes >= onMinutes)
				{
					return currentMinutes < offMinutes;
				}
				return false;
			}
			if (currentMinutes < onMinutes)
			{
				return currentMinutes < offMinutes;
			}
			return true;
		}
	}
	internal static class ManualToggleRules
	{
		internal static bool ShouldToggleWithoutFuel(bool respectManualOff, bool eligible, bool freeWindow, bool canTurnOff, bool hold, bool alt, float fuel)
		{
			if (respectManualOff && eligible && freeWindow && canTurnOff && !hold && !alt)
			{
				return fuel == 0f;
			}
			return false;
		}
	}
	internal class InfiniteFuelState
	{
		private readonly bool _original;

		private bool _changed;

		private bool _restored;

		internal InfiniteFuelState(bool original)
		{
			_original = original;
		}

		internal void MarkApplied()
		{
			_changed = !_original;
		}

		internal bool TryRestore(bool current, out bool restored)
		{
			restored = current;
			if (_restored || !_changed)
			{
				return false;
			}
			_restored = true;
			if (!current)
			{
				return false;
			}
			restored = _original;
			return true;
		}
	}
	internal static class PrefabRules
	{
		internal static bool IsDecorativeLight(string prefabName)
		{
			string text = Clean(prefabName).Replace("_", string.Empty).ToLowerInvariant();
			if (text.StartsWith("piece", StringComparison.Ordinal))
			{
				if (!text.Contains("groundtorch") && !text.Contains("walltorch") && !text.Contains("brazier"))
				{
					return text.Contains("jackoturnip");
				}
				return true;
			}
			return false;
		}

		private static string Clean(string value)
		{
			if (string.IsNullOrEmpty(value))
			{
				return string.Empty;
			}
			int num = value.IndexOf("(Clone)", StringComparison.OrdinalIgnoreCase);
			return ((num >= 0) ? value.Substring(0, num) : value).Trim();
		}
	}
	internal static class LegacyLumenConfigRules
	{
		internal const string CurrentFileName = "jg224.LumenControl.cfg";

		internal const string GeneralTweaksFileName = "jg224.GeneralTweaks.cfg";

		internal const string LegacyGeneralTweaksFileName = "JG224.GeneralTweaks.cfg";

		internal static string FindImportSource(IEnumerable<string> candidatePaths)
		{
			string[] paths = ((candidatePaths == null) ? Array.Empty<string>() : candidatePaths.ToArray());
			if (FindExact(paths, "jg224.LumenControl.cfg") != null)
			{
				return null;
			}
			return FindExact(paths, "jg224.GeneralTweaks.cfg") ?? FindExact(paths, "JG224.GeneralTweaks.cfg");
		}

		private static string FindExact(IEnumerable<string> paths, string fileName)
		{
			return paths.FirstOrDefault((string path) => string.Equals(Path.GetFileName(path), fileName, StringComparison.Ordinal));
		}
	}
}