Decompiled source of Flash light Enhanced v1.0.0

Mods/FlashLightEnhanced.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text.Json;
using System.Text.RegularExpressions;
using FlashLightEnhanced;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppScheduleOne;
using Il2CppScheduleOne.DevUtilities;
using Il2CppScheduleOne.UI.Phone;
using MelonLoader;
using MelonLoader.Preferences;
using MelonLoader.Utils;
using Microsoft.CodeAnalysis;
using S1API.Internal.Abstraction;
using S1API.PhoneApp;
using S1API.UI;
using S1API.Utils;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(/*Could not decode attribute arguments.*/)]
[assembly: MelonInfo(typeof(Mod), "Flash light Enhanced", "0.4.0", "Reborn Reaper", null)]
[assembly: MelonGame("TVGS", "Schedule I")]
[assembly: AssemblyTitle("Flash light Enhanced")]
[assembly: AssemblyProduct("Flash light Enhanced")]
[assembly: AssemblyFileVersion("0.4.0.0")]
[assembly: AssemblyVersion("0.4.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : System.Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(/*Could not decode attribute arguments.*/)]
	internal sealed class NullableAttribute : System.Attribute
	{
		public readonly byte[] NullableFlags;

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

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(/*Could not decode attribute arguments.*/)]
	internal sealed class NullableContextAttribute : System.Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(/*Could not decode attribute arguments.*/)]
	internal sealed class RefSafetyRulesAttribute : System.Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace FlashLightEnhanced
{
	public sealed class FlashlightSettings
	{
		[field: CompilerGenerated]
		public bool Enabled
		{
			[CompilerGenerated]
			get;
			[CompilerGenerated]
			set;
		} = true;

		[field: CompilerGenerated]
		public string LightColor
		{
			[CompilerGenerated]
			get;
			[CompilerGenerated]
			set;
		} = "#FFFFFF";

		[field: CompilerGenerated]
		public float Intensity
		{
			[CompilerGenerated]
			get;
			[CompilerGenerated]
			set;
		} = 3f;

		[field: CompilerGenerated]
		public float Range
		{
			[CompilerGenerated]
			get;
			[CompilerGenerated]
			set;
		} = 40f;

		[field: CompilerGenerated]
		public float SpotAngle
		{
			[CompilerGenerated]
			get;
			[CompilerGenerated]
			set;
		} = 80f;

		public FlashlightSettings Copy()
		{
			return (FlashlightSettings)base.MemberwiseClone();
		}

		public void RestoreAppearanceDefaults()
		{
			FlashlightSettings flashlightSettings = new FlashlightSettings();
			LightColor = flashlightSettings.LightColor;
			Intensity = flashlightSettings.Intensity;
			Range = flashlightSettings.Range;
			SpotAngle = flashlightSettings.SpotAngle;
		}

		public void Validate()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			if (LightColor == null || !Regex.IsMatch(LightColor, "\\A#[0-9a-fA-F]{6}\\z"))
			{
				throw new FormatException("LightColor must use #RRGGBB, for example #FFFFFF.");
			}
			Check(Intensity, 0f, 10f, "Intensity");
			Check(Range, 1f, 200f, "Range");
			Check(SpotAngle, 1f, 179f, "SpotAngle");
		}

		private static void Check(float value, float min, float max, string name)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			if (float.IsNaN(value) || float.IsInfinity(value) || value < min || value > max)
			{
				throw new FormatException($"{name} must be between {min} and {max}.");
			}
		}
	}
	public sealed class LumenApp : PhoneApp
	{
		private static LumenApp? current;

		private static Sprite? icon;

		private static readonly Color Background = new Color(0.018f, 0.022f, 0.018f, 1f);

		private static readonly Color Card = new Color(0.055f, 0.067f, 0.055f, 1f);

		private static readonly Color Accent = new Color(0.5f, 1f, 0f, 1f);

		private static readonly Color Muted = new Color(0.64f, 0.71f, 0.62f, 1f);

		private InputField hue;

		private InputField output;

		private InputField projection;

		private InputField spread;

		private Text enabledLabel;

		private Text status;

		private Image enabledImage;

		private Image swatch;

		private GameObject? root;

		private bool draftEnabled;

		private bool dirty;

		private bool syncing;

		private bool wasOpen;

		private bool ownsTyping;

		private int loadedRevision = -1;

		private int fontSize;

		private float nextError;

		protected override string AppName => "FlashLightEnhanced_Lumen";

		protected override string AppTitle => "Lumen";

		protected override string IconLabel => "Lumen";

		protected override string IconFileName => "FlashLightEnhanced/Lumen.png";

		protected override Sprite? IconSprite => LoadIcon();

		private SettingsStore Store => Mod.SharedSettings ?? throw new InvalidOperationException("Settings are not ready.");

		protected override void OnCreatedUI(GameObject container)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: 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)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: 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_0135: Expected O, but got Unknown
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Expected O, but got Unknown
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			//IL_028e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: Expected O, but got Unknown
			//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cf: Expected O, but got Unknown
			//IL_039b: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a5: Expected O, but got Unknown
			//IL_03d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03dc: Expected O, but got Unknown
			//IL_03e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f1: Unknown result type (might be due to invalid IL or missing references)
			root = container;
			current = this;
			Rect rect = container.GetComponent<RectTransform>().rect;
			fontSize = Mathf.Clamp(Mathf.RoundToInt(((Rect)(ref rect)).height * 0.038f), 12, 30);
			Image obj = container.AddComponent<Image>();
			((Graphic)obj).color = Background;
			((Graphic)obj).raycastTarget = true;
			Image component = Panel("Icon", container.transform, Color.white, 0.035f, 0.845f, 0.14f, 0.98f).GetComponent<Image>();
			component.sprite = LoadIcon();
			component.preserveAspect = true;
			Label("Title", "LUMEN", container.transform, 0.17f, 0.89f, 0.75f, 0.98f, fontSize + 12, Accent);
			Label("Subtitle", "FLASHLIGHT ENHANCED", container.transform, 0.17f, 0.835f, 0.75f, 0.9f, fontSize - 3, Muted);
			MakeButton("Back", "Back", container.transform, 0.85f, 0.87f, 0.96f, 0.96f, (Action)([CompilerGenerated] () =>
			{
				ReleaseTyping();
				((PhoneApp)this).CloseApp();
			}));
			status = Label("Status", "Changes are saved when you press Apply.", container.transform, 0.04f, 0.77f, 0.96f, 0.825f, fontSize - 3, Muted);
			GameObject val = Row("Enabled", "Custom appearance", container.transform, 0.65f, 0.75f);
			GameObject val2 = MakeButton("Enabled", "", val.transform, 0.69f, 0.14f, 0.97f, 0.86f, (Action)([CompilerGenerated] () =>
			{
				draftEnabled = !draftEnabled;
				UpdateEnabled();
				MarkDirty();
			}));
			enabledImage = val2.GetComponent<Image>();
			enabledLabel = val2.GetComponentInChildren<Text>();
			GameObject val3 = Row("Hue", "Colour / #RRGGBB", container.transform, 0.52f, 0.63f);
			hue = Field("Hue", val3.transform, 0.61f, 0.15f, 0.91f, 0.85f);
			swatch = Panel("ColourPreview", val3.transform, Color.white, 0.93f, 0.19f, 0.98f, 0.81f).GetComponent<Image>();
			MakeButton("Green", "Green", val3.transform, 0.31f, 0.18f, 0.44f, 0.82f, (Action)([CompilerGenerated] () =>
			{
				hue.text = "#80FF00";
			}));
			MakeButton("White", "White", val3.transform, 0.46f, 0.18f, 0.59f, 0.82f, (Action)([CompilerGenerated] () =>
			{
				hue.text = "#FFFFFF";
			}));
			output = NumberRow("Output", "Brightness / 0-10", container.transform, 0.39f, 0.5f, 0.5f, 0f, 10f);
			projection = NumberRow("Projection", "Distance / 1-200", container.transform, 0.26f, 0.37f, 5f, 1f, 200f);
			spread = NumberRow("Spread", "Degrees / 1-179", container.transform, 0.13f, 0.24f, 5f, 1f, 179f);
			MakeButton("Defaults", "Restore defaults", container.transform, 0.04f, 0.025f, 0.37f, 0.105f, new Action(RestoreDefaults));
			GameObject obj2 = MakeButton("Apply", "Apply", container.transform, 0.7f, 0.025f, 0.96f, 0.105f, new Action(Apply));
			((Graphic)obj2.GetComponent<Image>()).color = Accent;
			((Graphic)obj2.GetComponentInChildren<Text>()).color = Background;
			LoadSettings();
			Mod.LogInfo("Lumen phone interface created.");
		}

		internal static void TickCurrent()
		{
			LumenApp lumenApp = current;
			if (lumenApp == null)
			{
				return;
			}
			try
			{
				lumenApp.Tick();
			}
			catch (System.Exception ex)
			{
				lumenApp.ReleaseTyping();
				if (Time.realtimeSinceStartup >= lumenApp.nextError)
				{
					lumenApp.nextError = Time.realtimeSinceStartup + 30f;
					Mod.LogWarning("Lumen UI update failed: " + ex.Message);
				}
			}
		}

		private void Tick()
		{
			if ((Object)(object)root == (Object)null)
			{
				ShutdownCurrent();
				return;
			}
			bool flag = ((PhoneApp)this).IsOpen();
			if (flag && !wasOpen)
			{
				Store.Reload();
				LoadSettings();
			}
			if (flag && !dirty && loadedRevision != Store.Revision)
			{
				LoadSettings();
			}
			if (flag)
			{
				if (hue.isFocused || output.isFocused || projection.isFocused || spread.isFocused)
				{
					GameInput.IsTyping = true;
					ownsTyping = true;
				}
				else
				{
					ReleaseTyping();
				}
			}
			else
			{
				ReleaseTyping();
			}
			wasOpen = flag;
		}

		protected override void OnPhoneClosed()
		{
			ReleaseTyping();
		}

		protected override void OnDestroyed()
		{
			ReleaseTyping();
			if (current == this)
			{
				current = null;
			}
			((PhoneApp)this).OnDestroyed();
			root = null;
			hue = (output = (projection = (spread = null)));
			enabledLabel = (status = null);
			enabledImage = (swatch = null);
		}

		internal static void ShutdownCurrent()
		{
			LumenApp lumenApp = current;
			current = null;
			if (lumenApp == null)
			{
				return;
			}
			try
			{
				((Registerable)lumenApp).OnDestroyed();
			}
			catch (System.Exception ex)
			{
				Mod.LogWarning("Lumen cleanup: " + ex.Message);
			}
		}

		private void ReleaseTyping()
		{
			if (ownsTyping)
			{
				GameInput.IsTyping = false;
				ownsTyping = false;
			}
		}

		private void MarkDirty()
		{
			if (!syncing)
			{
				dirty = true;
				Message("Unsaved changes - press Apply.", error: false);
				UpdateSwatch();
			}
		}

		private void LoadSettings()
		{
			syncing = true;
			try
			{
				FlashlightSettings flashlightSettings = Store.Current;
				draftEnabled = flashlightSettings.Enabled;
				hue.text = flashlightSettings.LightColor;
				output.text = Format(flashlightSettings.Intensity);
				projection.text = Format(flashlightSettings.Range);
				spread.text = Format(flashlightSettings.SpotAngle);
				loadedRevision = Store.Revision;
				dirty = false;
				UpdateEnabled();
				UpdateSwatch();
				Message("Changes are saved when you press Apply.", error: false);
			}
			finally
			{
				syncing = false;
			}
		}

		private void Apply()
		{
			Store.Reload();
			if (loadedRevision != Store.Revision)
			{
				Message("Settings changed elsewhere. Close and reopen Lumen before applying.", error: true);
				return;
			}
			if (!LumenDraft.TryBuild(draftEnabled, hue.text, output.text, projection.text, spread.text, out FlashlightSettings settings, out string error))
			{
				Message(error, error: true);
				return;
			}
			if (!Store.TrySave(settings))
			{
				Message("Save failed. Previous settings retained; check the mod log.", error: true);
				return;
			}
			LoadSettings();
			Message("Saved. Your flashlight settings are up to date.", error: false);
			ReleaseTyping();
		}

		private void RestoreDefaults()
		{
			Store.Reload();
			FlashlightSettings flashlightSettings = Store.Current.Copy();
			flashlightSettings.RestoreAppearanceDefaults();
			if (!Store.TrySave(flashlightSettings))
			{
				Message("Could not restore defaults; previous settings retained.", error: true);
				return;
			}
			LoadSettings();
			Message("Defaults restored. Enabled is unchanged.", error: false);
			ReleaseTyping();
		}

		private void UpdateEnabled()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			enabledLabel.text = (draftEnabled ? "Enabled" : "Disabled");
			((Graphic)enabledLabel).color = (draftEnabled ? Background : Muted);
			((Graphic)enabledImage).color = (Color)(draftEnabled ? Accent : new Color(0.14f, 0.17f, 0.14f, 1f));
		}

		private void UpdateSwatch()
		{
			//IL_0030: 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)
			if (!((Object)(object)swatch == (Object)null))
			{
				Color val = default(Color);
				((Graphic)swatch).color = (ColorUtility.TryParseHtmlString(hue.text, ref val) ? val : Color.gray);
			}
		}

		private void Message(string text, bool error)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			status.text = text;
			((Graphic)status).color = (Color)(error ? new Color(1f, 0.47f, 0.35f, 1f) : Muted);
		}

		private InputField NumberRow(string title, string description, Transform parent, float bottom, float top, float step, float min, float max)
		{
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Expected O, but got Unknown
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Expected O, but got Unknown
			GameObject val = Row(title, description, parent, bottom, top);
			InputField field = Field(title, val.transform, 0.54f, 0.15f, 0.83f, 0.85f);
			MakeButton("Minus", "-", val.transform, 0.4f, 0.15f, 0.51f, 0.85f, (Action)delegate
			{
				Adjust(0f - step);
			});
			MakeButton("Plus", "+", val.transform, 0.86f, 0.15f, 0.97f, 0.85f, (Action)delegate
			{
				Adjust(step);
			});
			return field;
			void Adjust(float delta)
			{
				float num = default(float);
				if (float.TryParse(field.text, (NumberStyles)167, (IFormatProvider)(object)CultureInfo.InvariantCulture, ref num) && !float.IsNaN(num) && !float.IsInfinity(num))
				{
					field.text = Format(Mathf.Clamp(num + delta, min, max));
				}
			}
		}

		private GameObject Row(string title, string description, Transform parent, float bottom, float top)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Panel(title + "Row", parent, Card, 0.04f, bottom, 0.96f, top);
			Label(title + "Label", title, val.transform, 0.025f, 0.46f, 0.38f, 0.91f, fontSize, Color.white);
			Label(title + "Help", description, val.transform, 0.025f, 0.06f, 0.38f, 0.46f, fontSize - 4, Muted);
			return val;
		}

		private InputField Field(string name, Transform parent, float left, float bottom, float right, float top)
		{
			//IL_0020: 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)
			//IL_0098: 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)
			GameObject val = Panel(name + "Input", parent, new Color(0.015f, 0.02f, 0.015f, 1f), left, bottom, right, top);
			Text val2 = Label("Text", "", val.transform, 0.05f, 0.05f, 0.95f, 0.95f, fontSize, Color.white);
			val2.alignment = (TextAnchor)4;
			InputField val3 = val.AddComponent<InputField>();
			val3.textComponent = val2;
			((Selectable)val3).targetGraphic = (Graphic)(object)val.GetComponent<Image>();
			val3.lineType = (LineType)0;
			val3.characterLimit = 16;
			val3.caretColor = Accent;
			val3.customCaretColor = true;
			val3.selectionColor = new Color(0.3f, 0.6f, 0.1f, 0.6f);
			EventHelper.AddListener<string>((Action<string>)([CompilerGenerated] (string _) =>
			{
				MarkDirty();
			}), (UnityEvent<string>)(object)val3.onValueChanged);
			return val3;
		}

		private GameObject MakeButton(string name, string title, Transform parent, float left, float bottom, float right, float top, Action action)
		{
			//IL_0020: 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)
			GameObject val = Panel(name + "Button", parent, new Color(0.13f, 0.18f, 0.1f, 1f), left, bottom, right, top);
			Label("Label", title, val.transform, 0.03f, 0.03f, 0.97f, 0.97f, fontSize, Accent).alignment = (TextAnchor)4;
			Button val2 = val.AddComponent<Button>();
			((Selectable)val2).targetGraphic = (Graphic)(object)val.GetComponent<Image>();
			EventHelper.AddListener(action, (UnityEvent)(object)val2.onClick);
			return val;
		}

		private static GameObject Panel(string name, Transform parent, Color colour, float left, float bottom, float right, float top)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: 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)
			//IL_0027: 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_0037: 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_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			GameObject val = new GameObject(name);
			RectTransform obj = val.AddComponent<RectTransform>();
			((Transform)obj).SetParent(parent, false);
			obj.anchorMin = new Vector2(left, bottom);
			obj.anchorMax = new Vector2(right, top);
			Vector2 offsetMin = (obj.offsetMax = Vector2.zero);
			obj.offsetMin = offsetMin;
			val.layer = ((Component)parent).gameObject.layer;
			((Graphic)val.AddComponent<Image>()).color = colour;
			return val;
		}

		private static Text Label(string name, string value, Transform parent, float left, float bottom, float right, float top, int size, Color colour)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			Text obj = UIFactory.Text(name, value, parent, size, (TextAnchor)3, (FontStyle)0);
			RectTransform component = ((Component)obj).GetComponent<RectTransform>();
			component.anchorMin = new Vector2(left, bottom);
			component.anchorMax = new Vector2(right, top);
			Vector2 offsetMin = (component.offsetMax = Vector2.zero);
			component.offsetMin = offsetMin;
			((Component)obj).gameObject.layer = ((Component)parent).gameObject.layer;
			((Graphic)obj).color = colour;
			((Graphic)obj).raycastTarget = false;
			obj.supportRichText = false;
			obj.resizeTextForBestFit = true;
			obj.resizeTextMinSize = Math.Max(8, size - 5);
			obj.resizeTextMaxSize = size;
			return obj;
		}

		private static Sprite? LoadIcon()
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Expected O, but got Unknown
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)icon != (Object)null)
			{
				return icon;
			}
			Stream manifestResourceStream = typeof(LumenApp).Assembly.GetManifestResourceStream("FlashLightEnhanced.Lumen.png");
			try
			{
				if (manifestResourceStream == null)
				{
					throw new InvalidOperationException("Embedded Lumen icon is missing.");
				}
				MemoryStream val = new MemoryStream();
				try
				{
					manifestResourceStream.CopyTo((Stream)(object)val);
					Texture2D val2 = new Texture2D(2, 2);
					if (!ImageConversion.LoadImage(val2, Il2CppStructArray<byte>.op_Implicit(val.ToArray())))
					{
						Object.Destroy((Object)(object)val2);
						throw new InvalidOperationException("Could not decode the Lumen icon.");
					}
					((Texture)val2).filterMode = (FilterMode)1;
					icon = Sprite.Create(val2, new Rect(0f, 0f, (float)((Texture)val2).width, (float)((Texture)val2).height), new Vector2(0.5f, 0.5f));
					return icon;
				}
				finally
				{
					((System.IDisposable)val)?.Dispose();
				}
			}
			finally
			{
				((System.IDisposable)manifestResourceStream)?.Dispose();
			}
		}

		private static string Format(float value)
		{
			return value.ToString("G", (IFormatProvider)(object)CultureInfo.InvariantCulture);
		}
	}
	internal static class LumenDraft
	{
		public static bool TryBuild(bool enabled, string hue, string output, string projection, string spread, out FlashlightSettings settings, out string error)
		{
			settings = new FlashlightSettings();
			error = "";
			if (!Read(output, "Output", 0f, 10f, out var value, out error) || !Read(projection, "Projection", 1f, 200f, out var value2, out error) || !Read(spread, "Spread", 1f, 179f, out var value3, out error))
			{
				return false;
			}
			settings = new FlashlightSettings
			{
				Enabled = enabled,
				LightColor = hue.Trim().ToUpperInvariant(),
				Intensity = value,
				Range = value2,
				SpotAngle = value3
			};
			try
			{
				settings.Validate();
				return true;
			}
			catch (FormatException)
			{
				error = "Hue must be #RRGGBB, for example #80FF00.";
				return false;
			}
		}

		private static bool Read(string text, string label, float min, float max, out float value, out string error)
		{
			error = "";
			if (!float.TryParse(text, (NumberStyles)167, (IFormatProvider)(object)CultureInfo.InvariantCulture, ref value) || float.IsNaN(value) || float.IsInfinity(value) || value < min || value > max)
			{
				error = $"{label} must be {min} to {max}. Use a dot for decimals.";
				return false;
			}
			return true;
		}
	}
	internal sealed class MenuPreferences
	{
		private readonly SettingsStore store;

		private readonly MelonPreferences_Entry<bool> enabled;

		private readonly MelonPreferences_Entry<bool> restoreDefaults;

		private readonly MelonPreferences_Entry<string> hue;

		private readonly MelonPreferences_Entry<float> output;

		private readonly MelonPreferences_Entry<float> projection;

		private readonly MelonPreferences_Entry<float> spread;

		private bool synchronizing;

		private int revision = -1;

		public MenuPreferences(SettingsStore store)
		{
			this.store = store;
			MelonPreferences_Category val = MelonPreferences.CreateCategory("FlashLightEnhanced", "Flashlight settings");
			FlashlightSettings flashlightSettings = new FlashlightSettings();
			enabled = val.CreateEntry<bool>("Enabled", flashlightSettings.Enabled, "Enabled", "Enable custom lighting. Disable to restore the original flashlight settings.", false, false, (ValueValidator)null, (string)null);
			hue = val.CreateEntry<string>("Hue", flashlightSettings.LightColor, "Hue", "Beam colour in #RRGGBB format. White: #FFFFFF. Green: #00FF66.", false, false, (ValueValidator)null, (string)null);
			output = val.CreateEntry<float>("Output", flashlightSettings.Intensity, "Output", "Brightness, from 0 to 10.", false, false, (ValueValidator)null, (string)null);
			projection = val.CreateEntry<float>("Projection", flashlightSettings.Range, "Projection", "Beam distance, from 1 to 200.", false, false, (ValueValidator)null, (string)null);
			spread = val.CreateEntry<float>("Spread", flashlightSettings.SpotAngle, "Spread", "Beam angle in degrees, from 1 to 179.", false, false, (ValueValidator)null, (string)null);
			restoreDefaults = val.CreateEntry<bool>("RestoreDefaults", false, "Restore default settings", "Turn on once to restore Hue #FFFFFF, Output 3, Projection 40 and Spread 80. Keeps Enabled unchanged. Reopen this panel to refresh the displayed values.", false, true, (ValueValidator)null, (string)null);
			SyncFromStore();
			((MelonEventBase<LemonAction<bool, bool>>)(object)enabled.OnEntryValueChanged).Subscribe((LemonAction<bool, bool>)([CompilerGenerated] (bool _, bool value) =>
			{
				Change(delegate(FlashlightSettings s)
				{
					s.Enabled = value;
				});
			}), 0, false);
			((MelonEventBase<LemonAction<string, string>>)(object)hue.OnEntryValueChanged).Subscribe((LemonAction<string, string>)([CompilerGenerated] (string _, string value) =>
			{
				Change(delegate(FlashlightSettings s)
				{
					s.LightColor = value;
				});
			}), 0, false);
			((MelonEventBase<LemonAction<float, float>>)(object)output.OnEntryValueChanged).Subscribe((LemonAction<float, float>)([CompilerGenerated] (float _, float value) =>
			{
				Change(delegate(FlashlightSettings s)
				{
					s.Intensity = value;
				});
			}), 0, false);
			((MelonEventBase<LemonAction<float, float>>)(object)projection.OnEntryValueChanged).Subscribe((LemonAction<float, float>)([CompilerGenerated] (float _, float value) =>
			{
				Change(delegate(FlashlightSettings s)
				{
					s.Range = value;
				});
			}), 0, false);
			((MelonEventBase<LemonAction<float, float>>)(object)spread.OnEntryValueChanged).Subscribe((LemonAction<float, float>)([CompilerGenerated] (float _, float value) =>
			{
				Change(delegate(FlashlightSettings s)
				{
					s.SpotAngle = value;
				});
			}), 0, false);
			((MelonEventBase<LemonAction<bool, bool>>)(object)restoreDefaults.OnEntryValueChanged).Subscribe((LemonAction<bool, bool>)([CompilerGenerated] (bool _, bool value) =>
			{
				if (value)
				{
					Change(delegate(FlashlightSettings s)
					{
						s.RestoreAppearanceDefaults();
					});
				}
			}), 0, false);
		}

		private void Change(Action<FlashlightSettings> edit)
		{
			if (!synchronizing)
			{
				store.Reload();
				FlashlightSettings flashlightSettings = store.Current.Copy();
				edit.Invoke(flashlightSettings);
				store.TrySave(flashlightSettings);
				revision = -1;
				SyncFromStore();
			}
		}

		public void SyncFromStore()
		{
			if (revision == store.Revision)
			{
				return;
			}
			synchronizing = true;
			try
			{
				FlashlightSettings current = store.Current;
				enabled.Value = current.Enabled;
				hue.Value = current.LightColor;
				output.Value = current.Intensity;
				projection.Value = current.Range;
				spread.Value = current.SpotAngle;
				restoreDefaults.Value = false;
				revision = store.Revision;
			}
			finally
			{
				synchronizing = false;
			}
		}
	}
	public sealed class Mod : MelonMod
	{
		private sealed class OriginalLight
		{
			public readonly Light Light;

			private readonly Color color;

			private readonly float intensity;

			private readonly float range;

			private readonly float angle;

			public OriginalLight(Light light)
			{
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				Light = light;
				color = light.color;
				intensity = light.intensity;
				range = light.range;
				angle = light.spotAngle;
			}

			public void Restore()
			{
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				Light.color = color;
				Light.intensity = intensity;
				Light.range = range;
				Light.spotAngle = angle;
			}
		}

		private static Mod? instance;

		private SettingsStore store;

		private MenuPreferences menu;

		private readonly List<OriginalLight> originals = new List<OriginalLight>();

		private GameObject? flashlight;

		private float nextCheck;

		private float nextError;

		private int appliedRevision = -1;

		private bool warnedMissingLight;

		[field: CompilerGenerated]
		internal static SettingsStore? SharedSettings
		{
			[CompilerGenerated]
			get;
			[CompilerGenerated]
			private set;
		}

		internal static void LogInfo(string message)
		{
			Mod? mod = instance;
			if (mod != null)
			{
				((MelonBase)mod).LoggerInstance.Msg(message);
			}
		}

		internal static void LogWarning(string message)
		{
			Mod? mod = instance;
			if (mod != null)
			{
				((MelonBase)mod).LoggerInstance.Warning(message);
			}
		}

		public override void OnInitializeMelon()
		{
			instance = this;
			store = new SettingsStore(Path.Combine(MelonEnvironment.UserDataDirectory, "FlashLightEnhanced.json"), [CompilerGenerated] (string message) =>
			{
				((MelonBase)this).LoggerInstance.Msg(message);
			}, [CompilerGenerated] (string message) =>
			{
				((MelonBase)this).LoggerInstance.Warning(message);
			}, Path.Combine(MelonEnvironment.UserDataDirectory, "BetterFlashlightReborn.json"));
			store.Reload();
			SharedSettings = store;
			menu = new MenuPreferences(store);
			((MelonBase)this).LoggerInstance.Msg("Ready. Configuration reloads every second; the game controls the flashlight toggle.");
		}

		public override void OnLateUpdate()
		{
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			LumenApp.TickCurrent();
			if (Time.realtimeSinceStartup < nextCheck)
			{
				return;
			}
			nextCheck = Time.realtimeSinceStartup + 1f;
			store.Reload();
			menu.SyncFromStore();
			try
			{
				Phone val = PlayerSingleton<Phone>.Instance;
				GameObject val2 = (((Object)(object)val != (Object)null) ? val.PhoneFlashlight : null);
				if ((Object)(object)flashlight != (Object)(object)val2)
				{
					Restore();
					flashlight = val2;
					warnedMissingLight = false;
				}
				if ((Object)(object)flashlight == (Object)null)
				{
					return;
				}
				Il2CppArrayBase<Light> componentsInChildren = flashlight.GetComponentsInChildren<Light>(true);
				bool flag = false;
				System.Collections.Generic.IEnumerator<Light> enumerator = componentsInChildren.GetEnumerator();
				Enumerator<OriginalLight> enumerator2;
				try
				{
					while (((System.Collections.IEnumerator)enumerator).MoveNext())
					{
						Light current = enumerator.Current;
						if ((Object)(object)current == (Object)null || (int)current.type != 0)
						{
							continue;
						}
						flag = true;
						bool flag2 = false;
						enumerator2 = originals.GetEnumerator();
						try
						{
							while (enumerator2.MoveNext())
							{
								if ((Object)(object)enumerator2.Current.Light == (Object)(object)current)
								{
									flag2 = true;
									break;
								}
							}
						}
						finally
						{
							((System.IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose();
						}
						if (!flag2)
						{
							originals.Add(new OriginalLight(current));
							appliedRevision = -1;
							((MelonBase)this).LoggerInstance.Msg("Bound local flashlight spotlight: " + ((Object)current).name);
						}
					}
				}
				finally
				{
					((System.IDisposable)enumerator)?.Dispose();
				}
				originals.RemoveAll((Predicate<OriginalLight>)((OriginalLight original) => (Object)(object)original.Light == (Object)null));
				if (!flag && !warnedMissingLight)
				{
					warnedMissingLight = true;
					((MelonBase)this).LoggerInstance.Warning("No spotlight under PhoneFlashlight; leaving vanilla behaviour intact.");
				}
				enumerator2 = originals.GetEnumerator();
				try
				{
					while (enumerator2.MoveNext())
					{
						OriginalLight current2 = enumerator2.Current;
						if (!((Object)(object)current2.Light == (Object)null))
						{
							if (store.Current.Enabled)
							{
								Apply(current2.Light, store.Current);
							}
							else if (appliedRevision != store.Revision)
							{
								current2.Restore();
							}
						}
					}
				}
				finally
				{
					((System.IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose();
				}
				appliedRevision = store.Revision;
			}
			catch (System.Exception ex)
			{
				if (Time.realtimeSinceStartup >= nextError)
				{
					nextError = Time.realtimeSinceStartup + 30f;
					((MelonBase)this).LoggerInstance.Warning("Flashlight binding failed; will retry: " + ex.Message);
				}
			}
		}

		private static void Apply(Light light, FlashlightSettings settings)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			string lightColor = settings.LightColor;
			Color color = default(Color);
			((Color)(ref color))..ctor((float)(int)byte.Parse(lightColor.Substring(1, 2), (NumberStyles)515) / 255f, (float)(int)byte.Parse(lightColor.Substring(3, 2), (NumberStyles)515) / 255f, (float)(int)byte.Parse(lightColor.Substring(5, 2), (NumberStyles)515) / 255f, 1f);
			light.color = color;
			light.intensity = settings.Intensity;
			light.range = settings.Range;
			light.spotAngle = settings.SpotAngle;
		}

		private void Restore()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			Enumerator<OriginalLight> enumerator = originals.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					OriginalLight current = enumerator.Current;
					if ((Object)(object)current.Light != (Object)null)
					{
						current.Restore();
					}
				}
			}
			finally
			{
				((System.IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
			}
			originals.Clear();
			flashlight = null;
			appliedRevision = -1;
		}

		public override void OnSceneWasUnloaded(int buildIndex, string sceneName)
		{
			if (sceneName == "Main")
			{
				LumenApp.ShutdownCurrent();
			}
		}

		public override void OnDeinitializeMelon()
		{
			LumenApp.ShutdownCurrent();
			Restore();
			SharedSettings = null;
			instance = null;
		}
	}
	public sealed class SettingsStore
	{
		private readonly string path;

		private readonly string? legacyPath;

		private bool migrationChecked;

		private readonly Action<string> info;

		private readonly Action<string> warning;

		private string? lastText;

		private string? lastError;

		[field: CompilerGenerated]
		public FlashlightSettings Current
		{
			[CompilerGenerated]
			get;
			[CompilerGenerated]
			private set;
		} = new FlashlightSettings();

		[field: CompilerGenerated]
		public int Revision
		{
			[CompilerGenerated]
			get;
			[CompilerGenerated]
			private set;
		}

		public SettingsStore(string path, Action<string> info, Action<string> warning, string? legacyPath = null)
		{
			this.path = path;
			this.legacyPath = legacyPath;
			this.info = info;
			this.warning = warning;
		}

		public bool TrySave(FlashlightSettings settings)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			string text = null;
			try
			{
				settings.Validate();
				FlashlightSettings flashlightSettings = settings.Copy();
				string text2 = JsonSerializer.Serialize<FlashlightSettings>(flashlightSettings, new JsonSerializerOptions
				{
					WriteIndented = true
				});
				Directory.CreateDirectory(Path.GetDirectoryName(path));
				string text3 = path;
				Guid val = Guid.NewGuid();
				text = text3 + "." + ((Guid)(ref val)).ToString("N") + ".tmp";
				File.WriteAllText(text, text2);
				File.Move(text, path, true);
				Current = flashlightSettings;
				lastText = text2;
				lastError = null;
				Revision++;
				return true;
			}
			catch (System.Exception ex) when (ex is IOException || ex is UnauthorizedAccessException || ex is FormatException)
			{
				warning.Invoke("Could not save flashlight settings; keeping previous values. " + ex.Message);
				return false;
			}
			finally
			{
				if (text != null)
				{
					try
					{
						File.Delete(text);
					}
					catch (IOException)
					{
					}
					catch (UnauthorizedAccessException)
					{
					}
				}
			}
		}

		public void Reload()
		{
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Expected O, but got Unknown
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Expected O, but got Unknown
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Expected O, but got Unknown
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!migrationChecked)
				{
					if (!File.Exists(path) && legacyPath != null && File.Exists(legacyPath))
					{
						Directory.CreateDirectory(Path.GetDirectoryName(path));
						File.Copy(legacyPath, path, false);
						info.Invoke("Migrated previous project configuration to: " + path);
					}
					migrationChecked = true;
				}
				if (!File.Exists(path))
				{
					Directory.CreateDirectory(Path.GetDirectoryName(path));
					FileStream val = new FileStream(path, (FileMode)1, (FileAccess)2, (FileShare)0);
					try
					{
						JsonSerializer.Serialize<FlashlightSettings>((Stream)(object)val, Current, new JsonSerializerOptions
						{
							WriteIndented = true
						});
						info.Invoke("Created configuration: " + path);
					}
					finally
					{
						((System.IDisposable)val)?.Dispose();
					}
				}
				string text = File.ReadAllText(path);
				if (!(text == lastText))
				{
					lastText = text;
					FlashlightSettings flashlightSettings = JsonSerializer.Deserialize<FlashlightSettings>(text, new JsonSerializerOptions
					{
						PropertyNameCaseInsensitive = true
					}) ?? throw new FormatException("Configuration must be a JSON object.");
					flashlightSettings.Validate();
					Current = flashlightSettings;
					Revision++;
					lastError = null;
					info.Invoke("Loaded flashlight settings: " + path);
				}
			}
			catch (System.Exception ex) when (ex is IOException || ex is UnauthorizedAccessException || ex is JsonException || ex is FormatException)
			{
				string message = ex.Message;
				if (message != lastError)
				{
					warning.Invoke("Keeping last valid flashlight settings. " + path + ": " + message);
				}
				lastError = message;
			}
		}
	}
}