Decompiled source of 3QsVanillaTweaks v0.0.1

plugins/3QsVanillaTweaks/3QsVanillaTweaks.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Microsoft.CodeAnalysis;
using Mono.Cecil;
using Mono.Cecil.Cil;
using MonoMod.Cil;
using MonoMod.RuntimeDetour;
using R2API;
using RoR2;
using ThreeQsVanillaTweaks.Config;
using UnityEngine;
using UnityEngine.Networking;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("3QsVanillaTweaks")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+26aeaf4406f82ed8ff29d4f7ee48857d6d1f8a01")]
[assembly: AssemblyProduct("3QsVanillaTweaks")]
[assembly: AssemblyTitle("3QsVanillaTweaks")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.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.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ThreeQsVanillaTweaks
{
	internal static class Log
	{
		private static ManualLogSource _logSource;

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

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

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

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

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

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

		internal static void Warning(object data)
		{
			_logSource.LogWarning(data);
		}
	}
	[BepInPlugin("3Questionmarks.3QsVanillaTweaks", "3QsVanillaTweaks", "0.0.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class VanillaTweaksPlugin : BaseUnityPlugin
	{
		public const string PluginAuthor = "3Questionmarks";

		public const string PluginName = "3QsVanillaTweaks";

		public const string PluginGUID = "3Questionmarks.3QsVanillaTweaks";

		public const string PluginVersion = "0.0.1";

		private void Awake()
		{
			Log.Init(((BaseUnityPlugin)this).Logger);
			ConfigManager.Init(((BaseUnityPlugin)this).Config);
			InitializeTweaks();
			Log.Info("3QsVanillaTweaks initialized.");
		}

		private void InitializeTweaks()
		{
			Type[] array = (from type2 in Assembly.GetExecutingAssembly().GetTypes()
				where type2.IsClass && type2.Namespace != null && (type2.Namespace == "ThreeQsVanillaTweaks.Tweaks" || type2.Namespace.StartsWith("ThreeQsVanillaTweaks.Tweaks.", StringComparison.Ordinal))
				orderby type2.FullName
				select type2).ToArray();
			int num = 0;
			Type[] array2 = array;
			foreach (Type type in array2)
			{
				MethodInfo method = type.GetMethod("Init", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
				if (!(method == null) && !(method.ReturnType != typeof(void)))
				{
					try
					{
						method.Invoke(null, null);
						num++;
						Log.Info("Initialized tweak: " + type.Name);
					}
					catch (Exception ex)
					{
						Log.Warning("Failed to initialize tweak " + type.FullName + ": " + ex);
					}
				}
			}
			Log.Info("Initialized " + num + " tweak(s).");
		}
	}
}
namespace ThreeQsVanillaTweaks.Tweaks.Items.Void
{
	internal static class PluripotentLarva
	{
		private const string Section = "Items - 06 Void - Pluripotent Larva";

		private static ConfigEntry<bool> enabled;

		internal static void Init()
		{
			enabled = ConfigManager.BindBool("Items - 06 Void - Pluripotent Larva", "Enabled", defaultValue: true, "Restore consumed Pluripotent Larva stacks at the beginning of each new stage.");
			if (enabled.Value)
			{
				LanguageAPI.Add("ITEM_EXTRALIFEVOID_PICKUP", "Revive on death and <style=cIsVoid>corrupt items</style>. <style=cIsHealing>Regenerates each stage.</style>");
				LanguageAPI.Add("ITEM_EXTRALIFEVOID_DESC", "Upon death, this item will be <style=cIsUtility>consumed</style> and you will return to life with <style=cIsUtility>3 seconds of invulnerability</style>, and all of your items that can be corrupted will be. <style=cIsHealing>Regenerates at the start of each stage.</style>");
				LanguageAPI.Add("ITEM_EXTRALIFEVOIDCONSUMED_PICKUP", "<style=cIsUtility>Regenerates at the start of the next stage.</style>");
				LanguageAPI.Add("ITEM_EXTRALIFEVOIDCONSUMED_DESC", "At the start of each stage, it transforms into <style=cIsHealing>Pluripotent Larva</style>.");
			}
			Stage.onStageStartGlobal += OnStageStart;
		}

		private static void OnStageStart(Stage stage)
		{
			//IL_00a1: 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_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			if (!enabled.Value || !NetworkServer.active || !Object.op_Implicit((Object)(object)Run.instance))
			{
				return;
			}
			ItemDef extraLifeVoid = Items.ExtraLifeVoid;
			ItemDef extraLifeVoidConsumed = Items.ExtraLifeVoidConsumed;
			if (!Object.op_Implicit((Object)(object)extraLifeVoid) || !Object.op_Implicit((Object)(object)extraLifeVoidConsumed))
			{
				return;
			}
			foreach (CharacterMaster readOnlyInstances in CharacterMaster.readOnlyInstancesList)
			{
				if (Object.op_Implicit((Object)(object)readOnlyInstances) && Object.op_Implicit((Object)(object)readOnlyInstances.inventory))
				{
					Inventory inventory = readOnlyInstances.inventory;
					int itemCountPermanent = inventory.GetItemCountPermanent(extraLifeVoidConsumed.itemIndex);
					if (itemCountPermanent > 0)
					{
						inventory.RemoveItemPermanent(extraLifeVoidConsumed.itemIndex, itemCountPermanent);
						inventory.GiveItemPermanent(extraLifeVoid.itemIndex, itemCountPermanent);
						CharacterMasterNotificationQueue.SendTransformNotification(readOnlyInstances, extraLifeVoidConsumed.itemIndex, extraLifeVoid.itemIndex, (TransformationType)5);
					}
				}
			}
		}
	}
}
namespace ThreeQsVanillaTweaks.Tweaks.Items.Uncommon
{
	internal static class RegeneratingScrap
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static Action <0>__Install;

			public static Manipulator <1>__PatchPayment;

			public static Func<ItemTier, ItemTier, ItemDef, bool> <2>__IsEligibleForPrinter;
		}

		private const string Section = "Items - 02 Uncommon - Regenerating Scrap";

		private static ConfigEntry<bool> enabled;

		private static ConfigEntry<bool> common;

		private static ConfigEntry<bool> uncommon;

		private static ConfigEntry<bool> legendary;

		private static ConfigEntry<bool> boss;

		private static bool installed;

		private static ILHook paymentHook;

		private static readonly MethodInfo IsItemDisabledMethod = typeof(Inventory).GetMethod("IsItemDisabled", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(ItemIndex) }, null);

		internal static void Init()
		{
			enabled = ConfigManager.BindBool("Items - 02 Uncommon - Regenerating Scrap", "Enabled", defaultValue: true, "Enable changes to Regenerating Scrap.");
			common = ConfigManager.BindBool("Items - 02 Uncommon - Regenerating Scrap", "Common Printers", defaultValue: true, "Allow Regenerating Scrap in white printers.");
			uncommon = ConfigManager.BindBool("Items - 02 Uncommon - Regenerating Scrap", "Uncommon Printers", defaultValue: true, "Allow Regenerating Scrap in green printers.");
			legendary = ConfigManager.BindBool("Items - 02 Uncommon - Regenerating Scrap", "Legendary Printers", defaultValue: false, "Allow Regenerating Scrap in red printers.");
			boss = ConfigManager.BindBool("Items - 02 Uncommon - Regenerating Scrap", "Boss Printers", defaultValue: false, "Allow Regenerating Scrap in yellow printers.");
			UpdateDescription("ITEM_REGENERATINGSCRAP_DESC");
			UpdatePickupDescription();
			RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(Install));
		}

		private static bool Allows(ItemTier tier)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: 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_001c: 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_0037: Expected I4, but got Unknown
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Invalid comparison between Unknown and I4
			if (!enabled.Value)
			{
				return (int)tier == 1;
			}
			return (int)tier switch
			{
				0 => common.Value, 
				1 => uncommon.Value, 
				2 => legendary.Value, 
				4 => boss.Value, 
				_ => false, 
			};
		}

		private static void Install()
		{
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			//IL_005d: 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: Expected O, but got Unknown
			if (installed)
			{
				return;
			}
			installed = true;
			CostTypeDef costTypeDef = CostTypeCatalog.GetCostTypeDef((CostTypeIndex)5);
			if (costTypeDef == null || costTypeDef.payCost == null)
			{
				Log.Warning("Regenerating Scrap: could not locate the vanilla printer payment method.");
				return;
			}
			try
			{
				MethodInfo method = ((Delegate)(object)costTypeDef.payCost).Method;
				object obj = <>O.<1>__PatchPayment;
				if (obj == null)
				{
					Manipulator val = PatchPayment;
					<>O.<1>__PatchPayment = val;
					obj = (object)val;
				}
				paymentHook = new ILHook((MethodBase)method, (Manipulator)obj);
			}
			catch (Exception ex)
			{
				Log.Warning("Regenerating Scrap: payment IL hook failed: " + ex);
				return;
			}
			InstallAffordability((CostTypeIndex)4);
			InstallAffordability((CostTypeIndex)5);
			InstallAffordability((CostTypeIndex)6);
			InstallAffordability((CostTypeIndex)10);
			UpdateDescription(Items.RegeneratingScrap?.descriptionToken);
			Log.Info("Regenerating Scrap tweak installed.");
		}

		private static void PatchPayment(ILContext il)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			ILCursor val = new ILCursor(il);
			if (!val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[6]
			{
				(Instruction i) => ILPatternMatchingExt.MatchCallvirt<ItemDef>(i, "get_tier"),
				(Instruction i) => ILPatternMatchingExt.MatchLdloc(i, 0),
				(Instruction i) => i.OpCode == OpCodes.Ldfld,
				(Instruction i) => ILPatternMatchingExt.MatchLdfld<PayCostContext>(i, "costTypeDef"),
				(Instruction i) => ILPatternMatchingExt.MatchLdfld<CostTypeDef>(i, "itemTier"),
				(Instruction i) => i.OpCode == OpCodes.Bne_Un_S || i.OpCode == OpCodes.Bne_Un
			}))
			{
				throw new InvalidOperationException("Regenerating Scrap: vanilla printer tier comparison not found.");
			}
			val.Index += 5;
			Instruction next = val.Next;
			object operand = next.Operand;
			ILLabel val2 = (ILLabel)((operand is ILLabel) ? operand : null);
			if (val2 == null || il.Body.Variables.Count <= 11 || ((MemberReference)((VariableReference)il.Body.Variables[11]).VariableType).FullName != typeof(ItemDef).FullName)
			{
				throw new InvalidOperationException("Regenerating Scrap: unexpected printer payment IL layout.");
			}
			val.Remove();
			val.Emit(OpCodes.Ldloc, il.Body.Variables[11]);
			val.EmitDelegate<Func<ItemTier, ItemTier, ItemDef, bool>>((Func<ItemTier, ItemTier, ItemDef, bool>)IsEligibleForPrinter);
			val.Emit(OpCodes.Brfalse, (object)val2);
			Log.Info("Regenerating Scrap: printer payment IL comparison patched.");
		}

		private static bool IsEligibleForPrinter(ItemTier itemTier, ItemTier printerTier, ItemDef item)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: 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)
			if ((Object)(object)item == (Object)(object)Items.RegeneratingScrap)
			{
				return Allows(printerTier);
			}
			return itemTier == printerTier;
		}

		private unsafe static void InstallAffordability(CostTypeIndex index)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			CostTypeDef costTypeDef = CostTypeCatalog.GetCostTypeDef(index);
			if (costTypeDef == null)
			{
				Log.Warning("Regenerating Scrap: missing cost type " + ((object)(*(CostTypeIndex*)(&index))/*cast due to .constrained prefix*/).ToString());
				return;
			}
			IsAffordableDelegate original = costTypeDef.isAffordable;
			costTypeDef.isAffordable = (IsAffordableDelegate)delegate(CostTypeDef costDef, IsAffordableContext context)
			{
				//IL_0008: 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_0015: 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_0033: Invalid comparison between Unknown and I4
				//IL_0050: Unknown result type (might be due to invalid IL or missing references)
				//IL_0052: Invalid comparison between Unknown and I4
				//IL_0054: 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_007e: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f2: 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)
				//IL_0148: Unknown result type (might be due to invalid IL or missing references)
				//IL_0128: Unknown result type (might be due to invalid IL or missing references)
				//IL_0159: Unknown result type (might be due to invalid IL or missing references)
				//IL_015b: Invalid comparison between Unknown and I4
				//IL_017d: 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)
				bool result = original.Invoke(costDef, context);
				ItemTier itemTier = costDef.itemTier;
				if (!enabled.Value)
				{
					return result;
				}
				if ((int)itemTier == 1 && uncommon.Value)
				{
					return result;
				}
				if ((int)itemTier != 1 && !Allows(itemTier))
				{
					return result;
				}
				CharacterBody val = (Object.op_Implicit((Object)(object)context.activator) ? ((Component)context.activator).GetComponent<CharacterBody>() : null);
				Inventory val2 = (Object.op_Implicit((Object)(object)val) ? val.inventory : null);
				if (!Object.op_Implicit((Object)(object)val2) || val2.inventoryDisabled)
				{
					return false;
				}
				ItemDef regeneratingScrap = Items.RegeneratingScrap;
				if ((Object)(object)regeneratingScrap == (Object)null || !regeneratingScrap.canRemove || regeneratingScrap.ContainsTag((ItemTag)33))
				{
					return result;
				}
				int itemCountPermanent = val2.GetItemCountPermanent(regeneratingScrap.itemIndex);
				if (itemCountPermanent <= 0 || IsDisabled(val2, regeneratingScrap.itemIndex))
				{
					return result;
				}
				int num = 0;
				for (int i = 1; i <= context.cost && val2.HasAtLeastXTotalRemovablePermanentItemsOfTier(itemTier, i); i++)
				{
					num = i;
				}
				return ((int)itemTier == 1) ? (num - itemCountPermanent >= context.cost) : (num + itemCountPermanent >= context.cost);
			};
		}

		private static bool IsDisabled(Inventory inventory, ItemIndex index)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			if (IsItemDisabledMethod == null)
			{
				return true;
			}
			try
			{
				return (bool)IsItemDisabledMethod.Invoke(inventory, new object[1] { index });
			}
			catch (Exception ex)
			{
				Log.Warning("Regenerating Scrap: disabled-item check failed: " + ex);
				return true;
			}
		}

		private static void UpdateDescription(string token)
		{
			if (!enabled.Value)
			{
				return;
			}
			ItemDef regeneratingScrap = Items.RegeneratingScrap;
			if (!((Object)(object)regeneratingScrap == (Object)null))
			{
				List<string> list = new List<string>();
				if (common.Value)
				{
					list.Add("<color=#FFFFFF>Common</color>");
				}
				if (uncommon.Value)
				{
					list.Add("<color=#77FF66>Uncommon</color>");
				}
				if (legendary.Value)
				{
					list.Add("<color=#FF5555>Legendary</color>");
				}
				if (boss.Value)
				{
					list.Add("<color=#FFFF00>Boss</color>");
				}
				string text = ((list.Count == 0) ? "Cannot be used in 3D Printers. Regenerates at the start of each stage." : ("Prioritized when used with " + FormatList(list) + " 3D Printers. Can be used once per stage."));
				LanguageAPI.Add(token, text);
			}
		}

		private static void UpdatePickupDescription()
		{
			if (enabled.Value)
			{
				List<string> list = new List<string>();
				if (common.Value)
				{
					list.Add("<color=#FFFFFF>Common</color>");
				}
				if (uncommon.Value)
				{
					list.Add("<color=#77FF66>Uncommon</color>");
				}
				if (legendary.Value)
				{
					list.Add("<color=#FF5555>Legendary</color>");
				}
				if (boss.Value)
				{
					list.Add("<color=#FFFF00>Boss</color>");
				}
				string text = ((list.Count == 0) ? "Cannot be used in 3D Printers. <style=cIsUtility>Regenerates each stage.</style>" : ("Prioritized in " + FormatList(list) + " 3D Printers. <style=cIsUtility>Regenerates each stage.</style>"));
				LanguageAPI.Add("ITEM_REGENERATINGSCRAP_PICKUP", text);
			}
		}

		private static string FormatList(List<string> values)
		{
			if (values.Count == 1)
			{
				return values[0];
			}
			if (values.Count == 2)
			{
				return values[0] + " and " + values[1];
			}
			string text = values[values.Count - 1];
			values.RemoveAt(values.Count - 1);
			return string.Join(", ", values) + ", and " + text;
		}
	}
}
namespace ThreeQsVanillaTweaks.Tweaks.Items.Legendary
{
	internal static class DiosBestFriend
	{
		private const string Section = "Items - 03 Legendary - Dios Best Friend";

