Decompiled source of SkilledCarryWeight v1.3.0

SkilledCarryWeight.dll

Decompiled 6 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
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.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using SkilledCarryWeight.Configs;
using SkilledCarryWeight.Extensions;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("SkilledCarryWeight")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SkilledCarryWeight")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")]
[assembly: AssemblyFileVersion("1.3.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.3.0.0")]
[module: UnverifiableCode]
namespace SkilledCarryWeight
{
	[BepInPlugin("Searica.Valheim.SkilledCarryWeight", "SkilledCarryWeight", "1.3.0")]
	[BepInDependency("com.jotunn.jotunn", "2.20.0")]
	internal sealed class SkilledCarryWeight : BaseUnityPlugin
	{
		internal class SkillConfig
		{
			public ConfigEntry<bool> enabledConfig;

			public ConfigEntry<float> coeffConfig;

			public ConfigEntry<float> powConfig;

			public bool IsEnabled => enabledConfig.Value;

			public float Coeff => coeffConfig.Value;

			public float Pow => powConfig.Value;
		}

		internal const string Author = "Searica";

		public const string PluginName = "SkilledCarryWeight";

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

		public const string PluginVersion = "1.3.0";

		internal static readonly Dictionary<SkillType, SkillConfig> SkillConfigsMap = new Dictionary<SkillType, SkillConfig>();

		internal static ConfigEntry<bool> EnableCartPatch;

		internal static ConfigEntry<float> CartPower;

		internal static ConfigEntry<float> MaxMassReduction;

		internal static ConfigEntry<float> MinCarryWeight;

		internal static ConfigEntry<KeyCode> QuickCartKey;

		internal static ConfigEntry<float> AttachDistance;

		internal static ConfigEntry<bool> AttachOutOfPlace;

		private static readonly string MainSection = ConfigManager.SetStringPriority("Global", 3);

		private static readonly string CartSection = ConfigManager.SetStringPriority("Cart Mass", 2);

		private static readonly string QuickCartSection = ConfigManager.SetStringPriority("Quick Cart", 1);

		private static bool SettingsUpdated = false;

		public void Awake()
		{
			Log.Init(((BaseUnityPlugin)this).Logger);
			ConfigManager.Init("Searica.Valheim.SkilledCarryWeight", ((BaseUnityPlugin)this).Config);
			Initialize();
			ConfigManager.Save();
			Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "Searica.Valheim.SkilledCarryWeight");
			Game.isModded = true;
			ConfigManager.SetupWatcher();
			ConfigManager.CheckForConfigManager();
			ConfigManager.OnConfigWindowClosed += delegate
			{
				if (SettingsUpdated)
				{
					ConfigManager.Save();
					SettingsUpdated = false;
				}
			};
		}

		public void OnDestroy()
		{
			ConfigManager.Save();
		}

		private static void OnSettingChanged(object sender, EventArgs e)
		{
			if (!SettingsUpdated)
			{
				SettingsUpdated = true;
			}
		}

