Decompiled source of WispTorchHeeler v1.1.0

WispTorchHeeler.dll

Decompiled 6 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ConditionalConfigSync;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.SceneManagement;
using WispTorchHeeler.Configuration;
using WispTorchHeeler.Lighting;
using WispTorchHeeler.Localization;
using WispTorchHeeler.Painter;
using WispTorchHeeler.Pieces;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("WispTorchHeeler")]
[assembly: AssemblyDescription("Tiered Mistlands wisp torches and lamps with expanded mist clearance, interactive torch painting, and multiplayer color synchronization. For more information, visit https://github.com/dreamwraith")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("dreamwraith (https://github.com/dreamwraith)")]
[assembly: AssemblyProduct("WispTorchHeeler")]
[assembly: AssemblyCopyright("Copyright © 2026 dreamwraith")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e8288be6-ca15-429d-9002-de73aa3f3ba7")]
[assembly: AssemblyFileVersion("1.1.0")]
[assembly: AssemblyInformationalVersion("1.1.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace WispTorchHeeler
{
	[BepInPlugin("dreamwraith.WispTorchHeeler", "WispTorchHeeler", "1.1.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string ModGUID = "dreamwraith.WispTorchHeeler";

		public const string ModName = "WispTorchHeeler";

		public const string ModVersion = "1.1.0";

		internal static ManualLogSource Log;

		private Harmony? _harmony;

		internal static Plugin? Instance { get; private set; }

		private void Awake()
		{
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			ModConfig.Initialize(((BaseUnityPlugin)this).Config);
			if (!ModConfig.EnableMod.Value)
			{
				Log.LogInfo((object)"WispTorchHeeler is disabled in configuration.");
				return;
			}
			ModLocalization.Initialize();
			WispPieceManager.Initialize();
			ModConfig.EnableMod.SettingChanged += delegate
			{
				WispTorchColorController.RefreshAll();
			};
			ModConfig.DefaultLightColor.SettingChanged += delegate
			{
				WispTorchColorController.RefreshAll();
			};
			ModConfig.ServerDefaultLightColor.SettingChanged += delegate
			{
				WispTorchColorController.RefreshAll();
			};
			ModConfig.EnforceServerDefaultColor.SettingChanged += delegate
			{
				WispTorchColorController.RefreshAll();
			};
			ModConfig.AffectNativeMistTorches.SettingChanged += delegate
			{
				WispTorchColorController.RefreshAll();
			};
			ModConfig.EnableAlphaCustomization.SettingChanged += delegate
			{
				WispTorchColorController.RefreshAll();
			};
			ModConfig.ShowMistSuppressionRadius.SettingChanged += delegate
			{
				WispTorchColorController.RefreshAllMarkers();
			};
			_harmony = Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "dreamwraith.WispTorchHeeler");
			Log.LogInfo((object)"WispTorchHeeler v1.1.0 loaded successfully.");
		}

		private void Update()
		{
			if (ModConfig.EnableMod.Value && !((Object)(object)Player.m_localPlayer == (Object)null))
			{
				if (ModConfig.ButtonResetConfig != null && ZInput.GetButtonDown(ModConfig.ButtonResetConfig.Name))
				{
					TorchPainter.TryPaintOrReset(isReset: true);
				}
				else if (ModConfig.ButtonPaintConfig != null && ZInput.GetButtonDown(ModConfig.ButtonPaintConfig.Name))
				{
					TorchPainter.TryPaintOrReset(isReset: false);
				}
			}
		}

		private void OnDestroy()
		{
			Harmony? harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		internal static void LogDebug(string message)
		{
			if (ModConfig.EnableDebugLogs != null && ModConfig.EnableDebugLogs.Value)
			{
				Log.LogInfo((object)("[DEBUG] " + message));
			}
		}
	}
	internal static class VersionInfo
	{
		public const string Version = "1.1.0";
	}
}
namespace WispTorchHeeler.Pieces
{
	public static class WispPieceManager
	{
		public class PieceBaseStats
		{
			public float BaseHealth;

			public float[] ForceFieldStartRanges = Array.Empty<float>();

			public float[] ForceFieldEndRanges = Array.Empty<float>();

			public float[] LightIntensities = Array.Empty<float>();

			public float[] LightRanges = Array.Empty<float>();
		}

		public const string Tier1TorchPrefab = "piece_wisptorch_heeler_lg";

		public const string Tier2SmallLampPrefab = "piece_wisplamp_heeler";

		public const string Tier3LargeLampPrefab = "piece_wisplamp_heeler_lg";

		public const string Tier4GrandLampPrefab = "piece_wisplamp_heeler_grand";

		public const string NativeMistTorchPrefab = "piece_groundtorch_mist";

		public const string NativeWallTorchPrefab = "piece_walltorch";

		public const string NativeDvergrLanternPrefab = "piece_dvergr_lantern";

		public const string NativeDemisterPrefab = "dverger_demister";

		public const string NativeDemisterLargePrefab = "dverger_demister_large";

		public const float NativePlayerBaseRadius = 20f;

		public const float NativeMistClearRadius = 24f;

		public const float NativeLightRange = 10f;

		private static bool s_piecesRegistered;

		public static readonly Dictionary<string, PieceBaseStats> BaseStats = new Dictionary<string, PieceBaseStats>();

		private static GameObject? s_areaMarkerTemplate;

		public static GameObject? AreaMarkerTemplate
		{
			get
			{
				if ((Object)(object)s_areaMarkerTemplate == (Object)null)
				{
					GameObject val = ((PrefabManager.Instance != null) ? PrefabManager.Instance.GetPrefab("guard_stone") : (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab("guard_stone") : null));
					if ((Object)(object)val != (Object)null)
					{
						PrivateArea component = val.GetComponent<PrivateArea>();
						if ((Object)(object)component != (Object)null && (Object)(object)component.m_areaMarker != (Object)null)
						{
							s_areaMarkerTemplate = ((Component)component.m_areaMarker).gameObject;
						}
					}
					if ((Object)(object)s_areaMarkerTemplate == (Object)null)
					{
						GameObject val2 = ((PrefabManager.Instance != null) ? PrefabManager.Instance.GetPrefab("piece_workbench") : (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab("piece_workbench") : null));
						if ((Object)(object)val2 != (Object)null)
						{
							CraftingStation component2 = val2.GetComponent<CraftingStation>();
							if ((Object)(object)component2 != (Object)null && (Object)(object)component2.m_areaMarker != (Object)null)
							{
								s_areaMarkerTemplate = component2.m_areaMarker;
							}
						}
					}
				}
				return s_areaMarkerTemplate;
			}
		}

		public static void Initialize()
		{
			PrefabManager.OnVanillaPrefabsAvailable += RegisterCustomPieces;
			PieceManager.OnPiecesRegistered += OnPiecesRegistered;
			ModConfig.Torch_Recipe.SettingChanged += delegate
			{
				UpdatePieceConfiguration("piece_wisptorch_heeler_lg");
			};
			ModConfig.Torch_CraftingStation.SettingChanged += delegate
			{
				UpdatePieceConfiguration("piece_wisptorch_heeler_lg");
			};
			ModConfig.Torch_Health.SettingChanged += delegate
			{
				UpdatePieceConfiguration("piece_wisptorch_heeler_lg");
			};
			ModConfig.Torch_MistClearRangeMultiplier.SettingChanged += delegate
			{
				UpdatePieceConfiguration("piece_wisptorch_heeler_lg");
			};
			ModConfig.Torch_LightIntensityMultiplier.SettingChanged += delegate
			{
				UpdatePieceConfiguration("piece_wisptorch_heeler_lg");
			};
			ModConfig.Torch_LightRangeMultiplier.SettingChanged += delegate
			{
				UpdatePieceConfiguration("piece_wisptorch_heeler_lg");
			};
			ModConfig.SmallLamp_Recipe.SettingChanged += delegate
			{
				UpdatePieceConfiguration("piece_wisplamp_heeler");
			};
			ModConfig.SmallLamp_CraftingStation.SettingChanged += delegate
			{
				UpdatePieceConfiguration("piece_wisplamp_heeler");
			};
			ModConfig.SmallLamp_Health.SettingChanged += delegate
			{
				UpdatePieceConfiguration("piece_wisplamp_heeler");
			};
			ModConfig.SmallLamp_MistClearRangeMultiplier.SettingChanged += delegate
			{
				UpdatePieceConfiguration("piece_wisplamp_heeler");
			};
			ModConfig.SmallLamp_LightIntensityMultiplier.SettingChanged += delegate
			{
				UpdatePieceConfiguration("piece_wisplamp_heeler");
			};
			ModConfig.SmallLamp_LightRangeMultiplier.SettingChanged += delegate
			{
				UpdatePieceConfiguration("piece_wisplamp_heeler");
			};
			ModConfig.LargeLamp_Recipe.SettingChanged += delegate
			{
				UpdatePieceConfiguration("piece_wisplamp_heeler_lg");
			};
			ModConfig.LargeLamp_CraftingStation.SettingChanged += delegate
			{
				UpdatePieceConfiguration("piece_wisplamp_heeler_lg");
			};
			ModConfig.LargeLamp_Health.SettingChanged += delegate
			{
				UpdatePieceConfiguration("piece_wisplamp_heeler_lg");
			};
			ModConfig.LargeLamp_MistClearRangeMultiplier.SettingChanged += delegate
			{
				UpdatePieceConfiguration("piece_wisplamp_heeler_lg");
			};
			ModConfig.LargeLamp_LightIntensityMultiplier.SettingChanged += delegate
			{
				UpdatePieceConfiguration("piece_wisplamp_heeler_lg");
			};
			ModConfig.LargeLamp_LightRangeMultiplier.SettingChanged += delegate
			{
				UpdatePieceConfiguration("piece_wisplamp_heeler_lg");
			};
			ModConfig.GrandLamp_Recipe.SettingChanged += delegate
			{
				UpdatePieceConfiguration("piece_wisplamp_heeler_grand");
			};
			ModConfig.GrandLamp_CraftingStation.SettingChanged += delegate
			{
				UpdatePieceConfiguration("piece_wisplamp_heeler_grand");
			};
			ModConfig.GrandLamp_Health.SettingChanged += delegate
			{
				UpdatePieceConfiguration("piece_wisplamp_heeler_grand");
			};
			ModConfig.GrandLamp_MistClearRangeMultiplier.SettingChanged += delegate
			{
				UpdatePieceConfiguration("piece_wisplamp_heeler_grand");
			};
			ModConfig.GrandLamp_LightIntensityMultiplier.SettingChanged += delegate
			{
				UpdatePieceConfiguration("piece_wisplamp_heeler_grand");
			};
			ModConfig.GrandLamp_LightRangeMultiplier.SettingChanged += delegate
			{
				UpdatePieceConfiguration("piece_wisplamp_heeler_grand");
			};
			ModConfig.PlayerBaseMistRadiusBonus.SettingChanged += delegate
			{
				UpdateAllPieceConfigurations();
			};
			Plugin.LogDebug("[PieceManager] Subscribed to native prefab, piece lifecycle, and config property events.");
		}

		private static void RegisterCustomPieces()
		{
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: 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)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			if (s_piecesRegistered)
			{
				return;
			}
			s_piecesRegistered = true;
			Plugin.LogDebug("[PieceManager] RegisterCustomPieces triggered.");
			GameObject prefab = PrefabManager.Instance.GetPrefab("piece_groundtorch_mist");
			if ((Object)(object)prefab != (Object)null)
			{
				if ((Object)(object)prefab.GetComponent<WispTorchColorController>() == (Object)null)
				{
					prefab.AddComponent<WispTorchColorController>();
					Plugin.LogDebug("[PieceManager] Injected WispTorchColorController into native prefab 'piece_groundtorch_mist'.");
				}
				EnsurePieceCollider(prefab, new Vector3(0f, 0.025f, 0f), new Vector3(0.25f, 1.35f, 0.25f));
			}
			else
			{
				Plugin.Log.LogWarning((object)"[PieceManager] Native prefab 'piece_groundtorch_mist' not found for controller injection.");
			}
			RegisterPiece("piece_wisptorch_heeler_lg", "piece_groundtorch_mist", "$piece_wisptorch_heeler_lg", "$piece_wisptorch_heeler_lg_description", 1.25f, ModConfig.Torch_Recipe.Value, (string)((ConfigEntryBase)ModConfig.Torch_Recipe).DefaultValue, ModConfig.Torch_CraftingStation.Value, new Vector3(0f, 0.025f, 0f), new Vector3(0.25f, 1.35f, 0.25f));
			RegisterPiece("piece_wisplamp_heeler", "dverger_demister", "$piece_wisplamp_heeler", "$piece_wisplamp_heeler_description", 1f, ModConfig.SmallLamp_Recipe.Value, (string)((ConfigEntryBase)ModConfig.SmallLamp_Recipe).DefaultValue, ModConfig.SmallLamp_CraftingStation.Value, new Vector3(0f, -0.1f, 0f), new Vector3(0.26f, 1.1f, 0.26f), "piece_walltorch", "piece_dvergr_lantern");
			RegisterPiece("piece_wisplamp_heeler_lg", "dverger_demister_large", "$piece_wisplamp_heeler_lg", "$piece_wisplamp_heeler_lg_description", 1.1f, ModConfig.LargeLamp_Recipe.Value, (string)((ConfigEntryBase)ModConfig.LargeLamp_Recipe).DefaultValue, ModConfig.LargeLamp_CraftingStation.Value, new Vector3(0f, -0.18f, 0f), new Vector3(0.32f, 1.45f, 0.32f), "piece_walltorch", "piece_dvergr_lantern");
			RegisterPiece("piece_wisplamp_heeler_grand", "dverger_demister_large", "$piece_wisplamp_heeler_grand", "$piece_wisplamp_heeler_grand_description", 1.5f, ModConfig.GrandLamp_Recipe.Value, (string)((ConfigEntryBase)ModConfig.GrandLamp_Recipe).DefaultValue, ModConfig.GrandLamp_CraftingStation.Value, new Vector3(0f, -0.18f, 0f), new Vector3(0.32f, 1.45f, 0.32f), "piece_walltorch", "piece_dvergr_lantern");
			PrefabManager.OnVanillaPrefabsAvailable -= RegisterCustomPieces;
		}

		private static void RegisterPiece(string customPrefabName, string basePrefabName, string nameToken, string descriptionToken, float scaleFactor, string recipeString, string defaultRecipeString, string stationString, in Vector3 colliderCenter, in Vector3 colliderSize, string? placeEffectSource = null, string? wearEffectSource = null)
		{
			//IL_0479: Unknown result type (might be due to invalid IL or missing references)
			//IL_0480: Expected O, but got Unknown
			//IL_04de: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e5: Expected O, but got Unknown
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			if (!TryParseAndValidateRecipe(recipeString, customPrefabName, out RequirementConfig[] requirements))
			{
				Plugin.Log.LogError((object)("[PieceManager] Config recipe for piece '" + customPrefabName + "' is invalid ('" + recipeString + "'). Falling back to default recipe: '" + defaultRecipeString + "'."));
				if (!TryParseAndValidateRecipe(defaultRecipeString, customPrefabName, out requirements))
				{
					Plugin.Log.LogError((object)("[PieceManager] Default recipe for piece '" + customPrefabName + "' is also invalid ('" + defaultRecipeString + "'). Aborting piece registration."));
					return;
				}
			}
			GameObject val = PrefabManager.Instance.CreateClonedPrefab(customPrefabName, basePrefabName);
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogError((object)("[PieceManager] Failed to clone prefab '" + basePrefabName + "' as '" + customPrefabName + "'."));
				return;
			}
			ParticleSystemForceField[] componentsInChildren = val.GetComponentsInChildren<ParticleSystemForceField>(true);
			Light[] componentsInChildren2 = val.GetComponentsInChildren<Light>(true);
			WearNTear component = val.GetComponent<WearNTear>();
			PieceBaseStats pieceBaseStats = new PieceBaseStats
			{
				BaseHealth = (((Object)(object)component != (Object)null) ? component.m_health : 100f),
				ForceFieldStartRanges = new float[componentsInChildren.Length],
				ForceFieldEndRanges = new float[componentsInChildren.Length],
				LightIntensities = new float[componentsInChildren2.Length],
				LightRanges = new float[componentsInChildren2.Length]
			};
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				pieceBaseStats.ForceFieldStartRanges[i] = componentsInChildren[i].startRange;
				pieceBaseStats.ForceFieldEndRanges[i] = 24f;
			}
			for (int j = 0; j < componentsInChildren2.Length; j++)
			{
				pieceBaseStats.LightIntensities[j] = componentsInChildren2[j].intensity;
				pieceBaseStats.LightRanges[j] = 10f;
			}
			BaseStats[customPrefabName] = pieceBaseStats;
			if (Mathf.Abs(scaleFactor - 1f) > 0.001f)
			{
				val.transform.localScale = val.transform.localScale * scaleFactor;
				Plugin.LogDebug($"[PieceManager] Scaled '{customPrefabName}' by {scaleFactor}x.");
			}
			if ((Object)(object)val.GetComponent<ZNetView>() == (Object)null)
			{
				val.AddComponent<ZNetView>().m_syncInitialScale = true;
			}
			Piece val2 = val.GetComponent<Piece>();
			if ((Object)(object)val2 == (Object)null)
			{
				val2 = val.AddComponent<Piece>();
			}
			val2.m_name = nameToken;
			val2.m_description = descriptionToken;
			val2.m_canBeRemoved = true;
			val2.m_category = (PieceCategory)0;
			HoverText val3 = val.GetComponent<HoverText>();
			if ((Object)(object)val3 == (Object)null)
			{
				val3 = val.AddComponent<HoverText>();
			}
			val3.m_text = nameToken;
			if (!string.IsNullOrEmpty(placeEffectSource))
			{
				GameObject prefab = PrefabManager.Instance.GetPrefab(placeEffectSource);
				Piece val4 = ((prefab != null) ? prefab.GetComponent<Piece>() : null);
				if ((Object)(object)val4 != (Object)null && val4.m_placeEffect != null)
				{
					val2.m_placeEffect = val4.m_placeEffect;
				}
			}
			if ((Object)(object)val2.m_icon == (Object)null)
			{
				GameObject prefab2 = PrefabManager.Instance.GetPrefab("piece_groundtorch_mist");
				Piece val5 = (((Object)(object)prefab2 != (Object)null) ? prefab2.GetComponent<Piece>() : null);
				if ((Object)(object)val5 != (Object)null && (Object)(object)val5.m_icon != (Object)null)
				{
					val2.m_icon = val5.m_icon;
				}
			}
			try
			{
				Sprite val6 = RenderManager.Instance.Render(val);
				if ((Object)(object)val6 != (Object)null)
				{
					val2.m_icon = val6;
					Plugin.LogDebug("[PieceManager] Generated custom 3D snapshot icon for '" + customPrefabName + "'.");
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[PieceManager] Failed to render 3D icon for '" + customPrefabName + "': " + ex.Message));
			}
			WearNTear val7 = val.GetComponent<WearNTear>();
			if ((Object)(object)val7 == (Object)null)
			{
				val7 = val.AddComponent<WearNTear>();
			}
			val7.m_noRoofWear = true;
			val7.m_noSupportWear = true;
			if (!string.IsNullOrEmpty(wearEffectSource))
			{
				GameObject prefab3 = PrefabManager.Instance.GetPrefab(wearEffectSource);
				WearNTear val8 = ((prefab3 != null) ? prefab3.GetComponent<WearNTear>() : null);
				if ((Object)(object)val8 != (Object)null)
				{
					val7.m_hitEffect = val8.m_hitEffect;
					val7.m_destroyedEffect = val8.m_destroyedEffect;
				}
			}
			int num = LayerMask.NameToLayer("piece");
			if (num >= 0)
			{
				val.layer = num;
				Collider[] componentsInChildren3 = val.GetComponentsInChildren<Collider>(true);
				foreach (Collider val9 in componentsInChildren3)
				{
					if (!val9.isTrigger)
					{
						((Component)val9).gameObject.layer = num;
					}
				}
			}
			EnsurePieceCollider(val, in colliderCenter, in colliderSize);
			EnsurePlayerBase(val);
			ApplyProperties(val, customPrefabName);
			if ((Object)(object)val.GetComponent<WispTorchColorController>() == (Object)null)
			{
				val.AddComponent<WispTorchColorController>();
			}
			PieceConfig val10 = new PieceConfig();
			val10.Name = nameToken;
			val10.Description = descriptionToken;
			val10.PieceTable = PieceTables.Hammer;
			val10.Category = PieceCategories.Misc;
			val10.Usage = new string[2]
			{
				PieceUsages.Lighting,
				PieceUsages.Misc
			};
			val10.CraftingStation = stationString;
			val10.Requirements = requirements;
			PieceConfig val11 = val10;
			CustomPiece val12 = new CustomPiece(val, true, val11);
			PieceManager.Instance.AddPiece(val12);
			Plugin.LogDebug("[PieceManager] Successfully registered CustomPiece '" + customPrefabName + "' in Hammer (Category=Misc, Usages=Lighting,Misc).");
		}

		private static void OnPiecesRegistered()
		{
			Plugin.LogDebug("[PieceManager] OnPiecesRegistered triggered. Updating piece recipes and stations.");
			UpdateAllPieceConfigurations();
		}

		public static void UpdateAllPieceConfigurations()
		{
			UpdatePieceConfiguration("piece_wisptorch_heeler_lg");
			UpdatePieceConfiguration("piece_wisplamp_heeler");
			UpdatePieceConfiguration("piece_wisplamp_heeler_lg");
			UpdatePieceConfiguration("piece_wisplamp_heeler_grand");
		}

		public static void UpdatePieceConfiguration(string prefabName)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: 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_0142: Expected O, but got Unknown
			Scene activeScene = SceneManager.GetActiveScene();
			if (((Scene)(ref activeScene)).name != "main")
			{
				string[] obj = new string[5] { "[PieceManager] Active scene is '", null, null, null, null };
				activeScene = SceneManager.GetActiveScene();
				obj[1] = ((Scene)(ref activeScene)).name;
				obj[2] = "'. Deferring piece update for '";
				obj[3] = prefabName;
				obj[4] = "' until game world loads.";
				Plugin.LogDebug(string.Concat(obj));
				return;
			}
			CustomPiece piece = PieceManager.Instance.GetPiece(prefabName);
			if (piece == null || (Object)(object)piece.PiecePrefab == (Object)null)
			{
				Plugin.LogDebug("[PieceManager] CustomPiece '" + prefabName + "' not found in PieceManager registry for config update.");
			}
			else
			{
				if (!TryGetPieceConfig(prefabName, out string recipeString, out string stationString, out float _, out float _, out float _, out float _))
				{
					return;
				}
				Piece component = piece.PiecePrefab.GetComponent<Piece>();
				if (TryParseAndValidateRecipe(recipeString, prefabName, out RequirementConfig[] requirements))
				{
					List<Requirement> list = new List<Requirement>();
					RequirementConfig[] array = requirements;
					foreach (RequirementConfig val in array)
					{
						GameObject prefab = PrefabManager.Instance.GetPrefab(val.Item);
						ItemDrop val2 = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<ItemDrop>() : null);
						if ((Object)(object)val2 != (Object)null)
						{
							list.Add(new Requirement
							{
								m_resItem = val2,
								m_amount = val.Amount,
								m_amountPerLevel = val.AmountPerLevel,
								m_recover = val.Recover
							});
						}
						else
						{
							Plugin.Log.LogError((object)("[PieceManager] Could not resolve ItemDrop for requirement '" + val.Item + "' on piece '" + prefabName + "'."));
						}
					}
					if ((Object)(object)component != (Object)null)
					{
						component.m_resources = list.ToArray();
					}
				}
				else
				{
					Plugin.Log.LogError((object)("[PieceManager] Rejecting recipe update for piece '" + prefabName + "' due to validation errors. Keeping existing recipe."));
				}
				if ((Object)(object)component != (Object)null)
				{
					string internalName = CraftingStations.GetInternalName(stationString);
					if (string.IsNullOrEmpty(internalName) || internalName.Equals("None", StringComparison.OrdinalIgnoreCase))
					{
						component.m_craftingStation = null;
					}
					else
					{
						GameObject prefab2 = PrefabManager.Instance.GetPrefab(internalName);
						if ((Object)(object)prefab2 != (Object)null)
						{
							component.m_craftingStation = prefab2.GetComponent<CraftingStation>();
						}
						else
						{
							Plugin.Log.LogWarning((object)("[PieceManager] Crafting station prefab '" + internalName + "' not found for piece '" + prefabName + "'."));
							component.m_craftingStation = null;
						}
					}
				}
				ApplyProperties(piece.PiecePrefab, prefabName);
				WispTorchColorController.RefreshPropertiesForPrefab(prefabName);
				if ((Object)(object)Player.m_localPlayer != (Object)null)
				{
					Player.m_localPlayer.UpdateKnownRecipesList();
					Player.m_localPlayer.UpdateAvailablePiecesList();
				}
				Plugin.LogDebug("[PieceManager] Updated '" + prefabName + "' configuration in real time.");
			}
		}

		public static bool TryGetPieceConfig(string prefabName, out string recipeString, out string stationString, out float health, out float mistClearRangeMultiplier, out float lightIntensityMultiplier, out float lightRangeMultiplier)
		{
			switch (prefabName)
			{
			case "piece_wisptorch_heeler_lg":
				recipeString = ModConfig.Torch_Recipe.Value;
				stationString = ModConfig.Torch_CraftingStation.Value;
				health = ModConfig.Torch_Health.Value;
				mistClearRangeMultiplier = ModConfig.Torch_MistClearRangeMultiplier.Value;
				lightIntensityMultiplier = ModConfig.Torch_LightIntensityMultiplier.Value;
				lightRangeMultiplier = ModConfig.Torch_LightRangeMultiplier.Value;
				return true;
			case "piece_wisplamp_heeler":
				recipeString = ModConfig.SmallLamp_Recipe.Value;
				stationString = ModConfig.SmallLamp_CraftingStation.Value;
				health = ModConfig.SmallLamp_Health.Value;
				mistClearRangeMultiplier = ModConfig.SmallLamp_MistClearRangeMultiplier.Value;
				lightIntensityMultiplier = ModConfig.SmallLamp_LightIntensityMultiplier.Value;
				lightRangeMultiplier = ModConfig.SmallLamp_LightRangeMultiplier.Value;
				return true;
			case "piece_wisplamp_heeler_lg":
				recipeString = ModConfig.LargeLamp_Recipe.Value;
				stationString = ModConfig.LargeLamp_CraftingStation.Value;
				health = ModConfig.LargeLamp_Health.Value;
				mistClearRangeMultiplier = ModConfig.LargeLamp_MistClearRangeMultiplier.Value;
				lightIntensityMultiplier = ModConfig.LargeLamp_LightIntensityMultiplier.Value;
				lightRangeMultiplier = ModConfig.LargeLamp_LightRangeMultiplier.Value;
				return true;
			case "piece_wisplamp_heeler_grand":
				recipeString = ModConfig.GrandLamp_Recipe.Value;
				stationString = ModConfig.GrandLamp_CraftingStation.Value;
				health = ModConfig.GrandLamp_Health.Value;
				mistClearRangeMultiplier = ModConfig.GrandLamp_MistClearRangeMultiplier.Value;
				lightIntensityMultiplier = ModConfig.GrandLamp_LightIntensityMultiplier.Value;
				lightRangeMultiplier = ModConfig.GrandLamp_LightRangeMultiplier.Value;
				return true;
			default:
				recipeString = string.Empty;
				stationString = string.Empty;
				health = 100f;
				mistClearRangeMultiplier = 1f;
				lightIntensityMultiplier = 1f;
				lightRangeMultiplier = 1f;
				return false;
			}
		}

		public static void ApplyProperties(GameObject targetGameObject, string prefabName)
		{
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)targetGameObject == (Object)null || !BaseStats.TryGetValue(prefabName, out PieceBaseStats value) || !TryGetPieceConfig(prefabName, out string _, out string _, out float health, out float mistClearRangeMultiplier, out float lightIntensityMultiplier, out float lightRangeMultiplier))
			{
				return;
			}
			ParticleSystemForceField[] componentsInChildren = targetGameObject.GetComponentsInChildren<ParticleSystemForceField>(true);
			for (int i = 0; i < componentsInChildren.Length && i < value.ForceFieldStartRanges.Length; i++)
			{
				componentsInChildren[i].startRange = value.ForceFieldStartRanges[i] * mistClearRangeMultiplier;
				componentsInChildren[i].endRange = value.ForceFieldEndRanges[i] * mistClearRangeMultiplier;
			}
			Light[] componentsInChildren2 = targetGameObject.GetComponentsInChildren<Light>(true);
			for (int j = 0; j < componentsInChildren2.Length && j < value.LightIntensities.Length; j++)
			{
				componentsInChildren2[j].intensity = value.LightIntensities[j] * lightIntensityMultiplier;
				componentsInChildren2[j].range = value.LightRanges[j] * lightRangeMultiplier;
			}
			WearNTear component = targetGameObject.GetComponent<WearNTear>();
			if ((Object)(object)component != (Object)null)
			{
				component.m_health = health;
			}
			Transform val = targetGameObject.transform.Find("PlayerBase");
			if ((Object)(object)val != (Object)null)
			{
				SphereCollider component2 = ((Component)val).GetComponent<SphereCollider>();
				if ((Object)(object)component2 != (Object)null)
				{
					float num = 24f * mistClearRangeMultiplier;
					float num2 = Mathf.Clamp01(ModConfig.PlayerBaseMistRadiusBonus.Value);
					float num3 = 20f + (num - 20f) * num2;
					Vector3 lossyScale = targetGameObject.transform.lossyScale;
					float num4 = Mathf.Max(Mathf.Abs(lossyScale.x), Mathf.Max(Mathf.Abs(lossyScale.y), Mathf.Abs(lossyScale.z)));
					component2.radius = ((num4 > 0.001f) ? (num3 / num4) : num3);
				}
			}
		}

		public static bool IsValidItemPrefab(string itemName)
		{
			if (string.IsNullOrWhiteSpace(itemName))
			{
				return false;
			}
			if (itemName.Equals("<PrefabName>", StringComparison.OrdinalIgnoreCase))
			{
				return false;
			}
			GameObject prefab = PrefabManager.Instance.GetPrefab(itemName);
			if ((Object)(object)prefab != (Object)null)
			{
				return (Object)(object)prefab.GetComponent<ItemDrop>() != (Object)null;
			}
			return false;
		}

		public static bool TryParseAndValidateRecipe(string recipeString, string pieceName, out RequirementConfig[] requirements)
		{
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Expected O, but got Unknown
			requirements = Array.Empty<RequirementConfig>();
			if (string.IsNullOrWhiteSpace(recipeString))
			{
				Plugin.Log.LogError((object)("[PieceManager] Recipe for piece '" + pieceName + "' is empty or whitespace."));
				return false;
			}
			string[] array = recipeString.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
			if (array.Length == 0)
			{
				Plugin.Log.LogError((object)("[PieceManager] Recipe for piece '" + pieceName + "' contains no valid tokens ('" + recipeString + "')."));
				return false;
			}
			List<RequirementConfig> list = new List<RequirementConfig>();
			string[] array2 = array;
			foreach (string text in array2)
			{
				string[] array3 = text.Trim().Split(new char[1] { ':' });
				if (array3.Length != 2)
				{
					Plugin.Log.LogError((object)("[PieceManager] Recipe for piece '" + pieceName + "' contains malformed token '" + text + "'. Expected 'ItemPrefab:Amount'."));
					return false;
				}
				string text2 = array3[0].Trim();
				if (string.IsNullOrEmpty(text2))
				{
					Plugin.Log.LogError((object)("[PieceManager] Recipe for piece '" + pieceName + "' contains an empty item prefab name in token '" + text + "'."));
					return false;
				}
				if (!int.TryParse(array3[1].Trim(), out var result) || result <= 0)
				{
					Plugin.Log.LogError((object)("[PieceManager] Recipe for piece '" + pieceName + "' contains invalid amount '" + array3[1] + "' in token '" + text + "'. Amount must be a positive integer."));
					return false;
				}
				if (!IsValidItemPrefab(text2))
				{
					Plugin.Log.LogError((object)("[PieceManager] Recipe for piece '" + pieceName + "' requires item '" + text2 + "' which does not exist in the game!"));
					return false;
				}
				list.Add(new RequirementConfig(text2, result, 0, true));
			}
			requirements = list.ToArray();
			return true;
		}

		private static void EnsurePieceCollider(GameObject targetGameObject, in Vector3 center, in Vector3 size)
		{
			//IL_0045: 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)
			if (!((Object)(object)targetGameObject == (Object)null))
			{
				BoxCollider val = targetGameObject.GetComponent<BoxCollider>();
				if ((Object)(object)val == (Object)null)
				{
					val = targetGameObject.AddComponent<BoxCollider>();
				}
				int num = LayerMask.NameToLayer("piece");
				if (num >= 0)
				{
					((Component)val).gameObject.layer = num;
				}
				((Collider)val).isTrigger = false;
				val.center = center;
				val.size = size;
			}
		}

		private static void EnsurePlayerBase(GameObject targetGameObject)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_0050: 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)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)targetGameObject == (Object)null))
			{
				Transform val = targetGameObject.transform.Find("PlayerBase");
				GameObject val2;
				if ((Object)(object)val != (Object)null)
				{
					val2 = ((Component)val).gameObject;
				}
				else
				{
					val2 = new GameObject("PlayerBase");
					val2.transform.SetParent(targetGameObject.transform, false);
					val2.transform.localPosition = Vector3.zero;
					val2.transform.localRotation = Quaternion.identity;
				}
				int num = LayerMask.NameToLayer("character_trigger");
				if (num >= 0)
				{
					val2.layer = num;
				}
				SphereCollider val3 = val2.GetComponent<SphereCollider>();
				if ((Object)(object)val3 == (Object)null)
				{
					val3 = val2.AddComponent<SphereCollider>();
				}
				((Collider)val3).isTrigger = true;
				val3.center = Vector3.zero;
				EffectArea val4 = val2.GetComponent<EffectArea>();
				if ((Object)(object)val4 == (Object)null)
				{
					val4 = val2.AddComponent<EffectArea>();
				}
				val4.m_type = (Type)4;
				Plugin.LogDebug($"[PieceManager] Configured PlayerBase on '{((Object)targetGameObject).name}' (layer: {val2.layer}).");
			}
		}
	}
}
namespace WispTorchHeeler.Patches
{
	public static class PiecePatches
	{
		[HarmonyPatch(typeof(Piece), "Awake")]
		public static class Piece_Awake_Patch
		{
			[HarmonyPostfix]
			public static void Postfix(Piece __instance)
			{
				if (ModConfig.EnableMod.Value && !((Object)(object)__instance == (Object)null) && !((Object)(object)((Component)__instance).gameObject == (Object)null))
				{
					string prefabName = Utils.GetPrefabName(((Component)__instance).gameObject);
					if (!(prefabName != "piece_groundtorch_mist") && (Object)(object)((Component)__instance).gameObject.GetComponent<WispTorchColorController>() == (Object)null)
					{
						((Component)__instance).gameObject.AddComponent<WispTorchColorController>();
						Plugin.LogDebug("[PiecePatch] Injected WispTorchColorController into spawned '" + prefabName + "'.");
					}
				}
			}
		}

