Decompiled source of CraftableAspects v1.0.2

plugins/CraftableAspects.dll

Decompiled 18 hours 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 Microsoft.CodeAnalysis;
using MonoMod.RuntimeDetour;
using RoR2;
using RoR2.ContentManagement;
using UnityEngine;

[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("CraftableAspects")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("CraftableAspects")]
[assembly: AssemblyTitle("CraftableAspects")]
[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 CraftableAspects
{
	internal static class CraftableCatalogProbe
	{
		private delegate void OrigSetCraftableDefs(CraftableDef[] newCraftableDefs);

		private delegate void HookSetCraftableDefs(OrigSetCraftableDefs orig, CraftableDef[] newCraftableDefs);

		private sealed class RecipeDefinition
		{
			internal string CraftableName { get; }

			internal string ResultDisplayName { get; }

			internal Object Result { get; }

			internal string IngredientADisplayName { get; }

			internal Object IngredientA { get; }

			internal string IngredientBDisplayName { get; }

			internal Object IngredientB { get; }

			internal RecipeDefinition(string craftableName, string resultDisplayName, Object result, string ingredientADisplayName, Object ingredientA, string ingredientBDisplayName, Object ingredientB)
			{
				CraftableName = craftableName;
				ResultDisplayName = resultDisplayName;
				Result = result;
				IngredientADisplayName = ingredientADisplayName;
				IngredientA = ingredientA;
				IngredientBDisplayName = ingredientBDisplayName;
				IngredientB = ingredientB;
			}
		}

		private const string CraftableNamePrefix = "CraftableAspects_";

		private static Hook setCraftableDefsHook;

		private static bool installed;

		internal static void Install()
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Expected O, but got Unknown
			if (!installed)
			{
				MethodInfo method = typeof(CraftableCatalog).GetMethod("SetCraftableDefs", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(CraftableDef[]) }, null);
				if (method == null)
				{
					Plugin.Log.LogError((object)"[CraftableCatalogProbe] Could not find CraftableCatalog.SetCraftableDefs(CraftableDef[]).");
					return;
				}
				setCraftableDefsHook = new Hook((MethodBase)method, (Delegate)new HookSetCraftableDefs(CraftableCatalog_SetCraftableDefs));
				installed = true;
				Plugin.Log.LogInfo((object)"[CraftableCatalogProbe] Installed RuntimeDetour hook.");
			}
		}

		internal static void Uninstall()
		{
			if (installed)
			{
				Hook obj = setCraftableDefsHook;
				if (obj != null)
				{
					obj.Dispose();
				}
				setCraftableDefsHook = null;
				installed = false;
				Plugin.Log.LogInfo((object)"[CraftableCatalogProbe] Uninstalled.");
			}
		}

		private static void CraftableCatalog_SetCraftableDefs(OrigSetCraftableDefs orig, CraftableDef[] newCraftableDefs)
		{
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			CraftableDef[] array = newCraftableDefs ?? Array.Empty<CraftableDef>();
			Plugin.Log.LogInfo((object)("[CraftableCatalogProbe] SetCraftableDefs received " + $"{array.Length} CraftableDefs."));
			try
			{
				RecipeDefinition[] array2 = CreateRecipeDefinitions();
				CraftableDef[] array3 = array2.Select(CreateCraftableDef).ToArray();
				HashSet<string> customCraftableNames = new HashSet<string>(array3.Select((CraftableDef def) => ((Object)def).name));
				CraftableDef[] array4 = (ContentManager._craftableDefs = array.Where((CraftableDef craftableDef) => (Object)(object)craftableDef != (Object)null && !customCraftableNames.Contains(((Object)craftableDef).name)).Concat(array3).ToArray());
				RecipeDefinition[] array5 = array2;
				foreach (RecipeDefinition recipeDefinition in array5)
				{
					Plugin.Log.LogInfo((object)("[CraftableCatalogProbe] Added recipe: " + recipeDefinition.IngredientADisplayName + " + " + recipeDefinition.IngredientBDisplayName + " -> " + recipeDefinition.ResultDisplayName + "."));
				}
				Plugin.Log.LogInfo((object)("[CraftableCatalogProbe] Added " + $"{array3.Length} custom CraftableDefs."));
				Plugin.Log.LogInfo((object)("[CraftableCatalogProbe] Submitting " + $"{array4.Length} CraftableDefs."));
				orig(array4);
				RecipeEntry[] allRecipes = CraftableCatalog.GetAllRecipes();
				Plugin.Log.LogInfo((object)("[CraftableCatalogProbe] Catalog initialized with " + $"{allRecipes.Length} runtime recipes."));
				RecipeDefinition[] array6 = array2;
				foreach (RecipeDefinition recipeDefinition2 in array6)
				{
					PickupIndex resultPickup = GetPickupIndex(recipeDefinition2.Result);
					int num3 = allRecipes.Count((RecipeEntry recipeEntry) => recipeEntry != null && recipeEntry.result == resultPickup);
					Plugin.Log.LogInfo((object)("[CraftableCatalogProbe] " + recipeDefinition2.ResultDisplayName + " has " + $"{num3} runtime recipe(s)."));
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)"[CraftableCatalogProbe] Failed to add custom recipes. Falling back to the vanilla catalog.");
				Plugin.Log.LogError((object)ex);
				ContentManager._craftableDefs = array;
				orig(array);
			}
		}

		private static RecipeDefinition[] CreateRecipeDefinitions()
		{
			ItemDef headHunter = Items.HeadHunter;
			ValidatePickup((Object)(object)headHunter, "Wake of Vultures");
			return new RecipeDefinition[10]
			{
				new RecipeDefinition("FunctionalCoupler", "Functional Coupler", (Object)(object)Items.ExtraEquipment, "Fuel Cell", (Object)(object)Items.EquipmentMagazine, "Bandolier", (Object)(object)Items.Bandolier),
				new RecipeDefinition("FireAspect", "Ifrit's Distinction", (Object)(object)Equipment.AffixRed, "Wake of Vultures", (Object)(object)headHunter, "Molten Perforator", (Object)(object)Items.FireballsOnHit),
				new RecipeDefinition("IceAspect", "Her Biting Embrace", (Object)(object)Equipment.AffixWhite, "Wake of Vultures", (Object)(object)headHunter, "Frost Relic", (Object)(object)Items.Icicle),
				new RecipeDefinition("LightningAspect", "Silence Between Two Strikes", (Object)(object)Equipment.AffixBlue, "Wake of Vultures", (Object)(object)headHunter, "Charged Perforator", (Object)(object)Items.LightningStrikeOnHit),
				new RecipeDefinition("GildedAspect", "Gilded Aspect", (Object)(object)Equipment.EliteAurelioniteEquipment, "Wake of Vultures", (Object)(object)headHunter, "Growth Nectar", (Object)(object)Items.BoostAllStats),
				new RecipeDefinition("MendingAspect", "Mending Aspect", (Object)(object)GetMendingAspectEquipment(), "Wake of Vultures", (Object)(object)headHunter, "Rejuvenation Rack", (Object)(object)Items.IncreaseHealing),
				new RecipeDefinition("CelestineAspect", "Celestine Aspect", (Object)(object)Equipment.AffixHaunted, "Wake of Vultures", (Object)(object)headHunter, "Soulbound Catalyst", (Object)(object)Items.Talisman),
				new RecipeDefinition("MalachiteAspect", "Malachite Aspect", (Object)(object)Equipment.AffixPoison, "Wake of Vultures", (Object)(object)headHunter, "Mired Urn", (Object)(object)Items.SiphonOnLowHealth),
				new RecipeDefinition("TwistedAspect", "Twisted Aspect", (Object)(object)Equipment.EliteBeadEquipment, "Wake of Vultures", (Object)(object)headHunter, "Beads of Fealty", (Object)(object)Items.LunarTrinket),
				new RecipeDefinition("PerfectedAspect", "Perfected Aspect", (Object)(object)Equipment.AffixLunar, "Wake of Vultures", (Object)(object)headHunter, "Purity", (Object)(object)Items.LunarBadLuck)
			};
		}

		private static EquipmentDef GetMendingAspectEquipment()
		{
			EliteDef earth = Elites.Earth;
			if (!Object.op_Implicit((Object)(object)earth))
			{
				throw new InvalidOperationException("Mending EliteDef is null.");
			}
			EquipmentDef eliteEquipmentDef = earth.eliteEquipmentDef;
			if (!Object.op_Implicit((Object)(object)eliteEquipmentDef))
			{
				throw new InvalidOperationException("Mending Aspect EquipmentDef is null.");
			}
			return eliteEquipmentDef;
		}

		private static CraftableDef CreateCraftableDef(RecipeDefinition definition)
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Expected O, but got Unknown
			ValidatePickup(definition.Result, definition.ResultDisplayName);
			ValidatePickup(definition.IngredientA, definition.IngredientADisplayName);
			ValidatePickup(definition.IngredientB, definition.IngredientBDisplayName);
			CraftableDef val = ScriptableObject.CreateInstance<CraftableDef>();
			((Object)val).name = "CraftableAspects_" + definition.CraftableName;
			val.pickup = definition.Result;
			Object result = definition.Result;
			ItemDef val2 = (ItemDef)(object)((result is ItemDef) ? result : null);
			if (val2 != null)
			{
				val.itemIndex = val2.itemIndex;
				val.equipmentIndex = (EquipmentIndex)(-1);
			}
			else
			{
				Object result2 = definition.Result;
				EquipmentDef val3 = (EquipmentDef)(object)((result2 is EquipmentDef) ? result2 : null);
				if (val3 == null)
				{
					throw new InvalidOperationException(definition.ResultDisplayName + " is neither an ItemDef nor an EquipmentDef.");
				}
				val.itemIndex = (ItemIndex)(-1);
				val.equipmentIndex = val3.equipmentIndex;
			}
			Recipe[] array = new Recipe[1];
			Recipe val4 = new Recipe();
			val4.amountToDrop = 1;
			val4.priority = 0;
			val4.ingredients = (RecipeIngredient[])(object)new RecipeIngredient[2]
			{
				CreateAssetReferenceIngredient(definition.IngredientA),
				CreateAssetReferenceIngredient(definition.IngredientB)
			};
			array[0] = val4;
			val.recipes = (Recipe[])(object)array;
			return val;
		}

		private static RecipeIngredient CreateAssetReferenceIngredient(Object pickup)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: 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: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: 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_003f: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Expected O, but got Unknown
			if (!Object.op_Implicit(pickup))
			{
				throw new ArgumentNullException("pickup");
			}
			return new RecipeIngredient
			{
				pickup = pickup,
				pickupIndex = PickupIndex.none,
				type = (IngredientTypeIndex)0,
				itemTier = (ItemTier)5,
				requiredTags = Array.Empty<ItemTag>(),
				forbiddenTags = Array.Empty<ItemTag>(),
				isLunar = false,
				isBoss = false
			};
		}

		private static PickupIndex GetPickupIndex(Object pickup)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: 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_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			ItemDef val = (ItemDef)(object)((pickup is ItemDef) ? pickup : null);
			if (val != null)
			{
				return PickupCatalog.FindPickupIndex(val.itemIndex);
			}
			EquipmentDef val2 = (EquipmentDef)(object)((pickup is EquipmentDef) ? pickup : null);
			if (val2 != null)
			{
				return PickupCatalog.FindPickupIndex(val2.equipmentIndex);
			}
			return PickupIndex.none;
		}

		private static void ValidatePickup(Object pickup, string displayName)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Invalid comparison between Unknown and I4
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Invalid comparison between Unknown and I4
			if (!Object.op_Implicit(pickup))
			{
				throw new InvalidOperationException(displayName + " pickup definition is null.");
			}
			ItemDef val = (ItemDef)(object)((pickup is ItemDef) ? pickup : null);
			if (val != null)
			{
				if ((int)val.itemIndex == -1)
				{
					throw new InvalidOperationException(displayName + " has not received an ItemIndex.");
				}
				return;
			}
			EquipmentDef val2 = (EquipmentDef)(object)((pickup is EquipmentDef) ? pickup : null);
			if (val2 != null)
			{
				if ((int)val2.equipmentIndex == -1)
				{
					throw new InvalidOperationException(displayName + " has not received an EquipmentIndex.");
				}
				return;
			}
			throw new InvalidOperationException(displayName + " is neither an ItemDef nor an EquipmentDef.");
		}
	}
	[BepInPlugin("evanr.craftableaspects", "Craftable Aspects", "1.0.2")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "evanr.craftableaspects";

		public const string PluginName = "Craftable Aspects";

		public const string PluginVersion = "1.0.2";

		internal static ManualLogSource Log;

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Craftable Aspects loaded.");
			CraftableCatalogProbe.Install();
		}

		private void OnDestroy()
		{
			CraftableCatalogProbe.Uninstall();
		}
	}
}