		internal static void Initialize()
		{
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Invalid comparison between Unknown and I4
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0292: Unknown result type (might be due to invalid IL or missing references)
			Log.Verbosity = ConfigManager.BindConfig(MainSection, "Verbosity", LogLevel.Low, "Low will log basic information about the mod. Medium will log information that is useful for troubleshooting. High will log a lot of information, do not set it to this without good reason as it will slow down your game.", null, synced: false);
			Log.Verbosity.SettingChanged += OnSettingChanged;
			EnableCartPatch = ConfigManager.BindConfig(CartSection, "CarryWeightAffectsCart", value: true, "Set to true/enabled to allow your max carry weight affect how easy carts are to pull by reducing the mass of carts you pull.");
			EnableCartPatch.SettingChanged += OnSettingChanged;
			CartPower = ConfigManager.BindConfig(CartSection, "Power", 1f, "Affects how much your maximum carry weight making pulling carts easier. Higher powers make your maximum carry weight reduce the mass of carts more.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3f));
			CartPower.SettingChanged += OnSettingChanged;
			MaxMassReduction = ConfigManager.BindConfig(CartSection, "MaxMassReduction", 0.7f, "Maximum reduction in cart mass due to increased max carry weight. Limits effective cart mass to always be equal to or greater than Mass * (1 - MaxMassReduction)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f));
			MaxMassReduction.SettingChanged += OnSettingChanged;
			MinCarryWeight = ConfigManager.BindConfig(CartSection, "MinCarryWeight", 300f, "Minimum value your maximum carry weight must be before it starts making carts easier to pull.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(300f, 1000f));
			MinCarryWeight.SettingChanged += OnSettingChanged;
			QuickCartKey = ConfigManager.BindConfig<KeyCode>(QuickCartSection, "QuickCartKey", (KeyCode)103, "The hotkey used to attach to or detach from a nearby cart.", null, synced: false);
			AttachDistance = ConfigManager.BindConfig(QuickCartSection, "AttachDistance", 5f, "Maximum distance to attach a cart from.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 8f));
			AttachOutOfPlace = ConfigManager.BindConfig(QuickCartSection, "AttachOutOfPlace", value: true, "Allow attaching the cart even when out of place.");
			SkillType[] s_allSkills = Skills.s_allSkills;
			for (int i = 0; i < s_allSkills.Length; i++)
			{
				SkillType val = s_allSkills[i];
				if ((int)val != 999)
				{
					string section = ((object)(SkillType)(ref val)).ToString();
					SkillConfig skillConfig = new SkillConfig();
					skillConfig.enabledConfig = ConfigManager.BindConfig(section, ConfigManager.SetStringPriority("Enabled", 1), GetDefaultEnabledValue(val), "Set to true/enabled to allow this skill to increase your max carry weight.");
					skillConfig.enabledConfig.SettingChanged += OnSettingChanged;
					skillConfig.coeffConfig = ConfigManager.BindConfig(section, "Coefficient", 0.25f, "Value to multiply the skill level by to determine how much extra carry weight it grants.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f));
					skillConfig.coeffConfig.SettingChanged += OnSettingChanged;
					skillConfig.powConfig = ConfigManager.BindConfig(section, "Power", 1f, "Power the skill level is raised to before multiplying by Coefficient to determine extra carry weight.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f));
					skillConfig.powConfig.SettingChanged += OnSettingChanged;
					SkillConfigsMap[val] = skillConfig;
				}
			}
		}

		private static bool GetDefaultEnabledValue(SkillType skillType)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected I4, but got Unknown
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Invalid comparison between Unknown and I4
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Invalid comparison between Unknown and I4
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Invalid comparison between Unknown and I4
			if ((int)skillType <= 13)
			{
				if ((int)skillType == 12)
				{
					return true;
				}
				if ((int)skillType == 13)
				{
					return true;
				}
			}
			else
			{
				switch (skillType - 100)
				{
				case 2:
					return true;
				case 0:
					return true;
				case 3:
					return true;
				case 1:
					return true;
				}
				if ((int)skillType == 110)
				{
					return true;
				}
			}
			return false;
		}

		private void Update()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			if (Input.GetKeyDown(QuickCartKey.Value) && PlayerCanAttach() && TryGetClosestVagon(out var closestVagon) && Object.op_Implicit((Object)(object)closestVagon))
			{
				closestVagon.Interact((Humanoid)(object)Player.m_localPlayer, false, false);
			}
		}

		private static bool PlayerCanAttach()
		{
			if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && !((Character)Player.m_localPlayer).IsDead())
			{
				return !((Character)Player.m_localPlayer).InPlaceMode();
			}
			return false;
		}

		private static bool TryGetClosestVagon(out Vagon closestVagon)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: 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_0023: 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_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			closestVagon = null;
			float num = float.PositiveInfinity;
			Vector3 val = ((Component)Player.m_localPlayer).transform.position + Vector3.up;
			Collider[] array = Physics.OverlapSphere(val, AttachDistance.Value);
			foreach (Collider val2 in array)
			{
				if (TryGetVagon(val2, out var vagon) && Object.op_Implicit((Object)(object)val2.attachedRigidbody) && (vagon.IsAttached((Character)(object)Player.m_localPlayer) || !vagon.InUse()))
				{
					float num2 = Vector3.Distance(val2.ClosestPoint(val), val);
					if (num2 < num)
					{
						Log.LogInfo($"Found cart {num2} away", LogLevel.Medium);
						num = num2;
						closestVagon = vagon;
					}
				}
			}
			return num < AttachDistance.Value;
		}

		private static bool TryGetVagon(Collider collider, out Vagon vagon)
		{
			vagon = ((Component)collider).gameObject.GetComponent<Vagon>();
			if (!Object.op_Implicit((Object)(object)vagon) && Object.op_Implicit((Object)(object)((Component)collider).transform.parent))
			{
				vagon = ((Component)((Component)collider).transform.parent).GetComponent<Vagon>();
			}
			return Object.op_Implicit((Object)(object)vagon);
		}
	}
	internal enum LogLevel
	{
		Low,
		Medium,
		High
	}
	internal static class Log
	{
		internal static ManualLogSource _logSource;

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

		internal static LogLevel VerbosityLevel => Verbosity.Value;

		internal static void Init(ManualLogSource logSource)
		{
			_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 LogInfo(object data, LogLevel level = LogLevel.Low)
		{
			if (Verbosity == null || VerbosityLevel >= level)
			{
				_logSource.LogInfo(data);
			}
		}

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

		internal static void LogWarning(object data)
		{
			_logSource.LogWarning(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;
				LogInfo(" - " + ((Object)((Component)val).gameObject).name);
				components = ((Component)val).gameObject.GetComponents<Component>();
				for (int i = 0; i < components.Length; i++)
				{
					LogComponent(components[i]);
				}
			}
		}

		internal static void LogComponent(Component compo)
		{
			LogInfo("--- " + ((object)compo).GetType().Name + ": " + ((Object)compo).name + " ---");
			PropertyInfo[] properties = ((object)compo).GetType().GetProperties(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.SetField | BindingFlags.GetProperty | BindingFlags.SetProperty);
			foreach (PropertyInfo propertyInfo in properties)
			{
				LogInfo($" - {propertyInfo.Name} = {propertyInfo.GetValue(compo)}");
			}
			FieldInfo[] fields = ((object)compo).GetType().GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.SetField | BindingFlags.GetProperty | BindingFlags.SetProperty);
			foreach (FieldInfo fieldInfo in fields)
			{
				LogInfo($" - {fieldInfo.Name} = {fieldInfo.GetValue(compo)}");
			}
		}
	}
}
namespace SkilledCarryWeight.Patches
{
	[HarmonyPatch(typeof(Player))]
	internal static class PlayerPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("GetMaxCarryWeight")]
		private static void GetMaxCarryWeight(Player __instance, ref float __result)
		{
			//IL_0023: 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)
			Skills skills = ((Character)__instance).GetSkills();
			foreach (SkillDef skill in skills.m_skills)
			{
				if (SkilledCarryWeight.SkillConfigsMap.TryGetValue(skill.m_skill, out var value) && value.IsEnabled)
				{
					__result += value.Coeff * Mathf.Pow(skills.GetSkillLevel(skill.m_skill), value.Pow);
					if (float.IsInfinity(__result))
					{
						__result = float.MaxValue;
						break;
					}
				}
			}
		}
	}
	[HarmonyPatch(typeof(Vagon))]
	internal static class VagonPatch
	{
		[HarmonyPrefix]
		[HarmonyPatch("SetMass")]
		private static void SetMassPrefix(Vagon __instance, ref float mass)
		{
			if (SkilledCarryWeight.EnableCartPatch.Value && Object.op_Implicit((Object)(object)__instance) && !((Object)(object)__instance.m_nview == (Object)null) && __instance.m_nview.IsOwner() && __instance.IsAttached((Character)(object)Player.m_localPlayer))
			{
				Player localPlayer = Player.m_localPlayer;
				float num = mass * Mathf.Pow(SkilledCarryWeight.MinCarryWeight.Value / localPlayer.GetMaxCarryWeight(), SkilledCarryWeight.CartPower.Value);
				mass = Mathf.Max(num, mass * (1f - SkilledCarryWeight.MaxMassReduction.Value));
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch("CanAttach")]
		private static bool CanAttachPrefix(Vagon __instance, GameObject go, ref bool __result)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			if (!SkilledCarryWeight.AttachOutOfPlace.Value || ((Component)__instance).transform.up.y < 0.1f || (Object)(object)go != (Object)(object)((Component)Player.m_localPlayer).gameObject)
			{
				__instance.m_detachDistance = SkilledCarryWeight.AttachDistance.Value;
				return true;
			}
			bool flag = Vector3.Distance(go.transform.position + __instance.m_attachOffset, __instance.m_attachPoint.position) < SkilledCarryWeight.AttachDistance.Value;
			__result = !((Character)Player.m_localPlayer).IsTeleporting() && !((Character)Player.m_localPlayer).InDodge() && flag;
			return false;
		}

		[HarmonyPostfix]
		[HarmonyPatch("GetHoverText")]
		private static void GetHoverTextPostfix(Vagon __instance, ref string __result)
		{
			//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_001c: Unknown result type (might be due to invalid IL or missing references)
			KeyCode value = SkilledCarryWeight.QuickCartKey.Value;
			__result = Localization.instance.Localize($"{__instance.m_name}\n[<color=yellow>{value}</color>] Quick Attach/Detach");
		}
	}
}
namespace SkilledCarryWeight.Extensions
{
	internal static class EventExtensions
	{
		public 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 ex)
				{
					Log.LogWarning($"Exception thrown at event {new StackFrame(1).GetMethod().Name} in {action.Method.DeclaringType.Name}.{action.Method.Name}:\n{ex}");
				}
			}
		}

		public static void SafeInvoke<TArg1>(this Action<TArg1> events, TArg1 arg1)
		{
			if (events == null)
			{
				return;
			}
			Delegate[] invocationList = events.GetInvocationList();
			for (int i = 0; i < invocationList.Length; i++)
			{
				Action<TArg1> action = (Action<TArg1>)invocationList[i];
				try
				{
					action(arg1);
				}
				catch (Exception ex)
				{
					Log.LogWarning($"Exception thrown at event {new StackFrame(1).GetMethod().Name} in {action.Method.DeclaringType.Name}.{action.Method.Name}:\n{ex}");
				}
			}
		}

		public static void SafeInvoke<TArg1, TArg2>(this Action<TArg1, TArg2> events, TArg1 arg1, TArg2 arg2)
		{
			if (events == null)
			{
				return;
			}
			Delegate[] invocationList = events.GetInvocationList();
			for (int i = 0; i < invocationList.Length; i++)
			{
				Action<TArg1, TArg2> action = (Action<TArg1, TArg2>)invocationList[i];
				try
				{
					action(arg1, arg2);
				}
				catch (Exception ex)
				{
					Log.LogWarning($"Exception thrown at event {new StackFrame(1).GetMethod().Name} in {action.Method.DeclaringType.Name}.{action.Method.Name}:\n{ex}");
				}
			}
		}

		public static void SafeInvoke<TEventArg>(this EventHandler<TEventArg> events, object sender, TEventArg arg1)
		{
			if (events == null)
			{
				return;
			}
			Delegate[] invocationList = events.GetInvocationList();
			for (int i = 0; i < invocationList.Length; i++)
			{
				EventHandler<TEventArg> eventHandler = (EventHandler<TEventArg>)invocationList[i];
				try
				{
					eventHandler(sender, arg1);
				}
				catch (Exception ex)
				{
					Log.LogWarning($"Exception thrown at event {new StackFrame(1).GetMethod().Name} in {eventHandler.Method.DeclaringType.Name}.{eventHandler.Method.Name}:\n{ex}");
				}
			}
		}
	}
	internal static class ReflectionUtils
	{
		public const BindingFlags AllBindings = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.SetField | BindingFlags.GetProperty | BindingFlags.SetProperty;

		internal static MethodInfo GetMethod(Type type, string name, Type[] types)
		{
			MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.SetField | BindingFlags.GetProperty | BindingFlags.SetProperty);
			foreach (MethodInfo methodInfo in methods)
			{
				if (methodInfo.Name == name && HasMatchingParameterTypes(0, types, methodInfo.GetParameters()))
				{
					return methodInfo;
				}
			}
			return null;
		}

		internal static MethodInfo GetGenericMethod(Type type, string name, int genericParameterCount, Type[] types)
		{
			MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.SetField | BindingFlags.GetProperty | BindingFlags.SetProperty);
			foreach (MethodInfo methodInfo in methods)
			{
				if (methodInfo.IsGenericMethod && methodInfo.ContainsGenericParameters && methodInfo.Name == name && HasMatchingParameterTypes(genericParameterCount, types, methodInfo.GetParameters()))
				{
					return methodInfo;
				}
			}
			return null;
		}

		private static bool HasMatchingParameterTypes(int genericParameterCount, Type[] types, ParameterInfo[] parameters)
		{
			if (parameters.Length < genericParameterCount || parameters.Length != types.Length)
			{
				return false;
			}
			int num = 0;
			for (int i = 0; i < parameters.Length; i++)
			{
				if (parameters[i].ParameterType.IsGenericParameter)
				{
					num++;
				}
				else if (types[i] != parameters[i].ParameterType)
				{
					return false;
				}
			}
			if (num != genericParameterCount)
			{
				return false;
			}
			return true;
		}
	}
}
namespace SkilledCarryWeight.Configs
{
	internal static class ConfigManager
	{
		private static string ConfigFileName;