		[HarmonyPatch(typeof(HoverText), "GetHoverText")]
		public static class HoverText_GetHoverText_Patch
		{
			[HarmonyPostfix]
			public static void Postfix(HoverText __instance, ref string __result)
			{
				//IL_0067: Unknown result type (might be due to invalid IL or missing references)
				//IL_006c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0081: Unknown result type (might be due to invalid IL or missing references)
				//IL_0086: Unknown result type (might be due to invalid IL or missing references)
				//IL_009b: Unknown result type (might be due to invalid IL or missing references)
				if (!ModConfig.EnableMod.Value || !ModConfig.AllowTorchPainting.Value || (Object)(object)__instance == (Object)null)
				{
					return;
				}
				WispTorchColorController wispTorchColorController = ((Component)__instance).GetComponentInParent<WispTorchColorController>() ?? ((Component)__instance).GetComponentInChildren<WispTorchColorController>();
				if (!((Object)(object)wispTorchColorController == (Object)null) && (!(Utils.GetPrefabName(((Component)wispTorchColorController).gameObject) == "piece_groundtorch_mist") || ModConfig.AffectNativeMistTorches.Value))
				{
					string text = ((object)ModConfig.PaintTorchHotkey.Value/*cast due to .constrained prefix*/).ToString();
					string text2 = ((object)ModConfig.ResetTorchHotkey.Value/*cast due to .constrained prefix*/).ToString();
					string text3 = ColorUtility.ToHtmlStringRGB(ModConfig.PainterColor.Value);
					string text4 = ModLocalization.Localize("$prompt_torch_paint");
					string text5 = ModLocalization.Localize("$prompt_torch_reset");
					if (string.IsNullOrEmpty(__result))
					{
						__result = ((Localization.instance != null) ? Localization.instance.Localize(__instance.m_text) : __instance.m_text);
					}
					__result = __result + "\n[<color=#" + text3 + "><b>" + text + "</b></color>] " + text4 + "   [<color=yellow><b>" + text2 + "</b></color>] " + text5;
				}
			}
		}
	}
}
namespace WispTorchHeeler.Painter
{
	public static class TorchPainter
	{
		private static int s_baseRaycastMask = -1;

