Decompiled source of EitrExtended v0.1.0

EitrExtended.dll

Decompiled 4 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Reflection.Emit;
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 Configs;
using HarmonyLib;
using Jotunn.Extensions;
using Jotunn.Managers;
using Jotunn.Utils;
using Logging;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("EitrExtended")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("EitrExtended")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("08a6f7d7-cf93-4931-aecd-abf2ce6ed34c")]
[assembly: AssemblyFileVersion("0.1.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Logging
{
	internal static class Log
	{
		internal enum InfoLevel
		{
			Low,
			Medium,
			High
		}

		private static ManualLogSource logSource;

		internal static ConfigEntry<InfoLevel> Verbosity { get; set; }

		internal static InfoLevel VerbosityLevel => Verbosity.Value;

		internal static bool IsVerbosityLow => Verbosity.Value >= InfoLevel.Low;

		internal static bool IsVerbosityMedium => Verbosity.Value >= InfoLevel.Medium;

		internal static bool IsVerbosityHigh => Verbosity.Value >= InfoLevel.High;

		internal static void Init(ManualLogSource logSource)
		{
			Log.logSource = logSource;
		}

		internal static void LogDebug(object data)
		{
			logSource.LogDebug(data);
		}

		internal static void LogError(object data)
		{
			logSource.LogError(data);
		}

		internal static void LogFatal(object data)
		{
			logSource.LogFatal(data);
		}

		internal static void LogMessage(object data)
		{
			logSource.LogMessage(data);
		}

		internal static void LogWarning(object data)
		{
			logSource.LogWarning(data);
		}

		internal static void LogInfo(object data, InfoLevel level = InfoLevel.Low)
		{
			if (Verbosity == null || VerbosityLevel >= level)
			{
				logSource.LogInfo(data);
			}
		}

		internal static void LogGameObject(GameObject prefab, bool includeChildren = false)
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Expected O, but got Unknown
			LogInfo("***** " + ((Object)prefab).name + " *****");
			Component[] components = prefab.GetComponents<Component>();
			for (int i = 0; i < components.Length; i++)
			{
				LogComponent(components[i]);
			}
			if (!includeChildren)
			{
				return;
			}
			LogInfo("***** " + ((Object)prefab).name + " (children) *****");
			foreach (Transform item in prefab.transform)
			{
				Transform val = item;
				if (Object.op_Implicit((Object)(object)val))
				{
					LogInfo(" - " + ((Object)val).name);
					components = ((Component)val).GetComponents<Component>();
					for (int i = 0; i < components.Length; i++)
					{
						LogComponent(components[i]);
					}
				}
			}
		}

		internal static void LogComponent(Component compo)
		{
			if (!Object.op_Implicit((Object)(object)compo))
			{
				return;
			}
			try
			{
				LogInfo("--- " + ((object)compo).GetType().Name + ": " + ((Object)compo).name + " ---");
			}
			catch (Exception ex)
			{
				LogError(ex.ToString());
				LogWarning("Could not get type name for component!");
				return;
			}
			try
			{
				foreach (PropertyInfo declaredProperty in AccessTools.GetDeclaredProperties(((object)compo).GetType()))
				{
					try
					{
						LogInfo($" - {declaredProperty.Name} = {declaredProperty.GetValue(compo)}");
					}
					catch (Exception ex2)
					{
						LogError(ex2.ToString());
						LogWarning("Could not get property: " + declaredProperty.Name + " for component!");
					}
				}
			}
			catch (Exception ex3)
			{
				LogError(ex3.ToString());
				LogWarning("Could not get properties for component!");
			}
			try
			{
				foreach (FieldInfo declaredField in AccessTools.GetDeclaredFields(((object)compo).GetType()))
				{
					try
					{
						LogInfo($" - {declaredField.Name} = {declaredField.GetValue(compo)}");
					}
					catch (Exception ex4)
					{
						LogError(ex4.ToString());
						LogWarning("Could not get field: " + declaredField.Name + " for component!");
					}
				}
			}
			catch (Exception ex5)
			{
				LogError(ex5.ToString());
				LogWarning("Could not get fields for component!");
			}
		}
	}
}
namespace EitrExtended
{
	[BepInPlugin("Searica.Valheim.EitrExtended", "EitrExtended", "0.1.0")]
	[BepInDependency("com.jotunn.jotunn", "2.23.2")]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	[SynchronizationMode(/*Could not decode attribute arguments.*/)]
	internal sealed class EitrExtended : BaseUnityPlugin
	{
		public const string PluginName = "EitrExtended";

		internal const string Author = "Searica";

		public const string PluginGUID = "Searica.Valheim.EitrExtended";

		public const string PluginVersion = "0.1.0";

		internal static EitrExtended Instance;

		internal static ConfigFile ConfigFile;

		internal static ConfigFileWatcher ConfigFileWatcher;

		internal const string GlobalSection = "Global";

		internal const string EitrRegenSection = "Eitr Regen";

		internal const string EitrBaseSection = "Eitr Base";

		internal ConfigEntry<bool> EnableEitrRegen;

		internal ConfigEntry<float> ExtraEitrRegenFlat;

		internal ConfigEntry<float> ExtraEitrRegen;

		internal ConfigEntry<bool> ExtraEitrRegenFoodOnly;

		internal ConfigEntry<bool> EnableEitrBase;

		internal ConfigEntry<float> BloodMagicBasePower;

		internal ConfigEntry<float> BloodMagicBaseCoeff;

		internal ConfigEntry<float> ElementMagicBasePower;

		internal ConfigEntry<float> ElementMagicBaseCoeff;

		public void Awake()
		{
			Instance = this;
			ConfigFile = ((BaseUnityPlugin)this).Config;
			Log.Init(((BaseUnityPlugin)this).Logger);
			((BaseUnityPlugin)this).Config.DisableSaveOnConfigSet();
			SetUpConfigEntries();
			((BaseUnityPlugin)this).Config.Save();
			((BaseUnityPlugin)this).Config.SaveOnConfigSet = true;
			Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "Searica.Valheim.EitrExtended");
			Game.isModded = true;
			ConfigFileWatcher = new ConfigFileWatcher(((BaseUnityPlugin)this).Config);
			ConfigFileWatcher.OnConfigFileReloaded += delegate
			{
			};
			SynchronizationManager.OnConfigurationSynchronized += delegate
			{
			};
			SynchronizationManager.OnConfigurationWindowClosed += delegate
			{
			};
		}

		internal void SetUpConfigEntries()
		{
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Expected O, but got Unknown
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Expected O, but got Unknown
			Log.Verbosity = ConfigFileExtensions.BindConfigInOrder<Log.InfoLevel>(((BaseUnityPlugin)this).Config, "Global", "Verbosity", Log.InfoLevel.Low, "Information level of logging.", true, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			EnableEitrRegen = ConfigFileExtensions.BindConfigInOrder<bool>(((BaseUnityPlugin)this).Config, "Eitr Regen", "Enable Extra Eitr Regen", true, "Enable increased eitr regen.", true, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			ExtraEitrRegen = ConfigFileExtensions.BindConfigInOrder<float>(((BaseUnityPlugin)this).Config, "Eitr Regen", "Extra Eitr Regen", 0.2f, "Increase eitr regen by X% of total eitr above base eitr value.", true, true, true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			ExtraEitrRegenFoodOnly = ConfigFileExtensions.BindConfigInOrder<bool>(((BaseUnityPlugin)this).Config, "Eitr Regen", "Total From Food Only", true, "Only count eitr from food when calcuating total eitr above base eitr value.", true, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			EnableEitrBase = ConfigFileExtensions.BindConfigInOrder<bool>(((BaseUnityPlugin)this).Config, "Eitr Base", "Enable Extra Base Eitr", true, "Enable magic skills granting base eitr as `extra eitr = coeff*(magic skil)^power`.", true, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			BloodMagicBasePower = ConfigFileExtensions.BindConfigInOrder<float>(((BaseUnityPlugin)this).Config, "Eitr Base", "Blood Magic Power", 0.5f, "The power to raise your magic skill to when calculating exta base eitr `(magic skill)^power`.", true, true, true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			BloodMagicBaseCoeff = ConfigFileExtensions.BindConfigInOrder<float>(((BaseUnityPlugin)this).Config, "Eitr Base", "Blood Magic Coeff", 2.5f, "The number to multiply your magic skill by after raising it to a power when calculating exta base eitr.", true, true, true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), (Action<ConfigEntryBase>)null, new ConfigurationManagerAttributes
			{
				ShowRangeAsPercent = false
			});
			ElementMagicBasePower = ConfigFileExtensions.BindConfigInOrder<float>(((BaseUnityPlugin)this).Config, "Eitr Base", "Elemental Magic Power", 0.5f, "The power to raise your magic skill to when calculating exta base eitr `(magic skill)^power`.", true, true, true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			ElementMagicBaseCoeff = ConfigFileExtensions.BindConfigInOrder<float>(((BaseUnityPlugin)this).Config, "Eitr Base", "Elemental Magic Coeff", 2.5f, "The number to multiply your magic skill by after raising it to a power when calculating exta base eitr.", true, true, true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), (Action<ConfigEntryBase>)null, new ConfigurationManagerAttributes
			{
				ShowRangeAsPercent = false
			});
		}

		public void OnDestroy()
		{
			((BaseUnityPlugin)this).Config.Save();
		}
	}
}
namespace EitrExtended.Patches
{
	[HarmonyPatch]
	internal static class BaseEitrPatches
	{
		[HarmonyTranspiler]
		[HarmonyPatch(typeof(Player), "GetTotalFoodValue")]
		private static IEnumerable<CodeInstruction> ChangeBaseEitrTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			CodeMatch[] array = (CodeMatch[])(object)new CodeMatch[1]
			{
				new CodeMatch((OpCode?)OpCodes.Ldc_R4, (object)0f, (string)null)
			};
			CodeInstruction[] array2 = (CodeInstruction[])(object)new CodeInstruction[2]
			{
				new CodeInstruction(OpCodes.Ldarg_0, (object)null),
				new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(BaseEitrPatches), "GetBaseEitr", (Type[])null, (Type[])null))
			};
			return new CodeMatcher(instructions, (ILGenerator)null).MatchStartForward(array).ThrowIfNotMatch("Failed to match code in ChangeBaseEitrTranspiler!", Array.Empty<CodeMatch>()).RemoveInstruction()
				.InsertAndAdvance(array2)
				.ThrowIfInvalid("Failed to insert code in ChangeBaseEitrTranspiler!")
				.InstructionEnumeration();
		}

		public static float GetBaseEitr(Player player)
		{
			if (!EitrExtended.Instance.EnableEitrBase.Value || !Object.op_Implicit((Object)(object)player) || !Object.op_Implicit((Object)(object)((Character)player).GetSkills()))
			{
				return 0f;
			}
			float num = 0f;
			if (TryGetSkillLevel(player, (SkillType)10, out var skillLevel))
			{
				num += EitrExtended.Instance.BloodMagicBaseCoeff.Value * Mathf.Pow(skillLevel, EitrExtended.Instance.BloodMagicBasePower.Value);
			}
			if (TryGetSkillLevel(player, (SkillType)9, out var skillLevel2))
			{
				num += EitrExtended.Instance.ElementMagicBaseCoeff.Value * Mathf.Pow(skillLevel2, EitrExtended.Instance.ElementMagicBasePower.Value);
			}
			return Mathf.Floor(num);
		}

		private static bool TryGetSkillLevel(Player player, SkillType skillType, out float skillLevel)
		{
			//IL_000b: 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)
			if (((Character)player).GetSkills().m_skillData.ContainsKey(skillType))
			{
				skillLevel = ((Character)player).GetSkillLevel(skillType);
				return true;
			}
			skillLevel = 0f;
			return false;
		}

		private static void UpdateBaseEitr(Player player)
		{
			if (!Object.op_Implicit((Object)(object)player))
			{
				return;
			}
			try
			{
				float num = default(float);
				float num2 = default(float);
				float num3 = default(float);
				player.GetTotalFoodValue(ref num, ref num2, ref num3);
				player.SetMaxEitr(num3, true);
			}
			catch (Exception arg)
			{
				Log.LogWarning($"While updating base eitr caught exception {arg}");
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Player), "Awake")]
		private static void Player_Awake_Postfix(Player __instance)
		{
			UpdateBaseEitr(__instance);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Player), "OnSkillLevelup")]
		private static void Player_OnSkillLevelUp_Postfix(Player __instance, SkillType skill)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (IsMagicSkill(skill))
			{
				UpdateBaseEitr(__instance);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Skills), "Awake")]
		private static void Skills_Awake_Postfix(Skills __instance)
		{
			UpdateBaseEitr(Player.m_localPlayer);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Terminal), "TryRunCommand")]
		private static void Terminal_TryRunCommand_Postfix(Terminal __instance, string text)
		{
			if (StringExtensions.ContainsAny(text.ToLower(), new string[2] { "puke", "skill" }))
			{
				UpdateBaseEitr(Player.m_localPlayer);
			}
		}

		private static bool IsMagicSkill(SkillType skillType)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Invalid comparison between Unknown and I4
			if (skillType - 9 <= 1)
			{
				return true;
			}
			return false;
		}
	}
	[HarmonyPatch]
	internal static class EitrRegenPatches
	{
		[HarmonyPatch(typeof(TextsDialog), "AddActiveEffects")]
		public static class TextsDialog_AddActiveEffects_SeasonTooltipWhenBuffDisabled
		{
			private static void Postfix(TextsDialog __instance)
			{
				if (EitrExtended.Instance.EnableEitrRegen.Value && Object.op_Implicit((Object)(object)Player.m_localPlayer))
				{
					float num = GetEitrRegenMultiplier(Player.m_localPlayer) - 1f;
					if (!(num < 0.01f))
					{
						TextInfo obj = __instance.m_texts[0];
						obj.m_text += Localization.instance.Localize(string.Format("\n$se_eitrregen ({0}): <color=orange>{1:P1}</color>", EitrExtended.Instance.ExtraEitrRegenFoodOnly.Value ? "$item_food" : "$hud_misc", num));
					}
				}
			}
		}

		private static readonly string[] tooltipTokens = new string[4] { "$item_food_regen", "$item_food_duration", "$item_food_eitr", "$item_food_stamina" };

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(Player), "UpdateStats", new Type[] { typeof(float) })]
		private static IEnumerable<CodeInstruction> Player_UpdateStats_EitrRegen(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Expected O, but got Unknown
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Expected O, but got Unknown
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			CodeMatch[] array = (CodeMatch[])(object)new CodeMatch[3]
			{
				new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null),
				new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(Player), "GetEquipmentEitrRegenModifier", (Type[])null, (Type[])null), (string)null),
				new CodeMatch((OpCode?)OpCodes.Add, (object)null, (string)null)
			};
			CodeInstruction[] array2 = (CodeInstruction[])(object)new CodeInstruction[3]
			{
				new CodeInstruction(OpCodes.Ldarg_0, (object)null),
				Transpilers.EmitDelegate<Func<Player, float>>((Func<Player, float>)GetEitrRegenMultiplier),
				new CodeInstruction(OpCodes.Mul, (object)null)
			};
			return new CodeMatcher(instructions, (ILGenerator)null).MatchEndForward(array).ThrowIfNotMatch("Failed to match in Player.UpdateStats!", Array.Empty<CodeMatch>()).InsertAndAdvance(array2)
				.ThrowIfInvalid("Failed to insert code in Player.UpdateStats!")
				.InstructionEnumeration();
		}

		public static float GetEitrRegenMultiplier(Player player)
		{
			if (!EitrExtended.Instance.EnableEitrRegen.Value || !Object.op_Implicit((Object)(object)player))
			{
				return 1f;
			}
			float maxEitr = ((Character)player).GetMaxEitr();
			if (!EitrExtended.Instance.ExtraEitrRegenFoodOnly.Value)
			{
				float num = default(float);
				float num2 = default(float);
				player.GetTotalFoodValue(ref num, ref num2, ref maxEitr);
			}
			float num3 = maxEitr - BaseEitrPatches.GetBaseEitr(player);
			float num4 = EitrExtended.Instance.ExtraEitrRegen.Value * num3 / 100f;
			return 1f + num4;
		}

		private static float GetEitrRegenMultiplierForFood(float foodEitr)
		{
			return EitrExtended.Instance.ExtraEitrRegen.Value * foodEitr / 100f;
		}

		[HarmonyPostfix]
		[HarmonyPriority(700)]
		[HarmonyBefore(new string[] { "shudnal.StaminaExtended", "shudnal.MyLittleUI" })]
		[HarmonyPatch(typeof(ItemData), "GetTooltip", new Type[]
		{
			typeof(ItemData),
			typeof(int),
			typeof(bool),
			typeof(float),
			typeof(int)
		})]
		private static void ItemDrop_ItemData_GetTooltip_EitrRegenTooltip_Postfix(ItemData item, ref string __result)
		{
			if (!EitrExtended.Instance.EnableEitrRegen.Value || !IsEitrFood(item, out var foodEitr))
			{
				return;
			}
			int foodToopTipStartIndex = GetFoodToopTipStartIndex(__result);
			if (foodToopTipStartIndex != -1)
			{
				string text = $"\n$se_eitrregen: <color=#ffff80ff>{GetEitrRegenMultiplierForFood(foodEitr):P1}</color> ($item_current:<color=yellow>{GetEitrRegenMultiplier(Player.m_localPlayer) - 1f:P1}</color>)";
				int num = __result.IndexOf("\n", foodToopTipStartIndex, StringComparison.InvariantCulture);
				if (num != -1)
				{
					__result.Insert(num, text);
				}
				else
				{
					__result += text;
				}
			}
		}

		private static bool IsEitrFood(ItemData item, out float foodEitr)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Invalid comparison between Unknown and I4
			foodEitr = 0f;
			if (!EitrExtended.Instance.EnableEitrRegen.Value || !Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				return false;
			}
			if ((int)item.m_shared.m_itemType == 2)
			{
				foodEitr = item.m_shared.m_foodEitr;
			}
			if (!(foodEitr > 0f))
			{
				if ((Object)(object)item.m_shared.m_appendToolTip != (Object)null)
				{
					return IsEitrFood(item.m_shared.m_appendToolTip.m_itemData, out foodEitr);
				}
				return false;
			}
			return true;
		}

		private static int GetFoodToopTipStartIndex(string text)
		{
			int num = -1;
			string[] array = tooltipTokens;
			foreach (string value in array)
			{
				num = text.IndexOf(value, StringComparison.InvariantCulture);
				if (num != -1)
				{
					break;
				}
			}
			return num;
		}
	}
}
namespace Configs
{
	public static class ConfigFileExtensions
	{
		public static bool DisableSaveOnConfigSet(this ConfigFile configFile)
		{
			bool saveOnConfigSet = configFile.SaveOnConfigSet;
			configFile.SaveOnConfigSet = false;
			return saveOnConfigSet;
		}
	}
	internal sealed class ConfigFileWatcher
	{
		private const long RELOAD_DELAY = 10000000L;