		private static string ConfigFileFullPath;

		private static ConfigFile configFile;

		private static BaseUnityPlugin ConfigurationManager;

		private const string ConfigManagerGUID = "com.bepis.bepinex.configurationmanager";

		private static readonly ConfigurationManagerAttributes AdminConfig = new ConfigurationManagerAttributes
		{
			IsAdminOnly = true
		};

		private static readonly ConfigurationManagerAttributes ClientConfig = new ConfigurationManagerAttributes
		{
			IsAdminOnly = false
		};

		private const char ZWS = '\u200b';

		internal static event Action OnConfigWindowClosed;

		internal static event Action OnConfigFileReloaded;

		private static void InvokeOnConfigWindowClosed()
		{
			ConfigManager.OnConfigWindowClosed?.SafeInvoke();
		}

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

		internal static ConfigEntry<T> BindConfig<T>(string section, string name, T value, string description, AcceptableValueBase acceptVals = null, bool synced = true)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			string extendedDescription = GetExtendedDescription(description, synced);
			return configFile.Bind<T>(section, name, value, new ConfigDescription(extendedDescription, acceptVals, new object[1] { synced ? AdminConfig : ClientConfig }));
		}

		internal static string SetStringPriority(string sectionName, int priority)
		{
			if (priority == 0)
			{
				return sectionName;
			}
			return new string('\u200b', priority) + sectionName;
		}