		private static int GetBaseRaycastMask()
		{
			if (s_baseRaycastMask == -1)
			{
				s_baseRaycastMask = LayerMask.GetMask(new string[4] { "piece", "piece_nonsolid", "Default", "static_solid" });
			}
			return s_baseRaycastMask;
		}

		public static void TryPaintOrReset(bool isReset)
		{
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_021d: 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)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_030c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0311: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0336: Unknown result type (might be due to invalid IL or missing references)
			//IL_035e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0355: Unknown result type (might be due to invalid IL or missing references)
			//IL_0368: Unknown result type (might be due to invalid IL or missing references)
			if (!ModConfig.EnableMod.Value)
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			WispTorchColorController wispTorchColorController = null;
			if ((Object)(object)localPlayer.m_hovering != (Object)null)
			{
				wispTorchColorController = ResolveControllerFromObject(localPlayer.m_hovering);
				if ((Object)(object)wispTorchColorController != (Object)null)
				{
					Plugin.LogDebug("[TorchPainter] Targeted torch via native hover: '" + ((Object)((Component)wispTorchColorController).gameObject).name + "'.");
				}
			}
			if ((Object)(object)wispTorchColorController == (Object)null && (Object)(object)localPlayer.m_hoveringPiece != (Object)null)
			{
				wispTorchColorController = ResolveControllerFromObject(((Component)localPlayer.m_hoveringPiece).gameObject);
				if ((Object)(object)wispTorchColorController != (Object)null)
				{
					Plugin.LogDebug("[TorchPainter] Targeted torch via hovering piece: '" + ((Object)((Component)wispTorchColorController).gameObject).name + "'.");
				}
			}
			if ((Object)(object)wispTorchColorController == (Object)null)
			{
				float value = ModConfig.PainterRaycastDistance.Value;
				int layerMask = GetBaseRaycastMask() | localPlayer.m_interactMask;
				Camera val = (((Object)(object)GameCamera.instance != (Object)null && (Object)(object)GameCamera.instance.m_camera != (Object)null) ? GameCamera.instance.m_camera : (((Object)(object)Camera.main != (Object)null) ? Camera.main : (((Object)(object)GameCamera.instance != (Object)null) ? ((Component)GameCamera.instance).GetComponent<Camera>() : null)));
				if ((Object)(object)val != (Object)null)
				{
					wispTorchColorController = RaycastForController(new Ray(((Component)val).transform.position, ((Component)val).transform.forward), value, layerMask);
				}
				if ((Object)(object)wispTorchColorController == (Object)null)
				{
					wispTorchColorController = RaycastForController(new Ray(((Character)localPlayer).GetEyePoint(), ((Character)localPlayer).GetLookDir()), value, layerMask);
				}
			}
			if ((Object)(object)wispTorchColorController == (Object)null)
			{
				Plugin.LogDebug("[TorchPainter] No valid wisp torch/lamp targeted.");
				return;
			}
			if (Utils.GetPrefabName(((Component)wispTorchColorController).gameObject) == "piece_groundtorch_mist" && (ModConfig.AffectNativeMistTorches == null || !ModConfig.AffectNativeMistTorches.Value))
			{
				Plugin.LogDebug("[TorchPainter] Painting native mist torches is disabled in config.");
				return;
			}
			if (!ModConfig.AllowTorchPainting.Value)
			{
				Plugin.LogDebug("[TorchPainter] Painting is globally disabled by server policy.");
				if ((Object)(object)MessageHud.instance != (Object)null)
				{
					MessageHud.instance.ShowMessage((MessageType)2, ModLocalization.Localize("$msg_cantpaint_disabled"), 0, (Sprite)null, false, true);
				}
				return;
			}
			Vector3 position = ((Component)wispTorchColorController).transform.position;
			if (!ModConfig.AllowPaintingInProtectedWards.Value && !PrivateArea.CheckAccess(position, 0f, true, false))
			{
				bool flag = (ModConfig.ConfigSync != null && ((ConditionalConfigSync)ModConfig.ConfigSync).IsAdmin) || (SynchronizationManager.Instance != null && SynchronizationManager.Instance.PlayerIsAdmin);
				if (!(ModConfig.AdminBypassesWardCheck.Value && flag))
				{
					Plugin.LogDebug("[TorchPainter] Ward access denied. Painting blocked.");
					if ((Object)(object)MessageHud.instance != (Object)null)
					{
						MessageHud.instance.ShowMessage((MessageType)2, ModLocalization.Localize("$msg_cantpaint_warded"), 0, (Sprite)null, false, true);
					}
					return;
				}
				Plugin.LogDebug("[TorchPainter] Ward access denied, but player is admin and AdminBypassesWardCheck is enabled. Access granted.");
			}
			ZNetView component = ((Component)wispTorchColorController).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid())
			{
				Plugin.Log.LogWarning((object)"[TorchPainter] Target piece has no valid ZNetView.");
				return;
			}
			string text;
			string text2;
			if (isReset)
			{
				text = string.Empty;
				wispTorchColorController.RefreshColor();
				text2 = ModLocalization.Localize("$msg_torch_reset");
			}
			else
			{
				Color value2 = ModConfig.PainterColor.Value;
				bool flag2 = ModConfig.EnableAlphaCustomization != null && ModConfig.EnableAlphaCustomization.Value;
				value2.a = (flag2 ? Mathf.Clamp(value2.a, 0.15f, 1f) : 1f);
				text = (flag2 ? ColorUtility.ToHtmlStringRGBA(value2) : ColorUtility.ToHtmlStringRGB(value2));
				wispTorchColorController.ApplyColor(value2);
				text2 = ModLocalization.Localize("$msg_torch_painted", "#" + text);
			}
			component.ClaimOwnership();
			component.GetZDO().Set(WispTorchColorController.ColorKeyHash, text);
			component.InvokeRPC(ZNetView.Everybody, "WTH_SetColor", new object[1] { text });
			if (ModConfig.ShowPainterFeedback.Value && (Object)(object)MessageHud.instance != (Object)null)
			{
				MessageHud.instance.ShowMessage((MessageType)2, text2, 0, (Sprite)null, false, true);
			}
			PlayFeedbackEffect(position);
			Plugin.LogDebug(isReset ? ("[TorchPainter] Reset color on '" + ((Object)((Component)wispTorchColorController).gameObject).name + "'.") : ("[TorchPainter] Applied color #" + text + " to '" + ((Object)((Component)wispTorchColorController).gameObject).name + "'."));
		}

		private static WispTorchColorController? ResolveControllerFromObject(GameObject targetGameObject)
		{
			if ((Object)(object)targetGameObject == (Object)null)
			{
				return null;
			}
			return targetGameObject.GetComponent<WispTorchColorController>() ?? targetGameObject.GetComponentInParent<WispTorchColorController>() ?? targetGameObject.GetComponentInChildren<WispTorchColorController>();
		}

		private static WispTorchColorController? RaycastForController(Ray ray, float maxDistance, int layerMask)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			RaycastHit[] array = Physics.RaycastAll(ray, maxDistance, layerMask);
			if (array == null || array.Length == 0)
			{
				return null;
			}
			Array.Sort(array, (RaycastHit firstHit, RaycastHit secondHit) => ((RaycastHit)(ref firstHit)).distance.CompareTo(((RaycastHit)(ref secondHit)).distance));
			RaycastHit[] array2 = array;
			for (int num = 0; num < array2.Length; num++)
			{
				RaycastHit val = array2[num];
				if (!((Object)(object)((RaycastHit)(ref val)).collider == (Object)null))
				{
					WispTorchColorController wispTorchColorController = ResolveControllerFromObject(((Component)((RaycastHit)(ref val)).collider).gameObject);
					if ((Object)(object)wispTorchColorController != (Object)null)
					{
						Plugin.LogDebug($"[TorchPainter] Targeted torch via raycast ({((RaycastHit)(ref val)).distance:F1}m): '{((Object)((Component)wispTorchColorController).gameObject).name}'.");
						return wispTorchColorController;
					}
				}
			}
			return null;
		}

		private static void PlayFeedbackEffect(Vector3 position)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)ZNetScene.instance == (Object)null))
			{
				GameObject val = ZNetScene.instance.GetPrefab("sfx_wisp_spawn") ?? ZNetScene.instance.GetPrefab("vfx_wisp_spawn") ?? ZNetScene.instance.GetPrefab("sfx_build_hammer_metal");
				if ((Object)(object)val != (Object)null)
				{
					Object.Instantiate<GameObject>(val, position, Quaternion.identity);
				}
			}
		}
	}
}
namespace WispTorchHeeler.Localization
{
	public static class ModLocalization
	{
		public const string TokenPieceTorchLg = "$piece_wisptorch_heeler_lg";

