Decompiled source of R2API Rulebook v1.0.2

plugins/R2API.Rulebook/R2API.Rules.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.Logging;
using HG;
using IL.RoR2;
using Microsoft.CodeAnalysis;
using Mono.Cecil.Cil;
using MonoMod.Cil;
using R2API.AutoVersionGen;
using RoR2;
using RoR2.EntitlementManagement;
using RoR2.ExpansionManagement;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("R2API.Rules")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.2.0")]
[assembly: AssemblyInformationalVersion("1.0.2+b0ad023cc271b28f24a0d498ac7081947f826823")]
[assembly: AssemblyProduct("R2API.Rules")]
[assembly: AssemblyTitle("R2API.Rules")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.2.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 System.Diagnostics.CodeAnalysis
{
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
	[ExcludeFromCodeCoverage]
	[DebuggerNonUserCode]
	internal sealed class MemberNotNullAttribute : Attribute
	{
		public string[] Members { get; }

		public MemberNotNullAttribute(string member)
		{
			Members = new string[1] { member };
		}

		public MemberNotNullAttribute(params string[] members)
		{
			Members = members;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
	[ExcludeFromCodeCoverage]
	[DebuggerNonUserCode]
	internal sealed class MemberNotNullWhenAttribute : Attribute
	{
		public bool ReturnValue { get; }

		public string[] Members { get; }

		public MemberNotNullWhenAttribute(bool returnValue, string member)
		{
			ReturnValue = returnValue;
			Members = new string[1] { member };
		}

		public MemberNotNullWhenAttribute(bool returnValue, params string[] members)
		{
			ReturnValue = returnValue;
			Members = members;
		}
	}
}
namespace R2API
{
	public class ExtendedRuleChoiceDef : RuleChoiceDef
	{
		public List<UnlockableDef> requiredUnlockables = new List<UnlockableDef>();

		public List<RuleChoiceDef> requiredChoiceDefs = new List<RuleChoiceDef>();

		public List<EntitlementDef> requiredEntitlementDefs = new List<EntitlementDef>();

		public List<ExpansionDef> requiredExpansionDefs = new List<ExpansionDef>();
	}
	internal static class PreGameControllerHelper
	{
		public static bool AnyUserHasAllUnlockables(IEnumerable<UnlockableDef> unlockables)
		{
			foreach (UnlockableDef unlockable in unlockables)
			{
				if (!PreGameController.AnyUserHasUnlockable(unlockable))
				{
					return false;
				}
			}
			return true;
		}

		public static bool AreAllExpansionsActive(PreGameController controllerInstance, IEnumerable<ExpansionDef> expansionDefs)
		{
			IEnumerable<RuleChoiceDef> ruleChoices = expansionDefs.Select((ExpansionDef expansion) => expansion.enabledChoice);
			return AreAllChoicesActive(controllerInstance, ruleChoices);
		}

		public static bool AreAllChoicesActive(PreGameController controllerInstance, IEnumerable<RuleChoiceDef> ruleChoices)
		{
			if (controllerInstance.readOnlyRuleBook == null)
			{
				return false;
			}
			RuleBook readOnlyRuleBook = controllerInstance.readOnlyRuleBook;
			foreach (RuleChoiceDef ruleChoice in ruleChoices)
			{
				if (!readOnlyRuleBook.IsChoiceActive(ruleChoice))
				{
					return false;
				}
			}
			return true;
		}

		public static bool AnyUserHasAllEntitlements(IEnumerable<EntitlementDef> entitlementDefs, bool checkNetworkInsteadOfLocal)
		{
			foreach (EntitlementDef entitlementDef in entitlementDefs)
			{
				if (!(checkNetworkInsteadOfLocal ? ((BaseUserEntitlementTracker<NetworkUser>)(object)EntitlementManager.networkUserEntitlementTracker).AnyUserHasEntitlement(entitlementDef) : ((BaseUserEntitlementTracker<LocalUser>)(object)EntitlementManager.localUserEntitlementTracker).AnyUserHasEntitlement(entitlementDef)))
				{
					return false;
				}
			}
			return true;
		}
	}
	[AutoVersion]
	public static class RuleCatalogExtras
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static Action <0>__AddCustomRulesAndCategoriesToCatalog;

			public static Manipulator <1>__SupportCollectionRequirement;

			public static Func<PreGameController, RuleChoiceDef, int, bool> <2>__HandleCollectionRequirement;
		}

		public const string PluginGUID = "com.bepis.r2api.rules";

		public const string PluginName = "R2API.Rules";

		private static bool _hooksEnabled = false;

		private static Dictionary<int, List<RuleDef>> categoryToCustomRules = new Dictionary<int, List<RuleDef>>();

		private static List<RuleCategoryDef> ruleCategoryDefs = new List<RuleCategoryDef>();

		public const string PluginVersion = "1.0.2";

		public static int DifficultyCategoryIndex => 0;

		public static int ExpansionsCategoryIndex => 1;

		public static int ArtifactsCategoryIndex => 2;

		public static int ItemsCategoryIndex => 3;

		public static int EquipmentsCategoryIndex => 4;

		public static int MiscCategoryIndex => 5;

		private static int TotalVanillaCategories => 5;

		public static int AddCategory(RuleCategoryDef category)
		{
			SetHooks();
			if (((ResourceAvailability)(ref RuleCatalog.availability)).available)
			{
				return AddCategoryDirectlyToCatalog(category);
			}
			return AddCategoryInternal(category);
			static int AddCategoryDirectlyToCatalog(RuleCategoryDef categoryDef)
			{
				RuleCatalog.allCategoryDefs.Add(categoryDef);
				ruleCategoryDefs.Add(categoryDef);
				return RuleCatalog.allCategoryDefs.Count - 1;
			}
			static int AddCategoryInternal(RuleCategoryDef categoryDef)
			{
				ruleCategoryDefs.Add(categoryDef);
				return TotalVanillaCategories + ruleCategoryDefs.Count;
			}
		}

		public static void AddRuleToCatalog(RuleDef ruleDef, int ruleCategoryDefIndex)
		{
			SetHooks();
			if (((ResourceAvailability)(ref RuleCatalog.availability)).available)
			{
				AddRuleDirectlyToCatalog(ruleDef, ruleCategoryDefIndex);
			}
			else
			{
				AddRuleInternal(ruleDef, ruleCategoryDefIndex);
			}
			static void AddRuleDirectlyToCatalog(RuleDef ruleDef2, int num)
			{
				AddRuleToCategoryInternal(RuleCatalog.GetCategoryDef(num), ruleDef2);
			}
			static void AddRuleInternal(RuleDef item, int key)
			{
				if (!categoryToCustomRules.ContainsKey(key))
				{
					categoryToCustomRules[key] = new List<RuleDef>();
				}
				categoryToCustomRules[key].Add(item);
			}
		}

		public static RuleDef FindCustomRuleDef(string ruleDefGlobalName)
		{
			SetHooks();
			if (((ResourceAvailability)(ref RuleCatalog.availability)).available)
			{
				return RuleCatalog.FindRuleDef(ruleDefGlobalName);
			}
			return FindRuleDefInternal(ruleDefGlobalName);
			static RuleDef FindRuleDefInternal(string a)
			{
				foreach (RuleDef item in categoryToCustomRules.Values.SelectMany((List<RuleDef> x) => x))
				{
					if (string.Equals(a, item.globalName, StringComparison.OrdinalIgnoreCase))
					{
						return item;
					}
				}
				return null;
			}
		}

		public static RuleChoiceDef FindCustomChoiceDef(string ruleChoiceDefGlobalName)
		{
			SetHooks();
			if (((ResourceAvailability)(ref RuleCatalog.availability)).available)
			{
				return RuleCatalog.FindChoiceDef(ruleChoiceDefGlobalName);
			}
			return FindChoiceDefInternal(ruleChoiceDefGlobalName);
			static RuleChoiceDef FindChoiceDefInternal(string a)
			{
				foreach (RuleChoiceDef item in categoryToCustomRules.Values.SelectMany((List<RuleDef> x) => x).SelectMany((RuleDef x) => x.choices))
				{
					if (string.Equals(a, item.globalName, StringComparison.OrdinalIgnoreCase))
					{
						return item;
					}
				}
				return null;
			}
		}

		internal static void SetHooks()
		{
			//IL_0049: 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_0054: Expected O, but got Unknown
			if (!_hooksEnabled)
			{
				if (!((ResourceAvailability)(ref RuleCatalog.availability)).available)
				{
					((ResourceAvailability)(ref RuleCatalog.availability)).onAvailable += AddCustomRulesAndCategoriesToCatalog;
				}
				object obj = <>O.<1>__SupportCollectionRequirement;
				if (obj == null)
				{
					Manipulator val = SupportCollectionRequirement;
					<>O.<1>__SupportCollectionRequirement = val;
					obj = (object)val;
				}
				PreGameController.RecalculateModifierAvailability += (Manipulator)obj;
				_hooksEnabled = true;
			}
		}

		internal static void UnsetHooks()
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			((ResourceAvailability)(ref RuleCatalog.availability)).onAvailable -= AddCustomRulesAndCategoriesToCatalog;
			object obj = <>O.<1>__SupportCollectionRequirement;
			if (obj == null)
			{
				Manipulator val = SupportCollectionRequirement;
				<>O.<1>__SupportCollectionRequirement = val;
				obj = (object)val;
			}
			PreGameController.RecalculateModifierAvailability -= (Manipulator)obj;
			_hooksEnabled = false;
		}

		private static void SupportCollectionRequirement(ILContext il)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: 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_0214: Unknown result type (might be due to invalid IL or missing references)
			ILCursor val = new ILCursor(il);
			ILLabel val2 = null;
			ILLabel val3 = default(ILLabel);
			val.GotoNext((MoveType)2, new Func<Instruction, bool>[4]
			{
				(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt<RuleBook>(x, "IsChoiceActive"),
				(Instruction x) => ILPatternMatchingExt.MatchBr(x, ref val3),
				(Instruction x) => ILPatternMatchingExt.MatchLdcI4(x, 1),
				(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt<SerializableBitArray>(x, "set_Item")
			});
			val2 = val.MarkLabel();
			if (val2 == null)
			{
				RulesPlugin.Logger.LogError((object)"ILHook on PreGameController.RecalculateModifierAvailability failed, could not find ILLabel");
				return;
			}
			val.Index = 0;
			if (!val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[7]
			{
				(Instruction x) => ILPatternMatchingExt.MatchRet(x),
				(Instruction x) => ILPatternMatchingExt.MatchLdcI4(x, 0),
				(Instruction x) => ILPatternMatchingExt.MatchStloc(x, 0),
				(Instruction x) => ILPatternMatchingExt.MatchBr(x, ref val3),
				(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, 0),
				(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, typeof(RuleCatalog), "GetChoiceDef"),
				(Instruction x) => ILPatternMatchingExt.MatchStloc(x, 1)
			}))
			{
				RulesPlugin.Logger.LogError((object)"ILHook on PreGameController.RecalculateModifierAvailability failed, could not get into position for calling the delegate.");
				return;
			}
			val.Emit(OpCodes.Ldarg_0);
			val.Emit(OpCodes.Ldloc_1);
			val.Emit(OpCodes.Ldloc_0);
			val.EmitDelegate<Func<PreGameController, RuleChoiceDef, int, bool>>((Func<PreGameController, RuleChoiceDef, int, bool>)HandleCollectionRequirement);
			val.Emit(OpCodes.Brtrue, (object)val2);
			static bool HandleCollectionRequirement(PreGameController preGameController, RuleChoiceDef currentRule, int choiceIndex)
			{
				if (currentRule.TryCastToExtendedRuleChoiceDef(out ExtendedRuleChoiceDef extendedRuleChoiceDef))
				{
					((SerializableBitArray)preGameController.unlockedChoiceMask)[choiceIndex] = extendedRuleChoiceDef.requiredUnlockables.Count == 0 || PreGameControllerHelper.AnyUserHasAllUnlockables(extendedRuleChoiceDef.requiredUnlockables);
					((SerializableBitArray)preGameController.dependencyChoiceMask)[choiceIndex] = extendedRuleChoiceDef.requiredChoiceDefs.Count == 0 || PreGameControllerHelper.AreAllChoicesActive(preGameController, extendedRuleChoiceDef.requiredChoiceDefs);
					((SerializableBitArray)preGameController.entitlementChoiceMask)[choiceIndex] = extendedRuleChoiceDef.requiredEntitlementDefs.Count == 0 || PreGameControllerHelper.AnyUserHasAllEntitlements(extendedRuleChoiceDef.requiredEntitlementDefs, checkNetworkInsteadOfLocal: true) || PreGameControllerHelper.AnyUserHasAllEntitlements(extendedRuleChoiceDef.requiredEntitlementDefs, checkNetworkInsteadOfLocal: false);
					((SerializableBitArray)preGameController.requiredExpansionEnabledChoiceMask)[choiceIndex] = extendedRuleChoiceDef.requiredExpansionDefs.Count == 0 || PreGameControllerHelper.AreAllExpansionsActive(preGameController, extendedRuleChoiceDef.requiredExpansionDefs);
					return true;
				}
				return false;
			}
		}

		private static void AddCustomRulesAndCategoriesToCatalog()
		{
			RuleCatalog.allCategoryDefs.AddRange(ruleCategoryDefs);
			foreach (var (categoryIndex, ruleDefs) in categoryToCustomRules)
			{
				try
				{
					AddRulesToCategory(categoryIndex, ruleDefs);
				}
				catch (Exception ex)
				{
					RulesPlugin.Logger.LogError((object)ex);
				}
			}
		}

		private static void AddRulesToCategory(int categoryIndex, List<RuleDef> ruleDefs)
		{
			RuleCategoryDef categoryDef = RuleCatalog.GetCategoryDef(categoryIndex);
			foreach (RuleDef ruleDef in ruleDefs)
			{
				try
				{
					AddRuleToCategoryInternal(categoryDef, ruleDef);
				}
				catch (Exception ex)
				{
					RulesPlugin.Logger.LogError((object)ex);
				}
			}
		}

		private static void AddRuleToCategoryInternal(RuleCategoryDef category, RuleDef ruleDef)
		{
			ruleDef.category = category;
			ruleDef.globalIndex = RuleCatalog.allRuleDefs.Count;
			category.children.Add(ruleDef);
			RuleCatalog.allRuleDefs.Add(ruleDef);
			if (RuleCatalog.highestLocalChoiceCount < ruleDef.choices.Count)
			{
				RuleCatalog.highestLocalChoiceCount = ruleDef.choices.Count;
			}
			RuleCatalog.ruleDefsByGlobalName[ruleDef.globalName] = ruleDef;
			for (int i = 0; i < ruleDef.choices.Count; i++)
			{
				RuleChoiceDef val = ruleDef.choices[i];
				val.localIndex = i;
				val.globalIndex = RuleCatalog.allChoicesDefs.Count;
				RuleCatalog.allChoicesDefs.Add(val);
				RuleCatalog.ruleChoiceDefsByGlobalName[val.globalName] = val;
				if (Object.op_Implicit((Object)(object)val.requiredUnlockable))
				{
					ArrayUtils.ArrayAppend<RuleChoiceDef>(ref RuleCatalog._allChoiceDefsWithUnlocks, ref val);
				}
				if (val.TryCastToExtendedRuleChoiceDef(out ExtendedRuleChoiceDef extendedRuleChoiceDef) && extendedRuleChoiceDef.requiredUnlockables.Count > 0)
				{
					RuleChoiceDef val2 = (RuleChoiceDef)(object)extendedRuleChoiceDef;
					ArrayUtils.ArrayAppend<RuleChoiceDef>(ref RuleCatalog._allChoiceDefsWithUnlocks, ref val2);
				}
			}
		}
	}
	public static class RulesExtensions
	{
		public static ExtendedRuleChoiceDef AddExtendedRuleChoiceDef(this RuleDef ruleDef, string choiceName, object extraData = null, bool excludeByDefault = false)
		{
			RuleCatalogExtras.SetHooks();
			ExtendedRuleChoiceDef extendedRuleChoiceDef = new ExtendedRuleChoiceDef();
			((RuleChoiceDef)extendedRuleChoiceDef).ruleDef = ruleDef;
			((RuleChoiceDef)extendedRuleChoiceDef).localName = choiceName;
			((RuleChoiceDef)extendedRuleChoiceDef).globalName = ruleDef.globalName + "." + choiceName;
			((RuleChoiceDef)extendedRuleChoiceDef).extraData = extraData;
			((RuleChoiceDef)extendedRuleChoiceDef).excludeByDefault = excludeByDefault;
			ruleDef.choices.Add((RuleChoiceDef)(object)extendedRuleChoiceDef);
			return extendedRuleChoiceDef;
		}

		public static bool TryCastToExtendedRuleChoiceDef(this RuleChoiceDef choice, out ExtendedRuleChoiceDef extendedRuleChoiceDef)
		{
			RuleCatalogExtras.SetHooks();
			if (choice is ExtendedRuleChoiceDef extendedRuleChoiceDef2)
			{
				extendedRuleChoiceDef = extendedRuleChoiceDef2;
				return true;
			}
			extendedRuleChoiceDef = null;
			return false;
		}
	}
	[BepInPlugin("com.bepis.r2api.rules", "R2API.Rules", "1.0.2")]
	public sealed class RulesPlugin : BaseUnityPlugin
	{
		internal static ManualLogSource Logger { get; set; }

		private void Awake()
		{
			Logger = ((BaseUnityPlugin)this).Logger;
		}

		private void OnEnable()
		{
			RuleCatalogExtras.SetHooks();
		}

		private void OnDisable()
		{
			RuleCatalogExtras.UnsetHooks();
		}
	}
}
namespace R2API.AutoVersionGen
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	internal class AutoVersionAttribute : Attribute
	{
	}
}