		internal static string GetExtendedDescription(string description, bool synchronizedSetting)
		{
			return description + (synchronizedSetting ? " [Synced with Server]" : " [Not Synced with Server]");
		}

		internal static void Init(string GUID, ConfigFile config, bool saveOnConfigSet = false)
		{
			configFile = config;
			configFile.SaveOnConfigSet = saveOnConfigSet;
			ConfigFileName = GUID + ".cfg";
			ConfigFileFullPath = Path.Combine(Paths.ConfigPath, ConfigFileName);
		}

		internal static bool DisableSaveOnConfigSet()
		{
			bool saveOnConfigSet = configFile.SaveOnConfigSet;
			configFile.SaveOnConfigSet = false;
			return saveOnConfigSet;
		}

		internal static void SaveOnConfigSet(bool value)
		{
			configFile.SaveOnConfigSet = value;
		}

		internal static void Save()
		{
			configFile.Save();
		}

		internal static void SetupWatcher()
		{
			FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(Paths.ConfigPath, ConfigFileName);
			fileSystemWatcher.Changed += ReloadConfigFile;
			fileSystemWatcher.Created += ReloadConfigFile;
			fileSystemWatcher.Renamed += ReloadConfigFile;
			fileSystemWatcher.IncludeSubdirectories = true;
			fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
			fileSystemWatcher.EnableRaisingEvents = true;
		}