		public const string TokenPieceTorchLgDesc = "$piece_wisptorch_heeler_lg_description";

		public const string TokenPieceSmallLamp = "$piece_wisplamp_heeler";

		public const string TokenPieceSmallLampDesc = "$piece_wisplamp_heeler_description";

		public const string TokenPieceLampLg = "$piece_wisplamp_heeler_lg";

		public const string TokenPieceLampLgDesc = "$piece_wisplamp_heeler_lg_description";

		public const string TokenPieceLampGrand = "$piece_wisplamp_heeler_grand";

		public const string TokenPieceLampGrandDesc = "$piece_wisplamp_heeler_grand_description";

		public const string TokenMsgPainted = "$msg_torch_painted";

		public const string TokenMsgReset = "$msg_torch_reset";

		public const string TokenMsgCantPaintWarded = "$msg_cantpaint_warded";

		public const string TokenMsgCantPaintDisabled = "$msg_cantpaint_disabled";

		public const string TokenPromptPaint = "$prompt_torch_paint";

		public const string TokenPromptReset = "$prompt_torch_reset";

		public static void Initialize()
		{
			CustomLocalization localization = LocalizationManager.Instance.GetLocalization();
			string text = "English";
			localization.AddTranslation(ref text, new Dictionary<string, string>
			{
				{ "$piece_wisptorch_heeler_lg", "Large Wisp Torch" },
				{ "$piece_wisptorch_heeler_lg_description", "A large wisp torch that clears mist across a wide area." },
				{ "$piece_wisplamp_heeler", "Dvergr Wisp Lamp" },
				{ "$piece_wisplamp_heeler_description", "A sturdy dwarven demister lamp that clears mist across a wide area." },
				{ "$piece_wisplamp_heeler_lg", "Large Dvergr Wisp Lamp" },
				{ "$piece_wisplamp_heeler_lg_description", "An advanced dwarven demister with an expanded core that clears mist across a wide radius." },
				{ "$piece_wisplamp_heeler_grand", "Grand Dvergr Wisp Lamp" },
				{ "$piece_wisplamp_heeler_grand_description", "A colossal, reinforced dwarven demister monument that clears mist across a vast perimeter." },
				{ "$msg_torch_painted", "Wisp piece painted: {0}" },
				{ "$msg_torch_reset", "Wisp piece color reset to default." },
				{ "$msg_cantpaint_warded", "Piece is protected by a ward." },
				{ "$msg_cantpaint_disabled", "Painting wisp pieces is disabled on this server." },
				{ "$prompt_torch_paint", "Paint Light" },
				{ "$prompt_torch_reset", "Reset Color" }
			});
			Plugin.LogDebug("[ModLocalization] Default English localizations registered.");
		}