		private DateTime lastReadTime = DateTime.MinValue;

		private readonly ConfigFile configFile;

		private readonly string ConfigFileDir;

		private readonly string ConfigFileName;

		internal event Action OnConfigFileReloaded;

		internal ConfigFileWatcher(ConfigFile configFile)
		{
			this.configFile = configFile;
			ConfigFileDir = Directory.GetParent(configFile.ConfigFilePath).FullName;
			ConfigFileName = Path.GetFileName(configFile.ConfigFilePath);
			FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(ConfigFileDir, ConfigFileName);
			fileSystemWatcher.Changed += ReloadConfigFile;
			fileSystemWatcher.Created += ReloadConfigFile;
			fileSystemWatcher.Renamed += ReloadConfigFile;
			fileSystemWatcher.IncludeSubdirectories = true;
			fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
			fileSystemWatcher.EnableRaisingEvents = true;
		}

		private void InvokeOnConfigFileReloaded()
		{
			this.OnConfigFileReloaded?.SafeInvoke();
		}

		internal void ReloadConfigFile(object sender, FileSystemEventArgs eventArgs)
		{
			DateTime now = DateTime.Now;
			long num = now.Ticks - lastReadTime.Ticks;
			if (!File.Exists(configFile.ConfigFilePath) || num < 10000000)
			{
				return;
			}
			try
			{
				Log.LogInfo("Reloading " + configFile.ConfigFilePath);
				bool saveOnConfigSet = configFile.DisableSaveOnConfigSet();
				configFile.Reload();
				configFile.SaveOnConfigSet = saveOnConfigSet;
				lastReadTime = now;
				InvokeOnConfigFileReloaded();
			}
			catch
			{
				Log.LogError("There was an issue loading " + configFile.ConfigFilePath);
				Log.LogError("Please check your config entries for spelling and format!");
			}
		}
	}
	internal static class SafeInvokeEvent
	{
		internal static void SafeInvoke(this Action events)
		{
			if (events == null)
			{
				return;
			}
			Delegate[] invocationList = events.GetInvocationList();
			for (int i = 0; i < invocationList.Length; i++)
			{
				Action action = (Action)invocationList[i];
				try
				{
					action();
				}
				catch (Exception arg)
				{
					Log.LogWarning("Exception thrown at event " + new StackFrame(1).GetMethod().Name + $" in {action.Method.DeclaringType.Name}.{action.Method.Name}:\n{arg}");
				}
			}
		}
	}
}