		private static void ReloadConfigFile(object sender, FileSystemEventArgs e)
		{
			if (!File.Exists(ConfigFileFullPath))
			{
				return;
			}
			try
			{
				Log.LogInfo("Reloading config file");
				bool value = DisableSaveOnConfigSet();
				configFile.Reload();
				SaveOnConfigSet(value);
				InvokeOnConfigFileReloaded();
			}
			catch
			{
				Log.LogError("There was an issue loading your " + ConfigFileName);
				Log.LogError("Please check your config entries for spelling and format!");
			}
		}

		internal static void CheckForConfigManager()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Invalid comparison between Unknown and I4
			if ((int)SystemInfo.graphicsDeviceType != 4 && Chainloader.PluginInfos.TryGetValue("com.bepis.bepinex.configurationmanager", out var value) && Object.op_Implicit((Object)(object)value.Instance))
			{
				ConfigurationManager = value.Instance;
				Log.LogDebug("Configuration manager found, hooking DisplayingWindowChanged");
				EventInfo @event = ((object)ConfigurationManager).GetType().GetEvent("DisplayingWindowChanged");
				if (@event != null)
				{
					Action<object, object> action = OnConfigManagerDisplayingWindowChanged;
					Delegate handler = Delegate.CreateDelegate(@event.EventHandlerType, action.Target, action.Method);
					@event.AddEventHandler(ConfigurationManager, handler);
				}
			}
		}

		private static void OnConfigManagerDisplayingWindowChanged(object sender, object e)
		{
			if (!(bool)((object)ConfigurationManager).GetType().GetProperty("DisplayingWindow").GetValue(ConfigurationManager, null))
			{
				InvokeOnConfigWindowClosed();
			}
		}
	}
}