		public static string Localize(string token, params string[] arguments)
		{
			string text = LocalizationManager.Instance.GetLocalization().TryTranslate(token);
			if (arguments != null && arguments.Length != 0)
			{
				text = string.Format(text, arguments);
			}
			return text;
		}
	}
}
namespace WispTorchHeeler.Lighting
{
	public class WispTorchColorController : MonoBehaviour, IPlaced
	{
		public static readonly int ColorKeyHash = StringExtensionMethods.GetStableHashCode("wisptorch_light_color");

		private static readonly int s_emissionColor = Shader.PropertyToID("_EmissionColor");

		private static readonly int s_color = Shader.PropertyToID("_Color");

		private static readonly int s_tintColor = Shader.PropertyToID("_TintColor");

		public static readonly Color NativeFallbackColor = new Color(0.706f, 0.941f, 1f, 1f);

		public const float MinimumAlphaFloor = 0.15f;

		private static readonly HashSet<string> s_targetedMaterialNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "demister_ball", "demister_ball_intense", "demister_ball_weak", "demister_ball_v_intense", "demister", "demister_sparcs", "wispysmoke", "slowwispysmoke" };

		public static readonly HashSet<WispTorchColorController> Instances = new HashSet<WispTorchColorController>();

		private ZNetView? _netView;

		private Light[] _lights = Array.Empty<Light>();

		private ParticleSystem[] _particleSystems = Array.Empty<ParticleSystem>();

		private Color[] _originalLightColors = Array.Empty<Color>();

		private MinMaxGradient[] _originalParticleGradients = Array.Empty<MinMaxGradient>();

		private Renderer[] _ballRenderers = Array.Empty<Renderer>();

		private Material[] _originalSharedMaterials = Array.Empty<Material>();

		private Color[] _originalEmissionColors = Array.Empty<Color>();

		private Color[] _originalAlbedoColors = Array.Empty<Color>();

		private Color[] _originalTintColors = Array.Empty<Color>();

		private CircleProjector? _circleProjector;

		private GameObject? _areaMarkerGameObject;