		private static ConfigEntry<bool> enabled;

		internal static void Init()
		{
			enabled = ConfigManager.BindBool("Items - 03 Legendary - Dios Best Friend", "Enabled", defaultValue: true, "Restore consumed Dio's Best Friend stacks at the beginning of each new stage.");
			if (enabled.Value)
			{
				LanguageAPI.Add("ITEM_EXTRALIFE_PICKUP", "Revive on death with <style=cIsUtility>temporary invulnerability</style>. <style=cIsHealing>Regenerates each stage.</style>");
				LanguageAPI.Add("ITEM_EXTRALIFE_DESC", "Upon death, this item will be <style=cIsUtility>consumed</style> and you will return to life with <style=cIsUtility>3 seconds of invulnerability</style>. <style=cIsHealing>Regenerates at the start of each stage.</style>");
				LanguageAPI.Add("ITEM_EXTRALIFECONSUMED_PICKUP", "<style=cIsUtility>Regenerates at the start of the next stage.</style>");
				LanguageAPI.Add("ITEM_EXTRALIFECONSUMED_DESC", "At the start of each stage, it transforms into <style=cIsHealing>Dio's Best Friend</style>.");
			}
			Stage.onStageStartGlobal += OnStageStart;
		}

		private static void OnStageStart(Stage stage)
		{
			//IL_00a1: 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_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			if (!enabled.Value || !NetworkServer.active || !Object.op_Implicit((Object)(object)Run.instance))
			{
				return;
			}
			ItemDef extraLife = Items.ExtraLife;
			ItemDef extraLifeConsumed = Items.ExtraLifeConsumed;
			if (!Object.op_Implicit((Object)(object)extraLife) || !Object.op_Implicit((Object)(object)extraLifeConsumed))
			{
				return;
			}
			foreach (CharacterMaster readOnlyInstances in CharacterMaster.readOnlyInstancesList)
			{
				if (Object.op_Implicit((Object)(object)readOnlyInstances) && Object.op_Implicit((Object)(object)readOnlyInstances.inventory))
				{
					Inventory inventory = readOnlyInstances.inventory;
					int itemCountPermanent = inventory.GetItemCountPermanent(extraLifeConsumed.itemIndex);
					if (itemCountPermanent > 0)
					{
						inventory.RemoveItemPermanent(extraLifeConsumed.itemIndex, itemCountPermanent);
						inventory.GiveItemPermanent(extraLife.itemIndex, itemCountPermanent);
						CharacterMasterNotificationQueue.SendTransformNotification(readOnlyInstances, extraLifeConsumed.itemIndex, extraLife.itemIndex, (TransformationType)5);
					}
				}
			}
		}
	}
}
namespace ThreeQsVanillaTweaks.Config
{
	internal static class ConfigManager
	{
		internal static ConfigFile File { get; private set; }

		internal static void Init(ConfigFile config)
		{
			File = config;
		}

		internal static ConfigEntry<bool> BindBool(string section, string key, bool defaultValue, string description)
		{
			return File.Bind<bool>(section, key, defaultValue, description);
		}
	}
}