		private void Awake()
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: 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_0093: 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_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: 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)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Unknown result type (might be due to invalid IL or missing references)
			_netView = ((Component)this).GetComponent<ZNetView>();
			_lights = ((Component)this).GetComponentsInChildren<Light>(true);
			_particleSystems = ((Component)this).GetComponentsInChildren<ParticleSystem>(true);
			_originalLightColors = (Color[])(object)new Color[_lights.Length];
			for (int i = 0; i < _lights.Length; i++)
			{
				_originalLightColors[i] = _lights[i].color;
			}
			_originalParticleGradients = (MinMaxGradient[])(object)new MinMaxGradient[_particleSystems.Length];
			for (int j = 0; j < _particleSystems.Length; j++)
			{
				MinMaxGradient[] originalParticleGradients = _originalParticleGradients;
				int num = j;
				MainModule main = _particleSystems[j].main;
				originalParticleGradients[num] = ((MainModule)(ref main)).startColor;
			}
			List<Renderer> list = new List<Renderer>();
			Renderer[] componentsInChildren = ((Component)this).GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val.sharedMaterial == (Object)null))
				{
					string text = ((Object)val.sharedMaterial).name;
					int num2 = text.IndexOf(" (Instance)", StringComparison.OrdinalIgnoreCase);
					if (num2 >= 0)
					{
						text = text.Substring(0, num2);
					}
					if (s_targetedMaterialNames.Contains(text))
					{
						list.Add(val);
					}
				}
			}
			_ballRenderers = list.ToArray();
			_originalSharedMaterials = (Material[])(object)new Material[_ballRenderers.Length];
			_originalEmissionColors = (Color[])(object)new Color[_ballRenderers.Length];
			_originalAlbedoColors = (Color[])(object)new Color[_ballRenderers.Length];
			_originalTintColors = (Color[])(object)new Color[_ballRenderers.Length];
			for (int l = 0; l < _ballRenderers.Length; l++)
			{
				Material sharedMaterial = _ballRenderers[l].sharedMaterial;
				_originalSharedMaterials[l] = sharedMaterial;
				_originalEmissionColors[l] = (sharedMaterial.HasProperty(s_emissionColor) ? sharedMaterial.GetColor(s_emissionColor) : Color.white);
				_originalAlbedoColors[l] = (sharedMaterial.HasProperty(s_color) ? sharedMaterial.GetColor(s_color) : Color.white);
				_originalTintColors[l] = (sharedMaterial.HasProperty(s_tintColor) ? sharedMaterial.GetColor(s_tintColor) : Color.white);
			}
			if ((Object)(object)_netView != (Object)null)
			{
				_netView.Register<string>("WTH_SetColor", (Action<long, string>)RPC_SetColor);
			}
		}

		private void OnEnable()
		{
			Instances.Add(this);
			EnsureAreaMarker();
			RefreshColor();
			RefreshProperties();
		}

		private void Start()
		{
			if ((Object)(object)_netView != (Object)null && !_netView.IsValid())
			{
				((MonoBehaviour)this).StartCoroutine(WaitForZDOAndInit());
			}
		}

		private IEnumerator WaitForZDOAndInit()
		{
			int maxFrames = 30;
			while ((Object)(object)_netView != (Object)null && !_netView.IsValid() && maxFrames-- > 0)
			{
				yield return null;
			}
			if ((Object)(object)_netView != (Object)null && _netView.IsValid())
			{
				RefreshColor();
			}
		}

		public void OnPlaced()
		{
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			if (!ModConfig.EnableMod.Value || !ModConfig.AutoPaintOnPlacement.Value || !ModConfig.AllowTorchPainting.Value)
			{
				return;
			}
			string prefabName = Utils.GetPrefabName(((Component)this).gameObject);
			if (!(prefabName == "piece_groundtorch_mist") || (ModConfig.AffectNativeMistTorches != null && ModConfig.AffectNativeMistTorches.Value))
			{
				if ((Object)(object)_netView == (Object)null)
				{
					_netView = ((Component)this).GetComponent<ZNetView>();
				}
				if (!((Object)(object)_netView == (Object)null) && _netView.IsValid())
				{
					Color value = ModConfig.PainterColor.Value;
					bool flag = ModConfig.EnableAlphaCustomization != null && ModConfig.EnableAlphaCustomization.Value;
					value.a = (flag ? Mathf.Clamp(value.a, 0.15f, 1f) : 1f);
					string text = (flag ? ColorUtility.ToHtmlStringRGBA(value) : ColorUtility.ToHtmlStringRGB(value));
					_netView.ClaimOwnership();
					_netView.GetZDO().Set(ColorKeyHash, text);
					_netView.InvokeRPC(ZNetView.Everybody, "WTH_SetColor", new object[1] { text });
					ApplyColor(value);
					Plugin.LogDebug("[PiecePlacement] Auto-painted newly placed '" + prefabName + "' with color #" + text + ".");
				}
			}
		}

		private void OnDisable()
		{
			Instances.Remove(this);
		}

		private void OnDestroy()
		{
			Instances.Remove(this);
			for (int i = 0; i < _ballRenderers.Length; i++)
			{
				if ((Object)(object)_ballRenderers[i] != (Object)null && i < _originalSharedMaterials.Length)
				{
					Material sharedMaterial = _ballRenderers[i].sharedMaterial;
					if ((Object)(object)sharedMaterial != (Object)null && (Object)(object)sharedMaterial != (Object)(object)_originalSharedMaterials[i])
					{
						Object.Destroy((Object)(object)sharedMaterial, 10f);
					}
				}
			}
		}

		private void RPC_SetColor(long sender, string hexColor)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			Color color = default(Color);
			if (string.IsNullOrEmpty(hexColor) || !ColorUtility.TryParseHtmlString(hexColor.StartsWith("#") ? hexColor : ("#" + hexColor), ref color))
			{
				RefreshColor();
			}
			else
			{
				ApplyColor(color);
			}
		}

		public void RefreshColor()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			if (ModConfig.AffectNativeMistTorches != null && !ModConfig.AffectNativeMistTorches.Value && Utils.GetPrefabName(((Component)this).gameObject) == "piece_groundtorch_mist")
			{
				RestoreOriginalColors();
			}
			else
			{
				ApplyColor(ResolveColor());
			}
		}

		public void RestoreOriginalColors()
		{
			//IL_002e: 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)
			//IL_0073: 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)
			for (int i = 0; i < _lights.Length; i++)
			{
				if ((Object)(object)_lights[i] != (Object)null && i < _originalLightColors.Length)
				{
					_lights[i].color = _originalLightColors[i];
				}
			}
			for (int j = 0; j < _particleSystems.Length; j++)
			{
				if ((Object)(object)_particleSystems[j] != (Object)null && j < _originalParticleGradients.Length)
				{
					MainModule main = _particleSystems[j].main;
					((MainModule)(ref main)).startColor = _originalParticleGradients[j];
				}
			}
			for (int k = 0; k < _ballRenderers.Length; k++)
			{
				if ((Object)(object)_ballRenderers[k] != (Object)null && k < _originalSharedMaterials.Length && (Object)(object)_ballRenderers[k].sharedMaterial != (Object)(object)_originalSharedMaterials[k])
				{
					Object.Destroy((Object)(object)_ballRenderers[k].sharedMaterial);
					_ballRenderers[k].sharedMaterial = _originalSharedMaterials[k];
				}
			}
		}

		public Color ResolveColor()
		{
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_netView != (Object)null && _netView.IsValid())
			{
				string text = _netView.GetZDO().GetString(ColorKeyHash, string.Empty);
				Color result = default(Color);
				if (!string.IsNullOrEmpty(text) && ColorUtility.TryParseHtmlString(text.StartsWith("#") ? text : ("#" + text), ref result))
				{
					return result;
				}
			}
			if (ModConfig.EnforceServerDefaultColor != null && ModConfig.EnforceServerDefaultColor.Value)
			{
				if (ModConfig.ServerDefaultLightColor == null)
				{
					return NativeFallbackColor;
				}
				return ModConfig.ServerDefaultLightColor.Value;
			}
			if (ModConfig.DefaultLightColor != null)
			{
				return ModConfig.DefaultLightColor.Value;
			}
			return NativeFallbackColor;
		}

		public void ApplyColor(Color color)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: 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_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: 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_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < _lights.Length; i++)
			{
				if ((Object)(object)_lights[i] != (Object)null)
				{
					_lights[i].color = color;
				}
			}
			float alphaMultiplier = ((ModConfig.EnableAlphaCustomization != null && ModConfig.EnableAlphaCustomization.Value) ? Mathf.Clamp(color.a, 0.15f, 1f) : 1f);
			for (int j = 0; j < _particleSystems.Length; j++)
			{
				if ((Object)(object)_particleSystems[j] != (Object)null && j < _originalParticleGradients.Length)
				{
					MainModule main = _particleSystems[j].main;
					((MainModule)(ref main)).startColor = TintMinMaxGradient(in _originalParticleGradients[j], color, alphaMultiplier);
				}
			}
			for (int k = 0; k < _ballRenderers.Length; k++)
			{
				Renderer val = _ballRenderers[k];
				if (!((Object)(object)val == (Object)null))
				{
					Material material = val.material;
					if (!((Object)(object)material == (Object)null))
					{
						TintMaterialProperty(material, s_emissionColor, in _originalEmissionColors[k], color, 1f);
						TintMaterialProperty(material, s_color, in _originalAlbedoColors[k], color, alphaMultiplier);
						TintMaterialProperty(material, s_tintColor, in _originalTintColors[k], color, alphaMultiplier);
					}
				}
			}
		}

		private static void TintMaterialProperty(Material material, int propertyId, in Color originalColor, Color targetColor, float alphaMultiplier)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: 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)
			if (material.HasProperty(propertyId))
			{
				float num = Mathf.Max(originalColor.r, Mathf.Max(originalColor.g, originalColor.b));
				material.SetColor(propertyId, new Color(targetColor.r * num, targetColor.g * num, targetColor.b * num, originalColor.a * alphaMultiplier));
			}
		}

		private static MinMaxGradient TintMinMaxGradient(in MinMaxGradient originalGradient, Color targetColor, float alphaMultiplier)
		{
			//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_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected I4, but got Unknown
			//IL_002a: 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_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: 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)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: 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_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: 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_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			MinMaxGradient val = originalGradient;
			ParticleSystemGradientMode mode = ((MinMaxGradient)(ref val)).mode;
			switch ((int)mode)
			{
			case 0:
			{
				float r3 = targetColor.r;
				float g3 = targetColor.g;
				float b3 = targetColor.b;
				val = originalGradient;
				return MinMaxGradient.op_Implicit(new Color(r3, g3, b3, ((MinMaxGradient)(ref val)).color.a * alphaMultiplier));
			}
			case 2:
			{
				float r = targetColor.r;
				float g = targetColor.g;
				float b = targetColor.b;
				val = originalGradient;
				Color val2 = new Color(r, g, b, ((MinMaxGradient)(ref val)).colorMin.a * alphaMultiplier);
				float r2 = targetColor.r;
				float g2 = targetColor.g;
				float b2 = targetColor.b;
				val = originalGradient;
				return new MinMaxGradient(val2, new Color(r2, g2, b2, ((MinMaxGradient)(ref val)).colorMax.a * alphaMultiplier));
			}
			case 1:
				val = originalGradient;
				return MinMaxGradient.op_Implicit(TintGradient(((MinMaxGradient)(ref val)).gradient, targetColor, alphaMultiplier));
			case 3:
			{
				val = originalGradient;
				Gradient obj = TintGradient(((MinMaxGradient)(ref val)).gradientMin, targetColor, alphaMultiplier);
				val = originalGradient;
				return new MinMaxGradient(obj, TintGradient(((MinMaxGradient)(ref val)).gradientMax, targetColor, alphaMultiplier));
			}
			default:
				return originalGradient;
			}
		}

		private static Gradient TintGradient(Gradient? sourceGradient, Color targetColor, float alphaMultiplier)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Expected O, but got Unknown
			//IL_001f: 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_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Expected O, but got Unknown
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			if (sourceGradient != null)
			{
				GradientColorKey[] colorKeys = sourceGradient.colorKeys;
				GradientColorKey[] array = (GradientColorKey[])(object)new GradientColorKey[colorKeys.Length];
				for (int i = 0; i < colorKeys.Length; i++)
				{
					array[i] = new GradientColorKey(new Color(targetColor.r, targetColor.g, targetColor.b), colorKeys[i].time);
				}
				GradientAlphaKey[] array2;
				if (alphaMultiplier < 0.999f)
				{
					GradientAlphaKey[] alphaKeys = sourceGradient.alphaKeys;
					array2 = (GradientAlphaKey[])(object)new GradientAlphaKey[alphaKeys.Length];
					for (int j = 0; j < alphaKeys.Length; j++)
					{
						array2[j] = new GradientAlphaKey(alphaKeys[j].alpha * alphaMultiplier, alphaKeys[j].time);
					}
				}
				else
				{
					array2 = sourceGradient.alphaKeys;
				}
				Gradient val = new Gradient();
				val.SetKeys(array, array2);
				return val;
			}
			return new Gradient();
		}

		public void RefreshProperties()
		{
			string prefabName = Utils.GetPrefabName(((Component)this).gameObject);
			WispPieceManager.ApplyProperties(((Component)this).gameObject, prefabName);
			UpdateAreaMarkerRadius();
		}

		public float GetMistSuppressionRadius()
		{
			ParticleSystemForceField componentInChildren = ((Component)this).GetComponentInChildren<ParticleSystemForceField>(true);
			if ((Object)(object)componentInChildren != (Object)null && componentInChildren.endRange > 0f)
			{
				return componentInChildren.endRange;
			}
			return 0f;
		}

		public void EnsureAreaMarker()
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Expected O, but got Unknown
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_areaMarkerGameObject != (Object)null)
			{
				return;
			}
			GameObject areaMarkerTemplate = WispPieceManager.AreaMarkerTemplate;
			if (!((Object)(object)areaMarkerTemplate == (Object)null))
			{
				CircleProjector val = areaMarkerTemplate.GetComponent<CircleProjector>() ?? areaMarkerTemplate.GetComponentInChildren<CircleProjector>();
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val.m_prefab == (Object)null))
				{
					_areaMarkerGameObject = new GameObject("_MistSuppressionMarker");
					_areaMarkerGameObject.transform.SetParent(((Component)this).transform, false);
					_areaMarkerGameObject.transform.localPosition = Vector3.zero;
					_areaMarkerGameObject.transform.localRotation = Quaternion.identity;
					_circleProjector = _areaMarkerGameObject.AddComponent<CircleProjector>();
					_circleProjector.m_prefab = val.m_prefab;
					_circleProjector.m_mask = val.m_mask;
					_circleProjector.m_speed = val.m_speed;
					_circleProjector.m_turns = 1f;
					UpdateAreaMarkerRadius();
				}
			}
		}

		public void UpdateAreaMarkerRadius()
		{
			if ((Object)(object)_circleProjector == (Object)null)
			{
				return;
			}
			float mistSuppressionRadius = GetMistSuppressionRadius();
			if (mistSuppressionRadius <= 0f)
			{
				GameObject? areaMarkerGameObject = _areaMarkerGameObject;
				if (areaMarkerGameObject != null)
				{
					areaMarkerGameObject.SetActive(false);
				}
			}
			else
			{
				_circleProjector.m_radius = mistSuppressionRadius;
				_circleProjector.m_nrOfSegments = Mathf.Clamp(Mathf.RoundToInt(mistSuppressionRadius * 5f), 24, 250);
				_circleProjector.CreateSegments();
				RefreshMarkerVisibility();
			}
		}

		public void RefreshMarkerVisibility()
		{
			if ((Object)(object)_areaMarkerGameObject != (Object)null)
			{
				bool active = ModConfig.ShowMistSuppressionRadius != null && ModConfig.ShowMistSuppressionRadius.Value && GetMistSuppressionRadius() > 0f;
				_areaMarkerGameObject.SetActive(active);
			}
		}

		public static void RefreshAllMarkers()
		{
			foreach (WispTorchColorController instance in Instances)
			{
				if ((Object)(object)instance != (Object)null)
				{
					instance.EnsureAreaMarker();
					instance.RefreshMarkerVisibility();
				}
			}
		}

		public static void RefreshPropertiesForPrefab(string prefabName)
		{
			foreach (WispTorchColorController instance in Instances)
			{
				if ((Object)(object)instance != (Object)null && Utils.GetPrefabName(((Component)instance).gameObject) == prefabName)
				{
					instance.RefreshProperties();
				}
			}
		}

		public static void RefreshAll()
		{
			foreach (WispTorchColorController instance in Instances)
			{
				if ((Object)(object)instance != (Object)null)
				{
					instance.RefreshColor();
					instance.RefreshProperties();
				}
			}
		}
	}
}
namespace WispTorchHeeler.Configuration
{
	public class ConfigurationManagerAttributes
	{
		public Action<ConfigEntryBase>? CustomDrawer;

		public bool? Browsable;

		public bool? ReadOnly;

		public string? Category;

		public int? Order;
	}
	public static class ModConfig
	{
		public static ConfigSync ConfigSync = null;

		public static ConfigEntry<bool> EnableMod = null;

		public static ConfigEntry<bool> AffectNativeMistTorches = null;

		public static ConfigEntry<float> PlayerBaseMistRadiusBonus = null;

		public static ConfigEntry<float> Torch_MistClearRangeMultiplier = null;

		public static ConfigEntry<float> Torch_LightIntensityMultiplier = null;

		public static ConfigEntry<float> Torch_LightRangeMultiplier = null;

		public static ConfigEntry<float> Torch_Health = null;

		public static ConfigEntry<string> Torch_CraftingStation = null;

		public static ConfigEntry<string> Torch_Recipe = null;

		public static ConfigEntry<float> SmallLamp_MistClearRangeMultiplier = null;

		public static ConfigEntry<float> SmallLamp_LightIntensityMultiplier = null;

		public static ConfigEntry<float> SmallLamp_LightRangeMultiplier = null;

		public static ConfigEntry<float> SmallLamp_Health = null;

		public static ConfigEntry<string> SmallLamp_CraftingStation = null;

		public static ConfigEntry<string> SmallLamp_Recipe = null;

		public static ConfigEntry<float> LargeLamp_MistClearRangeMultiplier = null;

		public static ConfigEntry<float> LargeLamp_LightIntensityMultiplier = null;

		public static ConfigEntry<float> LargeLamp_LightRangeMultiplier = null;

		public static ConfigEntry<float> LargeLamp_Health = null;

		public static ConfigEntry<string> LargeLamp_CraftingStation = null;

		public static ConfigEntry<string> LargeLamp_Recipe = null;

		public static ConfigEntry<float> GrandLamp_MistClearRangeMultiplier = null;

		public static ConfigEntry<float> GrandLamp_LightIntensityMultiplier = null;

		public static ConfigEntry<float> GrandLamp_LightRangeMultiplier = null;

		public static ConfigEntry<float> GrandLamp_Health = null;

		public static ConfigEntry<string> GrandLamp_CraftingStation = null;

		public static ConfigEntry<string> GrandLamp_Recipe = null;

		public static ConfigEntry<bool> EnforceServerDefaultColor = null;

		public static ConfigEntry<Color> ServerDefaultLightColor = null;

		public static ConfigEntry<bool> AllowTorchPainting = null;

		public static ConfigEntry<bool> AllowPaintingInProtectedWards = null;

		public static ConfigEntry<bool> AdminBypassesWardCheck = null;

		public static ConfigEntry<bool> EnableAlphaCustomization = null;

		public static ConfigEntry<Color> DefaultLightColor = null;

		public static ConfigEntry<Color> PainterColor = null;

		public static ConfigEntry<KeyboardShortcut> PaintTorchHotkey = null;

		public static ConfigEntry<KeyboardShortcut> ResetTorchHotkey = null;

		public static ButtonConfig? ButtonPaintConfig;

		public static ButtonConfig? ButtonResetConfig;

		public static ConfigEntry<float> PainterRaycastDistance = null;

		public static ConfigEntry<bool> ShowPainterFeedback = null;

		public static ConfigEntry<bool> AutoPaintOnPlacement = null;

		public static ConfigEntry<bool> EnableDebugLogs = null;

		public static ConfigEntry<bool> ShowMistSuppressionRadius = null;

		private static readonly Color s_defaultCyan = new Color(0.706f, 0.941f, 1f, 1f);

		private static readonly Color s_defaultOrange = new Color(1f, 0.533f, 0f, 1f);

		public const string ButtonPaint = "WTH_Paint";

		public const string ButtonReset = "WTH_Reset";

		public static void Initialize(ConfigFile config)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: 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_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			//IL_0528: Unknown result type (might be due to invalid IL or missing references)
			//IL_05bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_05de: Unknown result type (might be due to invalid IL or missing references)
			//IL_0606: Unknown result type (might be due to invalid IL or missing references)
			//IL_0637: Unknown result type (might be due to invalid IL or missing references)
			ConfigSync = new ConfigSync("dreamwraith.WispTorchHeeler")
			{
				DisplayName = "WispTorchHeeler",
				CurrentVersion = "1.1.0",
				MinimumRequiredVersion = "1.1.0",
				ModRequired = true
			};
			EnableMod = BindSynced(config, "1 - General", "EnableMod (Requires Restart)", defaultValue: true, "Master switch to enable or disable the functionality of this mod. (Requires Restart)");
			AffectNativeMistTorches = BindSynced(config, "1 - General", "AffectNativeMistTorches", defaultValue: true, "Allows painting and color defaults on standard native wisp torches.");
			PlayerBaseMistRadiusBonus = BindSynced(config, "1 - General", "PlayerBaseMistRadiusBonus", 0f, "Additive bonus percentage (0.0 to 1.0) scaling PlayerBase spawn suppression from a baseline of 20.0m toward active mist clearance radius. At 0.0, all custom pieces use the 20.0m baseline. At 1.0, the suppression radius matches the active mist reveal boundary. Note: higher values reduce native spawn balance in favor of mist sanctuary.", (AcceptableValueBase?)(object)new AcceptableValueRange<float>(0f, 1f));
			Torch_MistClearRangeMultiplier = BindSynced(config, "2 - Large Torch", "Torch_MistClearRangeMultiplier", 1.5f, "Large torch mist clearance radius multiplier (relative to 24.0m baseline, range: 1.0 - 10.0).", (AcceptableValueBase?)(object)new AcceptableValueRange<float>(1f, 10f));
			Torch_LightIntensityMultiplier = BindSynced(config, "2 - Large Torch", "Torch_LightIntensityMultiplier", 1.33f, "Large torch light emission intensity multiplier (relative to 1.0 baseline, range: 0.5 - 5.0).", (AcceptableValueBase?)(object)new AcceptableValueRange<float>(0.5f, 5f));
			Torch_LightRangeMultiplier = BindSynced(config, "2 - Large Torch", "Torch_LightRangeMultiplier", 1.25f, "Large torch light emission range radius multiplier (relative to 10.0m baseline, range: 0.5 - 5.0).", (AcceptableValueBase?)(object)new AcceptableValueRange<float>(0.5f, 5f));
			Torch_Health = BindSynced(config, "2 - Large Torch", "Torch_Health", 200f, "Large torch structural health points (1.0 - 5000.0).", (AcceptableValueBase?)(object)new AcceptableValueRange<float>(1f, 5000f));
			Torch_CraftingStation = BindSynced(config, "2 - Large Torch", "Torch_CraftingStation", "", "Required station formatted as StationPrefab (e.g. piece_workbench, piece_forge, or \"\" for freeform hammer placement).");
			Torch_Recipe = BindSynced(config, "2 - Large Torch", "Torch_Recipe", "Wisp:8,YggdrasilWood:5,Sap:1", "Crafting recipe string formatted as ItemPrefab:Amount,... parsed against ObjectDB.", null, RecipeConfigDrawer.Draw);
			SmallLamp_MistClearRangeMultiplier = BindSynced(config, "3 - Small Lamp", "SmallLamp_MistClearRangeMultiplier", 2.25f, "Tier 2 small lamp mist clearance radius multiplier (relative to 24.0m baseline, range: 1.0 - 10.0).", (AcceptableValueBase?)(object)new AcceptableValueRange<float>(1f, 10f));
			SmallLamp_LightIntensityMultiplier = BindSynced(config, "3 - Small Lamp", "SmallLamp_LightIntensityMultiplier", 1.5f, "Tier 2 small lamp light emission intensity multiplier (relative to 1.0 baseline, range: 0.5 - 5.0).", (AcceptableValueBase?)(object)new AcceptableValueRange<float>(0.5f, 5f));
			SmallLamp_LightRangeMultiplier = BindSynced(config, "3 - Small Lamp", "SmallLamp_LightRangeMultiplier", 1.5f, "Tier 2 small lamp light emission range radius multiplier (relative to 10.0m baseline, range: 0.5 - 5.0).", (AcceptableValueBase?)(object)new AcceptableValueRange<float>(0.5f, 5f));
			SmallLamp_Health = BindSynced(config, "3 - Small Lamp", "SmallLamp_Health", 250f, "Tier 2 small lamp structural health points (1.0 - 5000.0).", (AcceptableValueBase?)(object)new AcceptableValueRange<float>(1f, 5000f));
			SmallLamp_CraftingStation = BindSynced(config, "3 - Small Lamp", "SmallLamp_CraftingStation", "forge", "Required station formatted as StationPrefab or Jotunn name (defaults to 'forge').");
			SmallLamp_Recipe = BindSynced(config, "3 - Small Lamp", "SmallLamp_Recipe", "Wisp:15,Copper:5,Iron:2,BlackMarble:2,Sap:2", "Crafting recipe string formatted as ItemPrefab:Amount,... parsed against ObjectDB.", null, RecipeConfigDrawer.Draw);
			LargeLamp_MistClearRangeMultiplier = BindSynced(config, "4 - Large Lamp", "LargeLamp_MistClearRangeMultiplier", 3f, "Tier 3 lamp mist clearance radius multiplier (relative to 24.0m baseline, range: 1.0 - 15.0).", (AcceptableValueBase?)(object)new AcceptableValueRange<float>(1f, 15f));
			LargeLamp_LightIntensityMultiplier = BindSynced(config, "4 - Large Lamp", "LargeLamp_LightIntensityMultiplier", 2.25f, "Tier 3 lamp light emission intensity multiplier (relative to 1.0 baseline, range: 0.5 - 8.0).", (AcceptableValueBase?)(object)new AcceptableValueRange<float>(0.5f, 8f));
			LargeLamp_LightRangeMultiplier = BindSynced(config, "4 - Large Lamp", "LargeLamp_LightRangeMultiplier", 1.75f, "Tier 3 lamp light emission range radius multiplier (relative to 10.0m baseline, range: 0.5 - 5.0).", (AcceptableValueBase?)(object)new AcceptableValueRange<float>(0.5f, 5f));
			LargeLamp_Health = BindSynced(config, "4 - Large Lamp", "LargeLamp_Health", 500f, "Tier 3 lamp structural health points (1.0 - 5000.0).", (AcceptableValueBase?)(object)new AcceptableValueRange<float>(1f, 5000f));
			LargeLamp_CraftingStation = BindSynced(config, "4 - Large Lamp", "LargeLamp_CraftingStation", "blackforge", "Required station formatted as StationPrefab or Jotunn name (defaults to 'blackforge').");
			LargeLamp_Recipe = BindSynced(config, "4 - Large Lamp", "LargeLamp_Recipe", "Wisp:22,Copper:8,Iron:3,Eitr:2,BlackMarble:5", "Crafting recipe string formatted as ItemPrefab:Amount,... parsed against ObjectDB.", null, RecipeConfigDrawer.Draw);
			GrandLamp_MistClearRangeMultiplier = BindSynced(config, "5 - Grand Lamp", "GrandLamp_MistClearRangeMultiplier", 3.75f, "Tier 4 grand lamp mist clearance radius multiplier (relative to 24.0m baseline, range: 1.0 - 15.0).", (AcceptableValueBase?)(object)new AcceptableValueRange<float>(1f, 15f));
			GrandLamp_LightIntensityMultiplier = BindSynced(config, "5 - Grand Lamp", "GrandLamp_LightIntensityMultiplier", 2.5f, "Tier 4 grand lamp light emission intensity multiplier (relative to 1.0 baseline, range: 0.5 - 8.0).", (AcceptableValueBase?)(object)new AcceptableValueRange<float>(0.5f, 8f));
			GrandLamp_LightRangeMultiplier = BindSynced(config, "5 - Grand Lamp", "GrandLamp_LightRangeMultiplier", 2f, "Tier 4 grand lamp light emission range radius multiplier (relative to 10.0m baseline, range: 0.5 - 8.0).", (AcceptableValueBase?)(object)new AcceptableValueRange<float>(0.5f, 8f));
			GrandLamp_Health = BindSynced(config, "5 - Grand Lamp", "GrandLamp_Health", 750f, "Tier 4 grand lamp structural health points (1.0 - 5000.0).", (AcceptableValueBase?)(object)new AcceptableValueRange<float>(1f, 5000f));
			GrandLamp_CraftingStation = BindSynced(config, "5 - Grand Lamp", "GrandLamp_CraftingStation", "blackforge", "Required station formatted as StationPrefab or Jotunn name (defaults to 'blackforge').");
			GrandLamp_Recipe = BindSynced(config, "5 - Grand Lamp", "GrandLamp_Recipe", "Wisp:30,Copper:10,Iron:4,Eitr:4,BlackMarble:10", "Crafting recipe string formatted as ItemPrefab:Amount,... parsed against ObjectDB.", null, RecipeConfigDrawer.Draw);
			EnforceServerDefaultColor = BindSynced(config, "6 - Lighting Policy", "EnforceServerDefaultColor", defaultValue: false, "If true, all clients must render unpainted pieces with the server's default color.");
			ServerDefaultLightColor = BindSynced<Color>(config, "6 - Lighting Policy", "ServerDefaultLightColor", s_defaultCyan, "Server-wide default color for unpainted pieces when enforced.");
			AllowTorchPainting = BindSynced(config, "6 - Lighting Policy", "AllowTorchPainting", defaultValue: true, "Server master toggle allowing players to paint individual pieces.");
			AllowPaintingInProtectedWards = BindSynced(config, "6 - Lighting Policy", "AllowPaintingInProtectedWards", defaultValue: false, "If false, players cannot paint pieces inside wards they lack access to.");
			AdminBypassesWardCheck = BindSynced(config, "6 - Lighting Policy", "AdminBypassesWardCheck", defaultValue: true, "If true, verified server admins bypass ward restrictions when painting.");
			EnableAlphaCustomization = BindSynced(config, "6 - Lighting Policy", "EnableAlphaCustomization", defaultValue: false, "Allows customizing light and particle transparency using the alpha slider in the color picker. When disabled, native opacity is strictly preserved. Alpha is safely clamped to a minimum of 15% to prevent pieces from becoming invisible.");
			DefaultLightColor = BindClient<Color>(config, "7 - Client Lighting", "DefaultLightColor", s_defaultCyan, "Client's personal default color for unpainted pieces (active when server does not enforce).");
			PainterColor = BindClient<Color>(config, "8 - Torch Painter", "PainterColor", s_defaultOrange, "Active paint color selected by player via UI color picker drawer.");
			PaintTorchHotkey = BindClient<KeyboardShortcut>(config, "8 - Torch Painter", "PaintTorchHotkey", new KeyboardShortcut((KeyCode)112, Array.Empty<KeyCode>()), "Hotkey pressed while aiming at a torch/lamp to apply PainterColor.");
			ResetTorchHotkey = BindClient<KeyboardShortcut>(config, "8 - Torch Painter", "ResetTorchHotkey", new KeyboardShortcut((KeyCode)112, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Hotkey pressed while aiming at a torch/lamp to clear custom color.");
			PainterRaycastDistance = BindClient(config, "8 - Torch Painter", "PainterRaycastDistance", 10f, "Maximum distance in meters to aim and paint a piece (2.0 - 25.0).", (AcceptableValueBase?)(object)new AcceptableValueRange<float>(2f, 25f));
			ShowPainterFeedback = BindClient(config, "8 - Torch Painter", "ShowPainterFeedback", defaultValue: true, "Shows on-screen HUD text confirmations upon painting/resetting.");
			AutoPaintOnPlacement = BindClient(config, "8 - Torch Painter", "AutoPaintOnPlacement", defaultValue: false, "If true, newly placed torches and lamps are automatically painted with your active PainterColor upon placement.");
			RegisterInputButtons();
			EnableDebugLogs = BindClient(config, "9 - Debug", "EnableDebugLogs", defaultValue: false, "Enables verbose diagnostic logging in the BepInEx console.");
			ShowMistSuppressionRadius = BindClient(config, "9 - Debug", "ShowMistSuppressionRadius", defaultValue: false, "Projects a ground boundary ring around wisp torches and lamps showing their active mist suppression radius.");
			Plugin.LogDebug("Configuration initialized and bound.");
		}

		private static void RegisterInputButtons()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Expected O, but got Unknown
			try
			{
				ButtonPaintConfig = new ButtonConfig
				{
					Name = "WTH_Paint",
					ShortcutConfig = PaintTorchHotkey,
					ActiveInGUI = false,
					HintToken = "$prompt_torch_paint"
				};
				InputManager.Instance.AddButton("dreamwraith.WispTorchHeeler", ButtonPaintConfig);
				ButtonResetConfig = new ButtonConfig
				{
					Name = "WTH_Reset",
					ShortcutConfig = ResetTorchHotkey,
					ActiveInGUI = false,
					HintToken = "$prompt_torch_reset"
				};
				InputManager.Instance.AddButton("dreamwraith.WispTorchHeeler", ButtonResetConfig);
				Plugin.LogDebug("[ModConfig] Registered input buttons 'WTH_Paint' and 'WTH_Reset' via Jotunn InputManager.");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[ModConfig] Failed to register Jotunn input buttons: " + ex.Message));
			}
		}

		private static ConfigEntry<T> BindSynced<T>(ConfigFile config, string section, string key, T defaultValue, string description, AcceptableValueBase? acceptableValues = null, Action<ConfigEntryBase>? customDrawer = null)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			ConfigDescription val = ((customDrawer != null) ? new ConfigDescription(description, acceptableValues, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					CustomDrawer = customDrawer
				}
			}) : new ConfigDescription(description, acceptableValues, Array.Empty<object>()));
			ConfigEntry<T> val2 = config.Bind<T>(section, key, defaultValue, val);
			((ConditionalConfigSync)ConfigSync).AddConfigEntry<T>(val2);
			return val2;
		}

		private static ConfigEntry<T> BindClient<T>(ConfigFile config, string section, string key, T defaultValue, string description, AcceptableValueBase? acceptableValues = null, Action<ConfigEntryBase>? customDrawer = null)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			ConfigDescription val = ((customDrawer != null) ? new ConfigDescription(description, acceptableValues, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					CustomDrawer = customDrawer
				}
			}) : new ConfigDescription(description, acceptableValues, Array.Empty<object>()));
			return config.Bind<T>(section, key, defaultValue, val);
		}
	}
	public static class RecipeConfigDrawer
	{
		public record struct RecipeItemEntry(string PrefabName, int Amount);

		public const string DefaultPlaceholderPrefab = "<PrefabName>";

		private const char ItemSeparator = ',';

		private const char AmountSeparator = ':';

		private static readonly GUILayoutOption s_amountWidth = GUILayout.Width(40f);

		private static readonly GUILayoutOption s_buttonWidth = GUILayout.Width(24f);

		public static void Draw(ConfigEntryBase entry)
		{
			if (entry == null)
			{
				return;
			}
			List<RecipeItemEntry> list = Deserialize((entry.BoxedValue as string) ?? string.Empty);
			bool flag = false;
			List<RecipeItemEntry> list2 = new List<RecipeItemEntry>();
			GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
			if (list.Count == 0)
			{
				if (GUILayout.Button("+ Add Requirement", Array.Empty<GUILayoutOption>()))
				{
					list2.Add(new RecipeItemEntry("<PrefabName>", 1));
					flag = true;
				}
			}
			else
			{
				for (int i = 0; i < list.Count; i++)
				{
					RecipeItemEntry item = list[i];
					GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
					string text = GUILayout.TextField(item.PrefabName ?? string.Empty, (GUILayoutOption[])(object)new GUILayoutOption[2]
					{
						GUILayout.ExpandWidth(true),
						GUILayout.MinWidth(60f)
					});
					if (text != item.PrefabName)
					{
						item.PrefabName = text;
						flag = true;
					}
					if (int.TryParse(GUILayout.TextField(item.Amount.ToString(), (GUILayoutOption[])(object)new GUILayoutOption[1] { s_amountWidth }), out var result) && result != item.Amount)
					{
						item.Amount = result;
						flag = true;
					}
					if (GUILayout.Button("-", (GUILayoutOption[])(object)new GUILayoutOption[1] { s_buttonWidth }))
					{
						flag = true;
					}
					else
					{
						list2.Add(item);
					}
					if (GUILayout.Button("+", (GUILayoutOption[])(object)new GUILayoutOption[1] { s_buttonWidth }))
					{
						list2.Add(new RecipeItemEntry("<PrefabName>", 1));
						flag = true;
					}
					GUILayout.EndHorizontal();
				}
			}
			GUILayout.EndVertical();
			if (flag)
			{
				entry.BoxedValue = Serialize(list2);
			}
		}

		public static List<RecipeItemEntry> Deserialize(string rawRecipeString)
		{
			List<RecipeItemEntry> list = new List<RecipeItemEntry>();
			if (string.IsNullOrWhiteSpace(rawRecipeString))
			{
				return list;
			}
			string[] array = rawRecipeString.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
			for (int i = 0; i < array.Length; i++)
			{
				string[] array2 = array[i].Trim().Split(new char[1] { ':' });
				string prefabName = array2[0].Trim();
				int amount = 1;
				if (array2.Length > 1 && int.TryParse(array2[1].Trim(), out var result))
				{
					amount = result;
				}
				list.Add(new RecipeItemEntry(prefabName, amount));
			}
			return list;
		}

		public static string Serialize(IEnumerable<RecipeItemEntry> entries)
		{
			if (entries == null)
			{
				return string.Empty;
			}
			return string.Join(','.ToString(), entries.Select((RecipeItemEntry entry) => $"{entry.PrefabName.Trim()}{':'}{Mathf.Max(1, entry.Amount)}"));
		}
	}
}