Decompiled source of BlackMagicAPI v3.0.1
BepInEx/plugins/BlackMagicAPI/BlackMagicAPI.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using System.Threading.Tasks; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Logging; using BlackMagicAPI.Enums; using BlackMagicAPI.Helpers; using BlackMagicAPI.Interfaces; using BlackMagicAPI.Managers; using BlackMagicAPI.Modules.Items; using BlackMagicAPI.Modules.Soups; using BlackMagicAPI.Modules.Spells; using BlackMagicAPI.Network; using BlackMagicAPI.Patches.Items; using BlackMagicAPI.Patches.Managers; using BlackMagicAPI.Patches.Player; using FishNet.Connection; using FishNet.Managing; using FishNet.Object; using FishNet.Object.Delegating; using FishNet.Serializing; using FishNet.Transporting; using FishUtilities.Helpers; using FishUtilities.Managers; using HarmonyLib; using MageArena_StealthSpells; using Microsoft.CodeAnalysis; using Recognissimo; using Recognissimo.Components; using Unity.VisualScripting; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: IgnoresAccessChecksTo("BepInEx")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("BlackMagicAPI")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("3.0.0.0")] [assembly: AssemblyInformationalVersion("3.0.0.0+8a171c82f858d41b35cd37867533ab58c4465dac")] [assembly: AssemblyProduct("BlackMagicAPI")] [assembly: AssemblyTitle("BlackMagicAPI")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("3.0.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.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] [Microsoft.CodeAnalysis.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] [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 BlackMagicAPI { [BepInProcess("MageArena")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("com.d1gq.black.magic.api", "BlackMagicAPI", "3.0.1")] public class BMAPlugin : BaseUnityPlugin { private static Harmony? Harmony; private ManualLogSource? _log; public static string modsync = "all"; internal static BMAPlugin Instance { get; [param: AllowNull] private set; } internal static ManualLogSource Log => Instance._log; public static string BlackMagicSyncHash { get; internal set; } = ""; private void Awake() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown _log = ((BaseUnityPlugin)this).Logger; Instance = this; Harmony = new Harmony("com.d1gq.black.magic.api"); Harmony.PatchAll(); Log.LogInfo((object)string.Format("BlackMagicAPI v{0} loaded, (Compatibility -> v{1})", "3.0.1", CompatibilityManager.COMPATIBILITY_VERSION)); SynchronizeManager.UpdateSyncHash(); ((MonoBehaviour)this).StartCoroutine(CoWaitForChainloaderToLog()); } private IEnumerator CoWaitForChainloaderToLog() { while (!Chainloader._loaded && !SplashScreen.isFinished) { yield return null; } yield return (object)new WaitForSeconds(1f); ModSyncManager.LogAll(); } } internal static class ModMetaData { internal const string GUID = "com.d1gq.black.magic.api"; internal const string PLUGIN_NAME = "BlackMagicAPI"; internal const string VERSION = "3.0.1"; internal const string MOD_SYNC_GUID_DEP = "com.magearena.modsync"; internal const string FISH_UTILITIES_GUID_DEP = "com.d1gq.fish.utilities"; } } namespace BlackMagicAPI.Patches.Soups { [Harmony] internal class SoupManPatch { [HarmonyPatch(typeof(SoupManController))] internal class SoupManControllerPatch { private static readonly ConditionalWeakTable<SoupManController, List<int>> usedIds = new ConditionalWeakTable<SoupManController, List<int>>(); [HarmonyPatch("Start")] [HarmonyPostfix] [HarmonyPriority(800)] private static void Start_Postfix(SoupManController __instance) { if (!usedIds.TryGetValue(__instance, out List<int> value)) { value = new List<int>(); usedIds.Add(__instance, value); } else { value.Clear(); } List<GameObject> list = __instance.SoupPrefabs.ToList(); List<GameObject> list2 = __instance.SoupItems.ToList(); List<Material> list3 = __instance.matas.ToList(); int num = __instance.SoupPrefabs.Length + 1; list.Add(null); list2.Add(null); list3.Add(null); foreach (var item2 in SoupManager.Mapping.OrderBy<(SoupData, CrystalSoup, GameObject, SoupEffect), int>(((SoupData data, CrystalSoup itemPrefab, GameObject render, SoupEffect effect) m) => m.data.ItemId)) { if (value.Contains(item2.Item1.RequiredItemId)) { item2.Item1.SoupId = -1; item2.Item2.stewid = -1; continue; } value.Add(item2.Item1.RequiredItemId); item2.Item1.SoupId = num; item2.Item2.stewid = num; list.Add(((Component)item2.Item2).gameObject); list3.Add(((Renderer)item2.Item2.mrend).materials[1]); GameObject item = CreateItemDisplay(__instance, item2.Item3); list2.Add(item); num++; } SoupManController val = __instance; int num2 = 0; GameObject[] array = (GameObject[])(object)new GameObject[list.Count]; foreach (GameObject item3 in list) { array[num2] = item3; num2++; } val.SoupPrefabs = array; val = __instance; num2 = 0; array = (GameObject[])(object)new GameObject[list2.Count]; foreach (GameObject item4 in list2) { array[num2] = item4; num2++; } val.SoupItems = array; val = __instance; num2 = 0; Material[] array2 = (Material[])(object)new Material[list3.Count]; foreach (Material item5 in list3) { array2[num2] = item5; num2++; } val.matas = array2; } private static GameObject CreateItemDisplay(SoupManController __instance, GameObject? render) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Expected O, but got Unknown if (render == null) { render = new GameObject("Render"); } GameObject obj = Object.Instantiate<GameObject>(render, __instance.SoupItems.First().transform.parent); obj.SetActive(false); return obj; } } [HarmonyPatch(typeof(SoupManInteractor))] internal class SoupManInteractorPatch { [HarmonyPatch("DisplayInteractUI")] [HarmonyPrefix] [HarmonyPriority(800)] private static bool DisplayInteractUI_Prefix(SoupManInteractor __instance, GameObject player, ref string __result) { PlayerInventory val = default(PlayerInventory); if (player.TryGetComponent<PlayerInventory>(ref val) && !__instance.smc.isCookingSoup) { int equippedItemID = val.GetEquippedItemID(); (SoupData, CrystalSoup, GameObject, SoupEffect) tuple = SoupManager.Mapping.FirstOrDefault<(SoupData, CrystalSoup, GameObject, SoupEffect)>(((SoupData data, CrystalSoup itemPrefab, GameObject render, SoupEffect effect) map) => map.data.RequiredItemId == equippedItemID); var (soupData, val2, val3, soupEffect) = tuple; if (soupData != null || (Object)(object)val2 != (Object)null || (Object)(object)val3 != (Object)null || (Object)(object)soupEffect != (Object)null) { __result = "Make " + tuple.Item1.Name; return false; } } return true; } [HarmonyPatch("Interact")] [HarmonyPrefix] [HarmonyPriority(800)] private static bool Interact_Prefix(SoupManInteractor __instance, GameObject player) { if (Time.time - __instance.cd < 1f) { return true; } PlayerInventory val = default(PlayerInventory); if (player.TryGetComponent<PlayerInventory>(ref val) && !__instance.smc.isCookingSoup) { int equippedItemID = val.GetEquippedItemID(); (SoupData, CrystalSoup, GameObject, SoupEffect) tuple = SoupManager.Mapping.FirstOrDefault<(SoupData, CrystalSoup, GameObject, SoupEffect)>(((SoupData data, CrystalSoup itemPrefab, GameObject render, SoupEffect effect) map) => map.data.RequiredItemId == equippedItemID); var (soupData, val2, val3, soupEffect) = tuple; if (soupData != null || (Object)(object)val2 != (Object)null || (Object)(object)val3 != (Object)null || (Object)(object)soupEffect != (Object)null) { __instance.smc.CookSoup(tuple.Item1.SoupId); val.destroyHandItem(); return false; } } return true; } } [HarmonyPatch(typeof(GetSoupFromGuy))] internal class GetSoupFromGuyPatch { [HarmonyPatch("DisplayInteractUI")] [HarmonyPrefix] [HarmonyPriority(800)] private static bool DisplayInteractUI_Prefix(GetSoupFromGuy __instance, GameObject player, ref string __result) { GetSoupFromGuy __instance2 = __instance; (SoupData, CrystalSoup, GameObject, SoupEffect) tuple = SoupManager.Mapping.FirstOrDefault<(SoupData, CrystalSoup, GameObject, SoupEffect)>(((SoupData data, CrystalSoup itemPrefab, GameObject render, SoupEffect effect) map) => map.data.SoupId == __instance2.soupid); var (soupData, val, val2, soupEffect) = tuple; if (soupData != null || (Object)(object)val != (Object)null || (Object)(object)val2 != (Object)null || (Object)(object)soupEffect != (Object)null) { __result = "Grasp " + tuple.Item1.Name; return false; } return true; } } } } namespace BlackMagicAPI.Patches.Player { [HarmonyPatch(typeof(PlayerInventory))] internal class PlayerInventoryPatch { [HarmonyPatch] private static class PlaceOnCraftingTablePatch { private static MethodBase TargetMethod() { return Utils.PatchRpcMethod<PlayerInventory>("RpcLogic___PlaceOnCraftingTableObserver"); } [HarmonyPostfix] [HarmonyPriority(800)] private static void Postfix(GameObject obj, GameObject CrIn) { ItemBehavior itemBehavior = default(ItemBehavior); if (obj.TryGetComponent<ItemBehavior>(ref itemBehavior)) { itemBehavior.SetTransformOnCraftingForge(); } } } private static readonly Dictionary<int, Sprite?> UiSprites = new Dictionary<int, Sprite>(); [HarmonyPatch("SwapItemImg")] [HarmonyPrefix] [HarmonyPriority(800)] private static bool SwapItemImg_Prefix(PlayerInventory __instance, int slotid, int itemid) { if (itemid > __instance.ItemIcons.Length && UiSprites.TryGetValue(itemid, out Sprite value)) { ((Component)((Component)__instance.UIImages[slotid]).transform.GetChild(0)).GetComponent<Image>().sprite = value; return false; } return true; } internal static void SetUiSprite(Sprite? sprite, int itemId) { if (!((Object)(object)sprite == (Object)null)) { UiSprites[itemId] = sprite; } } [HarmonyPatch(typeof(PlayerInventory), "PlayerDied")] [HarmonyPrefix] [HarmonyPriority(800)] private static bool PlayerDied_Prefix(PlayerInventory __instance) { __instance.canUseItem = false; __instance.canSwapItem = false; bool flag = false; int equippedIndex = __instance.equippedIndex; __instance.equippedIndex = 0; int[] array = new int[3]; MageBookController? itemPrefab = BlackMagicManager.GetItemPrefab<MageBookController>(); array[0] = ((itemPrefab != null) ? itemPrefab.GetItemID() : (-1)); TorchController? itemPrefab2 = BlackMagicManager.GetItemPrefab<TorchController>(); array[1] = ((itemPrefab2 != null) ? itemPrefab2.GetItemID() : (-1)); ExcaliburController? itemPrefab3 = BlackMagicManager.GetItemPrefab<ExcaliburController>(); array[2] = ((itemPrefab3 != null) ? ((SwordController)itemPrefab3).GetItemID() : (-1)); int[] array2 = array; ItemBehavior itemBehavior = default(ItemBehavior); PageController val2 = default(PageController); SpellLogic spellLogic = default(SpellLogic); IItemInteraction val3 = default(IItemInteraction); for (int i = 0; i < __instance.equippedItems.Length; i++) { GameObject val = __instance.equippedItems[i]; if ((Object)(object)val == (Object)null) { __instance.equippedIndex++; continue; } if (val.TryGetComponent<ItemBehavior>(ref itemBehavior) && itemBehavior.KeepOnDeath) { __instance.equippedIndex++; continue; } if (val.TryGetComponent<PageController>(ref val2) && (Object)(object)val2.spellprefab != (Object)null && val2.spellprefab.TryGetComponent<SpellLogic>(ref spellLogic) && spellLogic.KeepOnDeath) { __instance.equippedIndex++; continue; } if (val.TryGetComponent<IItemInteraction>(ref val3)) { int itemID = val3.GetItemID(); if (!flag) { flag = itemID == array2[0]; } if (array2.Contains(itemID)) { __instance.equippedIndex++; continue; } } __instance.Drop(); __instance.equippedIndex++; } __instance.equippedIndex = equippedIndex; __instance.LayerMaskSwapZero(); GameObject val4 = __instance.equippedItems[__instance.equippedIndex]; if ((Object)(object)val4 != (Object)null) { __instance.HideObject(val4); } if (!flag) { ((MonoBehaviour)__instance).StartCoroutine(__instance.DelaySpellbookRespawn()); } return false; } } [HarmonyPatch(typeof(PlayerMovement))] internal class PlayerMovementPatch { [HarmonyPatch] private static class ObsDrinkSoupPatch { private static MethodBase TargetMethod() { return Utils.PatchRpcMethod<PlayerMovement>("RpcLogic___ObsDrinkSoup"); } [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(PlayerMovement __instance, int stewid) { (SoupData, CrystalSoup, GameObject, SoupEffect) tuple = SoupManager.Mapping.FirstOrDefault<(SoupData, CrystalSoup, GameObject, SoupEffect)>(((SoupData data, CrystalSoup itemPrefab, GameObject render, SoupEffect effect) map) => map.data.SoupId == stewid); var (soupData, val, val2, soupEffect) = tuple; if (soupData != null || (Object)(object)val != (Object)null || (Object)(object)val2 != (Object)null || (Object)(object)soupEffect != (Object)null) { ((Component)Camera.main).GetComponent<PlayerInteract>().leveluptxt(tuple.Item1.ConsumeDescription); SoupEffect soupEffect2 = Object.Instantiate<SoupEffect>(tuple.Item4); ((Component)soupEffect2).gameObject.SetActive(true); soupEffect2.ApplyEffect(__instance); return false; } return true; } } } } namespace BlackMagicAPI.Patches.Managers { [HarmonyPatch(typeof(ColoseumManager))] internal class ColoseumManagerPatch { [HarmonyPatch("OnStartClient")] [HarmonyPrefix] [HarmonyPriority(800)] private static void OnStartClient_Prefix(ColoseumManager __instance) { foreach (var (spellData, val) in SpellManager.Mapping) { if (spellData.CanSpawnInColoseum) { __instance.LootTable.Add(((Component)val).gameObject); } } foreach (var (itemData, itemBehavior) in ItemManager.Mapping.OrderBy<(ItemData, ItemBehavior), int>(((ItemData data, ItemBehavior behavior) map) => map.data.Id)) { if (itemData.CanSpawnInColoseum) { __instance.LootTable.Add(((Component)itemBehavior).gameObject); } } } } [HarmonyPatch(typeof(DuendeManager))] internal class DuendeManagerPatch { [HarmonyPatch] private static class ServerCreatePagePatch { private static MethodBase TargetMethod() { return Utils.PatchRpcMethod<DuendeManager>("RpcLogic___ServerCreatePage"); } [HarmonyPrefix] [HarmonyPriority(800)] private static void Prefix(DuendeManager __instance, [HarmonyArgument(1)] ref int rand) { for (int i = 0; i < __instance.plt.Pages.Length; i++) { GameObject val = __instance.plt.Pages[i]; if (!((Object)(object)val == (Object)null)) { PageController component = val.GetComponent<PageController>(); int num; if (component == null) { PipeItem component2 = val.GetComponent<PipeItem>(); num = ((component2 != null) ? component2.GetItemID() : 0); } else { num = component.ItemID; } if (num == rand) { rand = i; return; } } } rand = 0; } } [HarmonyPatch("Awake")] [HarmonyPrefix] [HarmonyPriority(800)] private static void Awake_Prefix(DuendeManager __instance) { List<GameObject> list = __instance.DuendeTradeItems.ToList(); foreach (var item in ItemManager.Mapping.OrderBy<(ItemData, ItemBehavior), int>(((ItemData data, ItemBehavior behavior) m) => m.data.Id)) { if (item.Item1.CanGetFromTrade) { list.Add(((Component)item.Item2).gameObject); } } int num = 0; GameObject[] array = (GameObject[])(object)new GameObject[list.Count]; foreach (GameObject item2 in list) { array[num] = item2; num++; } __instance.DuendeTradeItems = array; } [HarmonyPatch("ServerCreatePage")] [HarmonyPrefix] [HarmonyPriority(800)] private static void ServerCreatePage_Prefix(DuendeManager __instance, ref int rand) { PageController component = __instance.plt.Pages[rand].GetComponent<PageController>(); int num; if (component == null) { PipeItem component2 = __instance.plt.Pages[rand].GetComponent<PipeItem>(); num = ((component2 != null) ? component2.GetItemID() : 0); } else { num = component.ItemID; } rand = num; } } [HarmonyPatch(typeof(MainMenuManagerNetworked))] internal class MainMenuManagerNetworkedPatch { [HarmonyPatch("Start")] [HarmonyPrefix] [HarmonyPriority(800)] private static void Start_Prefix(MainMenuManagerNetworked __instance) { foreach (SpellData item in SpellManager.Mapping.Select<(SpellData, PageController), SpellData>(((SpellData data, PageController page) value) => value.data)) { AddSpellCommand(__instance, item, item.Name); string[] subNames = item.SubNames; foreach (string name in subNames) { AddSpellCommand(__instance, item, name); } } } private static void AddSpellCommand(MainMenuManagerNetworked __instance, SpellData spellData, string name) { CustomSpellCommand customSpellCommand = ComponentHolderProtocol.AddComponent<CustomSpellCommand>((Object)(object)__instance); ((Behaviour)customSpellCommand).enabled = true; customSpellCommand.SpellData = spellData; customSpellCommand.SpellName = name; } } [HarmonyPatch(typeof(MainMenuManager))] internal class MainMenuManagerPatch { private static string Hash = ""; private static Text? text; [HarmonyPatch("Start")] [HarmonyPostfix] [HarmonyPriority(800)] private static void Start_Postfix() { //IL_006d: Unknown result type (might be due to invalid IL or missing references) GameObject? obj = Utils.FindInactive("Canvas (1)/Main/AccentMenu/Text (Legacy) (3)/Text (Legacy) (6)"); text = Object.Instantiate<Text>((obj != null) ? obj.GetComponent<Text>() : null); if ((Object)(object)text != (Object)null) { Transform transform = ((Component)text).transform; GameObject? obj2 = Utils.FindInactive("Canvas (1)/Main/AccentMenu/Text (Legacy) (3)"); transform.SetParent((obj2 != null) ? obj2.transform : null); ((Component)text).transform.position = new Vector3(1821f, 90f, 0f); text.text = Hash; } } internal static void UpdateHash(string hash) { Hash = hash; if ((Object)(object)text != (Object)null) { text.text = Hash; } } } [HarmonyPatch(typeof(PlayerRespawnManager))] internal class PlayerRespawnManagerPatch { private static List<(string reason, Texture2D icon)> DeathIcons = new List<(string, Texture2D)>(); [HarmonyPatch("OnStartClient")] [HarmonyPostfix] [HarmonyPriority(800)] private static void OnStartClient_Postfix(PlayerRespawnManager __instance) { foreach (var deathIcon in DeathIcons) { if (!((Object)(object)deathIcon.icon == (Object)null)) { __instance.dethicons.Add(deathIcon.reason, deathIcon.icon); } } } internal static bool AddDeathIcon(BaseUnityPlugin baseUnity, string deathReason, Texture2D deathIcon) { string deathReason2 = deathReason; if (DeathIcons.Any<(string, Texture2D)>(((string reason, Texture2D icon) data) => data.reason == deathReason2)) { BMAPlugin.Log.LogError((object)("Failed to register " + deathReason2 + " Death Icon from " + baseUnity.Info.Metadata.Name + ": Unable to register the same DeathReason twice!")); return false; } DeathIcons.Add((deathReason2, deathIcon)); return true; } } } namespace BlackMagicAPI.Patches.Items { [HarmonyPatch(typeof(ChestNetController1))] internal class ChestNetController1Patch { [HarmonyPatch] private static class ServerPlaceItemPatch { private static MethodBase TargetMethod() { return Utils.PatchRpcMethod<ChestNetController1>("RpcLogic___ServerPlaceItem"); } [HarmonyPrefix] [HarmonyPriority(800)] private static void Prefix(ChestNetController1 __instance, ref int itemid) { for (int i = 0; i < __instance.plt.Pages.Length; i++) { GameObject val = __instance.plt.Pages[i]; if (!((Object)(object)val == (Object)null)) { PageController component = val.GetComponent<PageController>(); int num; if (component == null) { PipeItem component2 = val.GetComponent<PipeItem>(); num = ((component2 != null) ? component2.GetItemID() : 0); } else { num = component.ItemID; } if (num == itemid) { itemid = i; return; } } } itemid = 0; } } [HarmonyPatch("PlaceItemIn")] [HarmonyPrefix] [HarmonyPriority(800)] private static void PlaceItemIn_Prefix(ChestNetController1 __instance, ref int itemid) { PageController component = __instance.plt.Pages[itemid].GetComponent<PageController>(); int num; if (component == null) { PipeItem component2 = __instance.plt.Pages[itemid].GetComponent<PipeItem>(); num = ((component2 != null) ? component2.GetItemID() : 0); } else { num = component.ItemID; } itemid = num; } } [HarmonyPatch(typeof(CraftingForge))] internal class CraftingForgePatch { [HarmonyPatch] private static class ServerCraftPatch { private static MethodBase TargetMethod() { return Utils.PatchRpcMethod<CraftingForge>("RpcLogic___ServerCraft"); } [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(CraftingForge __instance) { //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance.SlotItems[0] == (Object)null || (Object)(object)__instance.SlotItems[1] == (Object)null) { return true; } IItemInteraction component = __instance.SlotItems[0].GetComponent<IItemInteraction>(); IItemInteraction component2 = __instance.SlotItems[1].GetComponent<IItemInteraction>(); if (component != null && component2 != null && TryGetRecipeByIDs(component.GetItemID(), component2.GetItemID(), out GameObject result) && (Object)(object)result != (Object)null) { __instance.makepoof(); ((NetworkBehaviour)__instance).ServerManager.Despawn(__instance.SlotItems[0], (DespawnType?)null); ((NetworkBehaviour)__instance).ServerManager.Despawn(__instance.SlotItems[1], (DespawnType?)null); GameObject val = Object.Instantiate<GameObject>(result); val.transform.position = __instance.itemSpawnPoint.position; ((NetworkBehaviour)__instance).ServerManager.Spawn(val, (NetworkConnection)null, default(Scene)); __instance.SlotItems[0] = null; __instance.SlotItems[1] = null; __instance.CraftCleanUp(); __instance.craftingComplete = true; return false; } return true; } } internal static Dictionary<(IItemInteraction firstItem, IItemInteraction secondItem), GameObject> Recipes = new Dictionary<(IItemInteraction, IItemInteraction), GameObject>(); internal static bool RegisterRecipe(GameObject firstItemPrefap, GameObject secondItemPrefap, GameObject resultPrefap) { IItemInteraction component = firstItemPrefap.GetComponent<IItemInteraction>(); IItemInteraction component2 = secondItemPrefap.GetComponent<IItemInteraction>(); if (!TryGetRecipeByIDs(component.GetItemID(), component2.GetItemID(), out GameObject _)) { Recipes[(component, component2)] = resultPrefap; return true; } return false; } private static bool TryGetRecipeByIDs(int id1, int id2, out GameObject? result) { foreach (KeyValuePair<(IItemInteraction, IItemInteraction), GameObject> recipe in Recipes) { if ((recipe.Key.Item1.GetItemID() == id1 && recipe.Key.Item2.GetItemID() == id2) || (recipe.Key.Item1.GetItemID() == id2 && recipe.Key.Item2.GetItemID() == id1)) { result = recipe.Value; return true; } } result = null; return false; } [HarmonyPatch("OnStartClient")] [HarmonyPostfix] [HarmonyPriority(800)] private static void OnStartClient_Postfix(CraftingForge __instance) { ((MonoBehaviour)__instance).StartCoroutine(CoCustomCrafter(__instance)); } private static IEnumerator CoCustomCrafter(CraftingForge __instance) { while (((Behaviour)__instance).isActiveAndEnabled) { yield return null; if (__instance.SlotItems != null && __instance.SlotItems.Length >= 2 && !((Object)(object)__instance.SlotItems[0] == (Object)null) && !((Object)(object)__instance.SlotItems[1] == (Object)null) && __instance.craftingComplete) { GameObject obj = __instance.SlotItems[0]; IItemInteraction val = ((obj != null) ? obj.GetComponent<IItemInteraction>() : null); GameObject obj2 = __instance.SlotItems[1]; IItemInteraction val2 = ((obj2 != null) ? obj2.GetComponent<IItemInteraction>() : null); if (val != null && val2 != null && TryGetRecipeByIDs(val.GetItemID(), val2.GetItemID(), out GameObject _)) { __instance.craftingComplete = false; __instance.ServerCraft(); } } } } } [HarmonyPatch(typeof(CrystalSoup))] internal class CrystalSoupPatch { [HarmonyPatch("DisplayInteractUI")] [HarmonyPrefix] [HarmonyPriority(800)] private static bool DisplayInteractUI_Prefix(CrystalSoup __instance, ref string __result) { CrystalSoup __instance2 = __instance; (SoupData, CrystalSoup, GameObject, SoupEffect) tuple = SoupManager.Mapping.FirstOrDefault<(SoupData, CrystalSoup, GameObject, SoupEffect)>(((SoupData data, CrystalSoup itemPrefab, GameObject render, SoupEffect effect) map) => map.data.SoupId == __instance2.stewid); var (soupData, val, val2, soupEffect) = tuple; if (soupData != null || (Object)(object)val != (Object)null || (Object)(object)val2 != (Object)null || (Object)(object)soupEffect != (Object)null) { __result = "Grasp " + tuple.Item1.Name; return false; } return true; } } [HarmonyPatch(typeof(Generator2D))] internal class Generator2DPatch { [HarmonyPatch] private static class ServerPlaceItemPatch { private static MethodBase TargetMethod() { return Utils.PatchRpcMethod<Generator2D>("RpcLogic___ServerPlaceItem"); } [HarmonyPrefix] [HarmonyPriority(800)] private static void Prefix(Generator2D __instance, ref int itemid) { for (int i = 0; i < __instance.plt.Pages.Length; i++) { GameObject val = __instance.plt.Pages[i]; if (!((Object)(object)val == (Object)null)) { PageController component = val.GetComponent<PageController>(); int num; if (component == null) { PipeItem component2 = val.GetComponent<PipeItem>(); num = ((component2 != null) ? component2.GetItemID() : 0); } else { num = component.ItemID; } if (num == itemid) { itemid = i; return; } } } itemid = 0; } } [HarmonyPatch("PlaceItemIn")] [HarmonyPrefix] [HarmonyPriority(800)] private static void PlaceItemIn_Prefix(Generator2D __instance, ref int itemid) { PageController component = __instance.plt.Pages[itemid].GetComponent<PageController>(); int num; if (component == null) { PipeItem component2 = __instance.plt.Pages[itemid].GetComponent<PipeItem>(); num = ((component2 != null) ? component2.GetItemID() : 0); } else { num = component.ItemID; } itemid = num; } } [HarmonyPatch(typeof(PageController))] internal class PageControllerPatch { [HarmonyPatch] private static class RpcReaderServerCastSpellServerPatch { private static MethodBase TargetMethod() { return Utils.PatchRpcMethod<PageController>("RpcReader___Server_CastSpellServer"); } [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(PageController __instance, PooledReader PooledReader0, Channel channel, NetworkConnection conn) { //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_001e: 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_003d: 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) if (IsCustomSpell(__instance)) { GameObject ownerobj = ((Reader)PooledReader0).ReadGameObject(); Vector3 fwdVector = ((Reader)PooledReader0).ReadVector3(); int level = ((Reader)PooledReader0).ReadInt32(); Vector3 spawnpos = ((Reader)PooledReader0).ReadVector3(); DataWriter dataWriter = new DataWriter(); dataWriter.ReadToBuffer(PooledReader0); if (((NetworkBehaviour)__instance).IsServerInitialized) { CastSpellObs_Write(__instance, ownerobj, fwdVector, level, spawnpos, dataWriter); } return false; } return true; } } [HarmonyPatch] private static class RpcReader___Observers_CastSpellObsPatch { private static MethodBase TargetMethod() { return Utils.PatchRpcMethod<PageController>("RpcReader___Observers_CastSpellObs"); } [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(PageController __instance, PooledReader PooledReader0, Channel channel) { //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_001e: 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_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) if (IsCustomSpell(__instance)) { GameObject ownerobj = ((Reader)PooledReader0).ReadGameObject(); Vector3 fwdVector = ((Reader)PooledReader0).ReadVector3(); int level = ((Reader)PooledReader0).ReadInt32(); Vector3 spawnpos = ((Reader)PooledReader0).ReadVector3(); if (((NetworkBehaviour)__instance).IsClientInitialized) { CastSpellObs_Logic(__instance, ownerobj, fwdVector, level, spawnpos, PooledReader0); } return false; } return true; } } private static bool IsCustomSpell(PageController __instance) { return (Object)(object)__instance.spellprefab.GetComponent<SpellLogic>() != (Object)null; } private static SpellLogic GetSpellPrefab(PageController __instance) { return __instance.spellprefab.GetComponent<SpellLogic>(); } [HarmonyPatch("Interaction")] [HarmonyPrefix] [HarmonyPriority(800)] private static void Interaction_Prefix(PageController __instance, GameObject player) { if (IsCustomSpell(__instance)) { __instance.spellprefab.GetComponent<SpellLogic>()?.OnPageItemUse(player.GetComponent<PlayerMovement>(), __instance); } } [HarmonyPatch("CastSpellServer")] [HarmonyPrefix] [HarmonyPriority(800)] private static bool CastSpellServer_Prefix(PageController __instance, GameObject ownerobj, Vector3 fwdVector, int level, Vector3 spawnpos) { //IL_0023: 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_0040: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) if (IsCustomSpell(__instance)) { if (!((NetworkBehaviour)__instance).IsClientInitialized) { NetworkManagerExtensions.LogWarning(((NetworkBehaviour)__instance).NetworkManager, "Cannot complete action because client is not active. This may also occur if the object is not yet initialized, has deinitialized, or if it does not contain a NetworkObject component."); return false; } Channel val = (Channel)0; PooledWriter val2 = WriterPool.Retrieve(); ((Writer)val2).WriteGameObject(ownerobj); ((Writer)val2).WriteVector3(fwdVector); ((Writer)val2).WriteInt32(level); ((Writer)val2).WriteVector3(spawnpos); DataWriter dataWriter = new DataWriter(); GetSpellPrefab(__instance).WriteData(dataWriter, __instance, ownerobj.GetComponent<PlayerMovement>(), spawnpos, fwdVector, level); dataWriter.WriteFromBuffer(val2); dataWriter.Dispose(); ((NetworkBehaviour)__instance).SendServerRpc(0u, val2, val, (DataOrderType)0); val2.Store(); return false; } return true; } private static void CastSpellObs_Write(PageController __instance, GameObject ownerobj, Vector3 fwdVector, int level, Vector3 spawnpos, DataWriter dataWriter) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0029: 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_0050: Unknown result type (might be due to invalid IL or missing references) if (!((NetworkBehaviour)__instance).IsServerInitialized) { NetworkManagerExtensions.LogWarning(((NetworkBehaviour)__instance).NetworkManager, "Cannot complete action because server is not active. This may also occur if the object is not yet initialized, has deinitialized, or if it does not contain a NetworkObject component."); return; } Channel val = (Channel)0; PooledWriter val2 = WriterPool.Retrieve(); ((Writer)val2).WriteGameObject(ownerobj); ((Writer)val2).WriteVector3(fwdVector); ((Writer)val2).WriteInt32(level); ((Writer)val2).WriteVector3(spawnpos); dataWriter.WriteFromBuffer(val2); dataWriter.Dispose(); ((NetworkBehaviour)__instance).SendObserversRpc(1u, val2, val, (DataOrderType)0, false, false, false); val2.Store(); } private static void CastSpellObs_Logic(PageController __instance, GameObject ownerobj, Vector3 fwdVector, int level, Vector3 spawnpos, PooledReader PooledReader0) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_005a: 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) if (!((Object)(object)ownerobj != (Object)null)) { return; } GameObject obj = Object.Instantiate<GameObject>(__instance.spellprefab, spawnpos, Quaternion.identity); obj.SetActive(true); SpellLogic spellLogic = default(SpellLogic); if (obj.TryGetComponent<SpellLogic>(ref spellLogic)) { spellLogic.IsPrefab = false; DataWriter dataWriter = new DataWriter(); dataWriter.ReadToBuffer(PooledReader0); spellLogic.SyncData(dataWriter.GetObjectBuffer()); dataWriter.Dispose(); if (!spellLogic.CastSpell(ownerobj.GetComponent<PlayerMovement>(), __instance, spawnpos, fwdVector, level)) { __instance.ReinstatePageEmis(); __instance.PageCoolDownTimer = Time.time - __instance.CoolDown; } } } } } namespace BlackMagicAPI.Patches.Generation { [HarmonyPatch(typeof(ChestNetController))] internal class ChestNetControllerPatch { [HarmonyPatch] [HarmonyPriority(800)] private static class PiseverPatch { private static MethodBase TargetMethod() { return Utils.PatchRpcMethod<ChestNetController>("RpcLogic___pisever"); } [HarmonyPrefix] private static void Prefix(ChestNetController __instance) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) if (__instance.hasBeenOpened) { return; } foreach (var item in ItemManager.Mapping.OrderBy<(ItemData, ItemBehavior), int>(((ItemData data, ItemBehavior behavior) m) => m.data.Id)) { if (item.Item1.DebugForceSpawn) { ItemBehavior itemBehavior = Object.Instantiate<ItemBehavior>(item.Item2); ((Component)itemBehavior).transform.position = ((Component)__instance.ItemPoints[__instance.slotnum]).transform.position; itemBehavior.SetDefaultTransforms(); ((NetworkBehaviour)__instance).ServerManager.Spawn(((Component)itemBehavior).gameObject, (NetworkConnection)null, default(Scene)); if (__instance.slotnum >= 4) { __instance.slotnum = 0; } else { __instance.slotnum++; } } } foreach (var item2 in SpellManager.Mapping.OrderBy<(SpellData, PageController), int>(((SpellData data, PageController page) m) => m.data.Id)) { if (item2.Item1.DebugForceSpawn) { GameObject val = Object.Instantiate<GameObject>(((Component)item2.Item2).gameObject); val.transform.position = ((Component)__instance.ItemPoints[__instance.slotnum]).transform.position; ((NetworkBehaviour)__instance).ServerManager.Spawn(val, (NetworkConnection)null, default(Scene)); if (__instance.slotnum >= 4) { __instance.slotnum = 0; } else { __instance.slotnum++; } } } } } [HarmonyPatch("Awake")] [HarmonyPrefix] [HarmonyPriority(800)] private static void Awake_Prefix(ChestNetController __instance) { List<GameObject> list = __instance.Items.ToList(); foreach (var item in ItemManager.Mapping.OrderBy<(ItemData, ItemBehavior), int>(((ItemData data, ItemBehavior behavior) m) => m.data.Id)) { if (item.Item1.CanSpawnInTeamChest) { list.Add(((Component)item.Item2).gameObject); } } foreach (var item2 in SpellManager.Mapping.OrderBy<(SpellData, PageController), int>(((SpellData data, PageController page) m) => m.data.Id)) { if (item2.Item1.CanSpawnInTeamChest) { list.Add(((Component)item2.Item2).gameObject); } } int num = 0; GameObject[] array = (GameObject[])(object)new GameObject[list.Count]; foreach (GameObject item3 in list) { array[num] = item3; num++; } __instance.Items = array; } } [HarmonyPatch(typeof(DungeonGenerator))] internal class DungeonGeneratorPatch { [HarmonyPatch("Start")] [HarmonyPrefix] [HarmonyPriority(800)] private static void Start_Prefix(DungeonGenerator __instance) { PageLootTable component = ((Component)__instance).GetComponent<PageLootTable>(); if (!((Object)(object)component != (Object)null)) { return; } List<GameObject> list = component.Pages.ToList(); foreach (var item2 in SpellManager.Mapping.OrderBy<(SpellData, PageController), int>(((SpellData data, PageController page) m) => m.page.ItemID)) { PageController item = item2.Item2; list.Add(((Component)item).gameObject); } PageLootTable val = component; int num = 0; GameObject[] array = (GameObject[])(object)new GameObject[list.Count]; foreach (GameObject item3 in list) { array[num] = item3; num++; } val.Pages = array; } } [HarmonyPatch(typeof(PaperInteract))] internal class PaperInteractPatch { [HarmonyPatch("Start")] [HarmonyPostfix] [HarmonyPriority(800)] private static void Start_Postfix(PaperInteract __instance) { } } } namespace BlackMagicAPI.Network { public class DataWriter : IDisposable { private readonly List<(Type type, object value)> _dataBuffer = new List<(Type, object)>(); public void Write<T>(T value) { if (value != null) { _dataBuffer.Add((typeof(T), value)); } } public void Write(object value) { if (value == null) { throw new ArgumentNullException("value"); } _dataBuffer.Add((value.GetType(), value)); } internal void WriteFromBuffer(PooledWriter writer) { ((Writer)writer).Write<byte>((byte)_dataBuffer.Count); foreach (var (type, obj) in _dataBuffer) { ((Writer)writer).Write<string>(type.AssemblyQualifiedName); FishUtils.WriteFast(writer, type, obj); } } internal void ReadToBuffer(PooledReader reader) { ClearBuffer(); byte b = ((Reader)reader).Read<byte>(); for (int i = 0; i < b; i++) { string text = ((Reader)reader).ReadString(); Type type = Type.GetType(text) ?? throw new InvalidOperationException("Type not found: " + text); object obj = FishUtils.ReadFast(reader, type); _dataBuffer.Add((obj.GetType(), obj)); } } internal object[] GetObjectBuffer() { object[] array = new object[_dataBuffer.Count]; for (int i = 0; i < _dataBuffer.Count; i++) { array[i] = _dataBuffer[i].value; } return array; } internal void ClearBuffer() { _dataBuffer.Clear(); } public void Dispose() { ClearBuffer(); GC.SuppressFinalize(this); } } } namespace BlackMagicAPI.Modules.Soups { public abstract class SoupEffect : MonoBehaviour { internal int Id { get; set; } public abstract void ApplyEffect(PlayerMovement player); public virtual void OnPrefabCreatedAutomatically(GameObject prefab) { } public void DisposeEffect() { Object.Destroy((Object)(object)((Component)this).gameObject); } } } namespace BlackMagicAPI.Modules.Spells { public abstract class ItemData : ICompatibility { public Version CompatibilityVersion => CompatibilityManager.GetReferencedVersion(GetType()); public abstract string Name { get; } public virtual bool DebugForceSpawn => false; public virtual bool CanSpawnInTeamChest => false; public virtual bool CanSpawnInColoseum => true; public virtual bool CanGetFromTrade => false; public virtual bool KeepOnDeath => false; public int Id { get; internal set; } public BaseUnityPlugin? Plugin { get; internal set; } internal Sprite? GetUiSprite() { if ((Object)(object)Plugin == (Object)null) { return null; } string path = Path.Combine(Path.GetDirectoryName(Plugin.Info.Location), "Sprites", Name.Replace(" ", "") + "_Ui.png"); if (File.Exists(path)) { return Utils.LoadSpriteFromDisk(path); } return Assembly.GetExecutingAssembly().LoadSpriteFromResources("BlackMagicAPI.Resources.Items.Item_Ui.png"); } public virtual AudioClip? GetPickupAudio() { if ((Object)(object)Plugin == (Object)null) { return null; } string text = Path.Combine(Path.GetDirectoryName(Plugin.Info.Location), "Sounds", Name.Replace(" ", "") + "_Pickup.wav"); if (File.Exists(text)) { return Utils.LoadWavFromDisk(text); } return null; } public virtual AudioClip? GetEquipAudio() { if ((Object)(object)Plugin == (Object)null) { return null; } string text = Path.Combine(Path.GetDirectoryName(Plugin.Info.Location), "Sounds", Name.Replace(" ", "") + "_Equip.wav"); if (File.Exists(text)) { return Utils.LoadWavFromDisk(text); } return null; } public virtual Task<ItemBehavior?> GetItemPrefab() { return Task.FromResult<ItemBehavior>(null); } } public abstract class SoupData : ICompatibility { public Version CompatibilityVersion => CompatibilityManager.GetReferencedVersion(GetType()); public abstract string Name { get; } public abstract string ConsumeDescription { get; } public abstract Color SoupColor { get; } public int ItemId { get; internal set; } public int SoupId { get; internal set; } public BaseUnityPlugin? Plugin { get; internal set; } internal int RequiredItemId { get; set; } = -1; internal Sprite? GetUiSprite() { if ((Object)(object)Plugin == (Object)null) { return null; } string path = Path.Combine(Path.GetDirectoryName(Plugin.Info.Location), "Sprites", Name.Replace(" ", "") + "_Ui.png"); if (File.Exists(path)) { return Utils.LoadSpriteFromDisk(path); } return Assembly.GetExecutingAssembly().LoadSpriteFromResources("BlackMagicAPI.Resources.Items.Empty_Ui.png"); } public virtual Task<SoupEffect?> GetEffectPrefab() { return Task.FromResult<SoupEffect>(null); } public virtual void SetObjectVisualTransform(GameObject render) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0034: 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: Unknown result type (might be due to invalid IL or missing references) render.transform.localPosition = new Vector3(-0.0003f, 0.004f, 0.004f); render.transform.rotation = Quaternion.Euler(-3f, 0f, 0f); render.transform.localScale = render.transform.localScale * 0.03f; } } internal class CustomSpellCommand : MonoBehaviour, ISpellCommand { internal string SpellName { get; set; } = "[]"; internal SpellData SpellData { get; [param: AllowNull] set; } private PlayerInventory? playerInventory { get; set; } private SpeechRecognizer? speechRecognizer { get; set; } public void Awake() { Resources.FindObjectsOfTypeAll<VoiceControlListener>()?.First()?.SpellPages?.Add((ISpellCommand)(object)this); } public string GetSpellName() { return SpellName.ToLower(); } public void ResetVoiceDetect() { if ((Object)(object)speechRecognizer == (Object)null) { SpeechRecognizer val = default(SpeechRecognizer); if (!((Component)this).TryGetComponent<SpeechRecognizer>(ref val)) { Debug.LogError((object)"ResetVoiceDetect: SpeechRecognizer component not found"); return; } speechRecognizer = val; } string text = SpellName.ToLower(); if (!speechRecognizer.Vocabulary.Contains(text)) { speechRecognizer.Vocabulary.Add(text); Debug.Log((object)("Added spell name to vocabulary: " + text)); } } public void TryCastSpell() { if ((Object)(object)playerInventory == (Object)null) { PlayerInventory val = default(PlayerInventory); if (!((Component)((Component)Camera.main).transform.parent).TryGetComponent<PlayerInventory>(ref val)) { Debug.LogError((object)"Failed to find PlayerInventory"); return; } playerInventory = val; } if ((Object)(object)speechRecognizer == (Object)null) { SpeechRecognizer val2 = default(SpeechRecognizer); if (!((Component)this).TryGetComponent<SpeechRecognizer>(ref val2)) { Debug.LogError((object)"Failed to find SpeechRecognizer"); return; } speechRecognizer = val2; } if (playerInventory.GetEquippedItemID() == SpellData.Id) { playerInventory.cPageSpell(); } ((SpeechProcessor)speechRecognizer).StopProcessing(); ((MonoBehaviour)this).StartCoroutine(CoWaitRestartVoiceDetect()); } private IEnumerator CoWaitRestartVoiceDetect() { while (true) { SpeechRecognizer? obj = speechRecognizer; if (obj != null && (int)((SpeechProcessor)obj).State <= 0) { break; } yield return null; } SpeechRecognizer? obj2 = speechRecognizer; if (obj2 != null) { ((SpeechProcessor)obj2).StartProcessing(); } } } public class Spell<SD> where SD : SpellData { public static SD? GetData() { return (SD)SpellManager.Mapping.FirstOrDefault<(SpellData, PageController)>(((SpellData data, PageController page) map) => map.data.GetType() == typeof(SD)).Item1; } public static PageController? GetPagePrefab() { return SpellManager.Mapping.FirstOrDefault<(SpellData, PageController)>(((SpellData data, PageController page) map) => map.data.GetType() == typeof(SD)).Item2; } public static SpellLogic? GetLogicPrefab() { PageController? pagePrefab = GetPagePrefab(); if (pagePrefab == null) { return null; } return pagePrefab.spellprefab.GetComponent<SpellLogic>(); } public static L? GetLogicPrefab<L>() where L : SpellLogic { PageController? pagePrefab = GetPagePrefab(); if (pagePrefab == null) { return null; } return pagePrefab.spellprefab.GetComponent<L>(); } public static SpellLogic?[] GetLogicInstances() { if (SpellLogic.Instances.TryGetValue(typeof(SD).FullName, out List<SpellLogic> value)) { List<SpellLogic> list = value; int num = 0; SpellLogic[] array = new SpellLogic[list.Count]; { foreach (SpellLogic item in list) { array[num] = item; num++; } return array; } } return Array.Empty<SpellLogic>(); } public static SL?[] GetLogicInstances<SL>() where SL : SpellLogic { if (SpellLogic.Instances.TryGetValue(typeof(SD).FullName, out List<SpellLogic> value)) { return (from logic in value select logic as SL into logic where (Object)(object)logic != (Object)null select logic).ToArray(); } return Array.Empty<SL>(); } } public abstract class SpellData : ICompatibility { public Version CompatibilityVersion => CompatibilityManager.GetReferencedVersion(GetType()); public virtual SpellType SpellType => SpellType.Page; public virtual bool DebugForceSpawn => false; public virtual bool CanSpawnInTeamChest => false; public virtual bool CanSpawnInColoseum => true; public virtual bool KeepOnDeath => false; public abstract string Name { get; } public virtual string[] SubNames => Array.Empty<string>(); public abstract float Cooldown { get; } public abstract Color GlowColor { get; } public int Id { get; internal set; } public BaseUnityPlugin? Plugin { get; internal set; } internal Sprite? GetUiSprite() { if ((Object)(object)Plugin == (Object)null) { return null; } string path = Path.Combine(Path.GetDirectoryName(Plugin.Info.Location), "Sprites", Name.Replace(" ", "") + "_Ui.png"); if (File.Exists(path)) { return Utils.LoadSpriteFromDisk(path); } return Assembly.GetExecutingAssembly().LoadSpriteFromResources("BlackMagicAPI.Resources.Items.Item_Ui.png"); } public virtual Texture2D? GetMainTexture() { if ((Object)(object)Plugin == (Object)null) { return null; } string path = Path.Combine(Path.GetDirectoryName(Plugin.Info.Location), "Sprites", Name.Replace(" ", "") + "_Main.png"); if (File.Exists(path)) { return Utils.LoadTextureFromDisk(path); } return Assembly.GetExecutingAssembly().LoadTextureFromResources("BlackMagicAPI.Resources.Items.Item_Main.png"); } public virtual Texture2D? GetEmissionTexture() { if ((Object)(object)Plugin == (Object)null) { return null; } string path = Path.Combine(Path.GetDirectoryName(Plugin.Info.Location), "Sprites", Name.Replace(" ", "") + "_Emission.png"); if (File.Exists(path)) { return Utils.LoadTextureFromDisk(path); } return Assembly.GetExecutingAssembly().LoadTextureFromResources("BlackMagicAPI.Resources.Items.Item_Emission.png"); } public virtual Task<SpellLogic?> GetLogicPrefab() { return Task.FromResult<SpellLogic>(null); } internal void SetUpPage(PageController page, SpellLogic logic) { page.ItemID = Id; page.CoolDown = Cooldown; page.PageCoolDownTimer = 0f - Cooldown; page.spellprefab = ((Component)logic).gameObject; SetMaterial(((Renderer)page.pagerender).material); } internal void SetMaterial(Material material) { Texture2D mainTexture = GetMainTexture(); if ((Object)(object)mainTexture != (Object)null) { material.SetTexture("_bk", (Texture)(object)mainTexture); } Texture2D emissionTexture = GetEmissionTexture(); if ((Object)(object)emissionTexture != (Object)null) { material.SetTexture("_emistexture", (Texture)(object)emissionTexture); } } internal void SetLight(Light? light) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)light == (Object)null)) { light.color = GlowColor; } } } public abstract class SpellLogic : MonoBehaviour, ISpell { internal static Dictionary<string, List<SpellLogic>> Instances = new Dictionary<string, List<SpellLogic>>(); [SerializeField] [Tooltip("Spelldata Fullname, (DO NOT SET)")] internal string? SpellDataTypeName; [SerializeField] [Tooltip("Keep item on death, (DO NOT SET)")] internal bool KeepOnDeath; public bool IsPrefab { get; internal set; } = true; protected virtual void Awake() { ((MonoBehaviour)this).StartCoroutine(CoAwake()); } protected virtual void OnDestroy() { if (SpellDataTypeName != null && Instances.TryGetValue(SpellDataTypeName, out List<SpellLogic> value)) { value.Remove(this); if (value.Count <= 0) { Instances.Remove(SpellDataTypeName); } } } private IEnumerator CoAwake() { while (SpellDataTypeName == null) { yield return null; } float wait = 0f; while (IsPrefab) { wait += Time.deltaTime; if (wait > 5f) { yield break; } yield return null; } if (!Instances.ContainsKey(SpellDataTypeName)) { Instances[SpellDataTypeName] = new List<SpellLogic>(); } Instances[SpellDataTypeName].Add(this); } public void PlayerSetup(GameObject ownerobj, Vector3 fwdVector, int level) { } public abstract bool CastSpell(PlayerMovement caster, PageController page, Vector3 spawnPos, Vector3 viewDirectionVector, int castingLevel); public virtual void OnPageItemUse(PlayerMovement itemOwner, PageController page) { } public virtual void OnPrefabCreatedAutomatically(GameObject prefab) { } public virtual void WriteData(DataWriter dataWriter, PageController page, PlayerMovement caster, Vector3 spawnPos, Vector3 viewDirectionVector, int level) { } public virtual void SyncData(object[] values) { } public void DisposeSpell() { Object.Destroy((Object)(object)((Component)this).gameObject); } } } namespace BlackMagicAPI.Modules.Items { [RequireComponent(typeof(AudioSource))] public abstract class ItemBehavior : NetworkBehaviour, IInteractable, IItemInteraction { [SerializeField] [Tooltip("The visual representation of the item in the game world, be sure that it's parenting to this object!")] public GameObject? ItemRender; [SerializeField] [Tooltip("Sound played when the item is picked up")] public AudioClip? EquipSound; [SerializeField] [Tooltip("Sound played when the item is dropped")] public AudioClip? DropSound; [SerializeField] [Tooltip("Display name of the item, (DO NOT SET)")] internal string Name = "???"; [SerializeField] [Tooltip("Unique identifier for the item type, (DO NOT SET)")] internal int Id; [SerializeField] [Tooltip("Keep item on death, (DO NOT SET)")] internal bool KeepOnDeath; private bool waitingInitItem; private bool netInit; public PlayerMovement? LastOwner { get; private set; } protected virtual void Awake() { NetworkInitialize(); } public int GetItemID() { return Id; } public string DisplayInteractUI(GameObject player) { return "Grasp " + Name; } public void ItemInit() { GameObject? itemRender = ItemRender; if (itemRender != null) { itemRender.SetActive(true); } PlayEquipSound(); if (!waitingInitItem) { ((MonoBehaviour)this).StartCoroutine(CoWaitInitItem()); } } public void ItemInitObs() { ItemInit(); } private IEnumerator CoWaitInitItem() { waitingInitItem = true; float wait = 0f; while (true) { Transform transform = ((Component)this).transform; object obj; if (transform == null) { obj = null; } else { Transform parent = transform.parent; obj = ((parent != null) ? ((Object)parent).name : null); } if (!((string?)obj != "pikupact")) { break; } wait += Time.deltaTime; if (wait >= 10f) { waitingInitItem = false; yield break; } yield return null; } LastOwner = ((Component)((Component)this).transform.parent.parent).GetComponent<PlayerMovement>(); OnItemEquipped(LastOwner); waitingInitItem = false; } public void Interact(GameObject player) { player.GetComponent<PlayerInventory>().Pickup(((Component)this).gameObject); } public void Interaction(GameObject player) { OnItemUse(player.GetComponent<PlayerMovement>()); } protected abstract void OnItemUse(PlayerMovement itemOwner); public virtual void OnItemEquipped(PlayerMovement itemOwner) { } public virtual void OnItemDropped(PlayerMovement itemOwner) { } public void Interaction2(GameObject subject) { } public void DropItem() { //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_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: 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_003e: Unknown result type (might be due to invalid IL or missing references) LayerMask val = LayerMask.op_Implicit(192); RaycastHit val2 = default(RaycastHit); if (Physics.Raycast(((Component)this).transform.position, Vector3.down, ref val2, 100f, ~LayerMask.op_Implicit(val))) { SetDefaultTransforms(); ((Component)this).transform.position = ((RaycastHit)(ref val2)).point; } GameObject? itemRender = ItemRender; if (itemRender != null) { itemRender.SetActive(true); } PlayDropSound(); if ((Object)(object)LastOwner != (Object)null) { OnItemDropped(LastOwner); } } public void HideItem() { GameObject? itemRender = ItemRender; if (itemRender != null) { itemRender.SetActive(false); } } public void PlayDropSound() { if (!((Object)(object)DropSound == (Object)null)) { AudioSource component = ((Component)this).GetComponent<AudioSource>(); if (component != null) { component.PlayOneShot(DropSound); } } } private void PlayEquipSound() { if (!((Object)(object)EquipSound == (Object)null)) { AudioSource component = ((Component)this).GetComponent<AudioSource>(); if (component != null) { component.PlayOneShot(EquipSound); } } } [Obsolete("Use SetDefaultTransforms instead.")] public virtual void SetScale() { SetDefaultTransforms(); } public virtual void SetDefaultTransforms() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) ((Component)this).transform.localScale = Vector3.one; ((Component)this).transform.rotation = Quaternion.Euler(-90f, 0f, 0f); } public virtual void SetTransformOnCraftingForge() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) ((Component)this).transform.localScale = Vector3.one; ((Component)this).transform.rotation = Quaternion.Euler(-90f, 0f, 0f); } internal void SetAudioClips(AudioClip drop, AudioClip equip) { DropSound = drop; EquipSound = equip; } public virtual void OnPrefabCreatedAutomatically(GameObject prefab) { } public virtual void AddColliderToPrefab(GameObject prefab) { prefab.AddComponent<BoxCollider>(); } private void NetworkInitialize() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown if (!netInit) { netInit = true; ((NetworkBehaviour)this).RegisterServerRpc(0u, new ServerRpcDelegate(HandleSyncClientCmd)); ((NetworkBehaviour)this).RegisterObserversRpc(1u, new ClientRpcDelegate(HandleSyncClientRpc)); } } protected void SendClientCmd(uint cmdId, params object[] args) { if (!((NetworkBehaviour)this).IsClientInitialized) { NetworkManagerExtensions.LogWarning(((NetworkBehaviour)this).NetworkManager, "Cannot complete action because client is not active. This may also occur if the object is not yet initialized, has deinitialized, or if it does not contain a NetworkObject component."); return; } PooledWriter val = WriterPool.Retrieve(); ((Writer)val).Write<uint>(cmdId); DataWriter dataWriter = new DataWriter(); foreach (object value in args) { dataWriter.Write(value); } dataWriter.WriteFromBuffer(val); dataWriter.Dispose(); ((NetworkBehaviour)this).SendServerRpc(0u, val, (Channel)0, (DataOrderType)0); val.Store(); } protected virtual void HandleSyncClient(uint cmdId, object[] args) { } private void HandleSyncClientCmd(PooledReader reader, Channel channel, NetworkConnection sender) { uint cmdId = ((Reader)reader).Read<uint>(); DataWriter dataWriter = new DataWriter(); dataWriter.ReadToBuffer(reader); HandleSyncClient(cmdId, dataWriter.GetObjectBuffer()); dataWriter.Dispose(); } protected void SendItemSync(uint syncId, params object[] args) { if (!((NetworkBehaviour)this).IsClientInitialized) { NetworkManagerExtensions.LogWarning(((NetworkBehaviour)this).NetworkManager, "Cannot complete action because client is not active. This may also occur if the object is not yet initialized, has deinitialized, or if it does not contain a NetworkObject component."); return; } PooledWriter val = WriterPool.Retrieve(); ((Writer)val).Write<uint>(syncId); DataWriter dataWriter = new DataWriter(); foreach (object value in args) { dataWriter.Write(value); } dataWriter.WriteFromBuffer(val); dataWriter.Dispose(); ((NetworkBehaviour)this).SendObserversRpc(1u, val, (Channel)0, (DataOrderType)0, false, false, false); val.Store(); } protected virtual void HandleItemSync(uint syncId, object[] args) { } private void HandleSyncClientRpc(PooledReader reader, Channel channel) { uint syncId = ((Reader)reader).Read<uint>(); DataWriter dataWriter = new DataWriter(); dataWriter.ReadToBuffer(reader); HandleItemSync(syncId, dataWriter.GetObjectBuffer()); dataWriter.Dispose(); } } } namespace BlackMagicAPI.Managers { public class BlackMagicManager { public static T? SpawnItem<T>(Vector3? position = null, Quaternion? rotation = null) where T : IItemInteraction { //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) NetworkManager val = NetworkManager.Instances.FirstOrDefault() ?? throw new InvalidOperationException("Can not spawn iten when the NetworkManager is null!"); if (!val.IsHostStarted) { BMAPlugin.Log.LogError((object)("Failed to spawn item " + typeof(T).Name + ": Items can only be spawned as host.")); return default(T); } object obj = GetItemPrefab<T>(); MonoBehaviour val2 = (MonoBehaviour)((obj is MonoBehaviour) ? obj : null); if (val2 != null) { MonoBehaviour val3 = Object.Instantiate<MonoBehaviour>(val2); if (position.HasValue) { ((Component)val3).transform.position = position.Value; } if (rotation.HasValue) { ((Component)val3).transform.rotation = rotation.Value; } val.ServerManager.Spawn(((Component)val3).gameObject, (NetworkConnection)null, default(Scene)); BMAPlugin.Log.LogInfo((object)("Successfully spawned item " + typeof(T).Name + ".")); return (T)(IItemInteraction)val3; } BMAPlugin.Log.LogError((object)("Failed to spawn item " + typeof(T).Name + ": Item prefab returned null.")); return default(T); } public static PageController? SpawnSpell<T>(Vector3? position = null, Quaternion? rotation = null) where T : ISpell { //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) NetworkManager val = NetworkManager.Instances.FirstOrDefault() ?? throw new InvalidOperationException("Can not spawn iten when the NetworkManager is null!"); if (!val.IsHostStarted) { BMAPlugin.Log.LogError((object)("Failed to spawn spell page " + typeof(T).Name + ": Spells can only be spawned as host.")); return null; } PageController spellPagePrefab = GetSpellPagePrefab<T>(); if (spellPagePrefab != null) { PageController val2 = spellPagePrefab; PageController val3 = Object.Instantiate<PageController>(val2); if (position.HasValue) { ((Component)val3).transform.position = position.Value; } if (rotation.HasValue) { ((Component)val3).transform.rotation = rotation.Value; } val.ServerManager.Spawn(((Component)val3).gameObject, (NetworkConnection)null, default(Scene)); BMAPlugin.Log.LogInfo((object)("Successfully spawned spell page " + typeof(T).Name + ".")); return val3; } BMAPlugin.Log.LogError((object)("Failed to spawn spell page " + typeof(T).Name + ": Spells prefab returned null.")); return null; } public static void RegisterCraftingRecipe(BaseUnityPlugin plugin, Type IItemInteraction_FirstType, Type IItemInteraction_SecondType, Type IItemInteraction_ResultType) { ItemManager.RegisterCraftingRecipe(plugin, IItemInteraction_FirstType, IItemInteraction_SecondType, IItemInteraction_ResultType); } public static T? GetItemPrefab<T>() where T : IItemInteraction { return ItemManager.GetItemPrefab<T>(); } public static void RegisterItem(BaseUnityPlugin plugin, Type ItemDataType, Type? ItemBehaviorType = null) { ItemManager.RegisterItem(plugin, ItemDataType, ItemBehaviorType); } public static void RegisterSoup(BaseUnityPlugin plugin, Type IItemInteraction, Type SoupDataType, Type? SoupEffectType = null) { SoupManager.RegisterSoup(plugin, IItemInteraction, SoupDataType, SoupEffectType); } public static PageController GetSpellPagePrefab<T>() where T : ISpell { return SpellManager.GetSpellPagePrefab<T>(); } public static T GetSpellLogicPrefab<T>() where T : ISpell { return SpellManager.GetSpellLogicPrefab<T>(); } public static void RegisterSpell(BaseUnityPlugin plugin, Type SpellDataType, Type? SpellLogicType = null) { SpellManager.RegisterSpell(plugin, SpellDataType, SpellLogicType); } public static void RegisterDeathIcon(BaseUnityPlugin plugin, string deathReason, string spriteName) { string path = Path.Combine(Path.GetDirectoryName(plugin.Info.Location), "Sprites", spriteName.Replace(".png", "") + ".png"); if (File.Exists(path)) { Texture2D val = Utils.LoadTextureFromDisk(path); if (!((Object)(object)val == (Object)null) && PlayerRespawnManagerPatch.AddDeathIcon(plugin, deathReason, val)) { BMAPlugin.Log.LogInfo((object)("Successfully registered " + deathReason + " Death Icon from " + plugin.Info.Metadata.GUID)); } } } public static void RegisterDeathIcon(BaseUnityPlugin plugin, string deathReason, Texture2D icon) { if (!((Object)(object)icon == (Object)null) && PlayerRespawnManagerPatch.AddDeathIcon(plugin, deathReason, icon)) { BMAPlugin.Log.LogInfo((object)("Successfully registered " + deathReason + " Death Icon from " + plugin.Info.Metadata.GUID)); } } } internal enum CompatibilityResult { Successful, NotAssignable, NoProperty, OldVersion, Error } internal class CompatibilityManager { internal static Version COMPATIBILITY_VERSION { get; } = typeof(CompatibilityManager).Assembly.GetName().Version; internal static Version GetReferencedVersion(Type type) { return type?.Assembly?.GetReferencedAssemblies()?.FirstOrDefault((AssemblyName assembly) => assembly.Name == "BlackMagicAPI")?.Version ?? new Version("0.0.0.0"); } private static bool CheckCompatibility(Version version) { if (version == COMPATIBILITY_VERSION) { return true; } return false; } private static bool CheckForProperty(Type type) { if (type.GetProperty("CompatibilityVersion", BindingFlags.Instance | BindingFlags.Public) == null) { return false; } return true; } internal static CompatibilityResult CheckSpellCompatibility(Type spellDataType) { if (!typeof(SpellData).IsAssignableFrom(spellDataType)) { return CompatibilityResult.NotAssignable; } if (!CheckForProperty(spellDataType)) { return CompatibilityResult.NoProperty; } try { if (Activator.CreateInstance(spellDataType) is SpellData spellData && CheckCompatibility(spellData.CompatibilityVersion)) { return CompatibilityResult.Successful; } return CompatibilityResult.OldVersion; } catch { return CompatibilityResult.Error; } } internal static CompatibilityResult CheckItemCompatibility(Type itemDataType) { if (!typeof(ItemData).IsAssignableFrom(itemDataType)) { return CompatibilityResult.NotAssignable; } if (!CheckForProperty(itemDataType)) { return CompatibilityResult.NoProperty; } try { if (Activator.CreateInstance(itemDataType) is ItemData itemData && CheckCompatibility(itemData.CompatibilityVersion)) { return CompatibilityResult.Successful; } return CompatibilityResult.OldVersion; } catch { return CompatibilityResult.Error; } } } internal static class ItemManager { private static readonly List<Type> registeredTypes = new List<Type>(); internal static List<(ItemData data, ItemBehavior behavior)> Mapping = new List<(ItemData, ItemBehavior)>(); internal static readonly Dictionary<Type, IItemInteraction> PrefabMapping = new Dictionary<Type, IItemInteraction>(); internal static void RegisterCraftingRecipe(BaseUnityPlugin baseUnity, Type IItemInteraction_FirstType, Type IItemInteraction_SecondType, Type IItemInteraction_ResultType) { if (IItemInteraction_FirstType.IsInterface) { BMAPlugin.Log.LogError((object)("Failed to register item recipe from " + baseUnity.Info.Metadata.Name + ": IItemInteraction_FirstType can not be directly IItemInteraction interface!")); ModSyncManager.FailedRecipes.Add((baseUnity, IItemInteraction_FirstType, IItemInteraction_SecondType, IItemInteraction_ResultType)); return; } if (IItemInteraction_SecondType.IsInterface) { BMAPlugin.Log.LogError((object)("Failed to register item recipe from " + baseUnity.Info.Metadata.Name + ": IItemInteraction_SecondType can not be directly IItemInteraction interface!")); ModSyncManager.FailedRecipes.Add((baseUnity, IItemInteraction_FirstType, IItemInteraction_SecondType, IItemInteraction_ResultType)); return; } if (IItemInteraction_ResultType.IsInterface) { BMAPlugin.Log.LogError((object)("Failed to register item recipe from " + baseUnity.Info.Metadata.Name + ": IItemInteraction_ResultType can not be directly IItemInteraction interface!")); ModSyncManager.FailedRecipes.Add((baseUnity, IItemInteraction_FirstType, IItemInteraction_SecondType, IItemInteraction_ResultType)); return; } if (!typeof(IItemInteraction).IsAssignableFrom(IItemInteraction_FirstType) && !typeof(ISpell).IsAssignableFrom(IItemInteraction_FirstType)) { BMAPlugin.Log.LogError((object)("Failed to register item recipe from " + baseUnity.Info.Metadata.Name + ": IItemInteraction_FirstType must be inherited from IItemInteraction interface!")); ModSyncManager.FailedRecipes.Add((baseUnity, IItemInteraction_FirstType, IItemInteraction_SecondType, IItemInteraction_ResultType)); return; } if (!typeof(IItemInteraction).IsAssignableFrom(IItemInteraction_SecondType) && !typeof(ISpell).IsAssignableFrom(IItemInteraction_SecondType)) { BMAPlugin.Log.LogError((object)("Failed to register item recipe from " + baseUnity.Info.Metadata.Name + ": IItemInteraction_SecondType must be inherited from IItemInteraction interface!")); ModSyncManager.FailedRecipes.Add((baseUnity, IItemInteraction_FirstType, IItemInteraction_SecondType, IItemInteraction_ResultType)); return; } if (!typeof(IItemInteraction).IsAssignableFrom(IItemInteraction_ResultType) && !typeof(ISpell).IsAssignableFrom(IItemInteraction_SecondType)) { BMAPlugin.Log.LogError((object)("Failed to register item recipe from " + baseUnity.Info.Metadata.Name + ": IItemInteraction_ResultType must be inherited from IItemInteraction interface!")); ModSyncManager.FailedRecipes.Add((baseUnity, IItemInteraction_FirstType, IItemInteraction_SecondType, IItemInteraction_ResultType)); return; } MonoBehaviour val = (MonoBehaviour)((!typeof(ISpell).IsAssignableFrom(IItemInteraction_FirstType)) ? ((object)/*isinst with value type is only supported in some contexts*/) : ((object)GetPageFromSpellType(IItemInteraction_FirstType))); if ((Object)(object)val != (Object)null) { MonoBehaviour val2 = (MonoBehaviour)((!typeof(ISpell).IsAssignableFrom(IItemInteraction_SecondType)) ? ((object)/*isinst with value type is only supported in some contexts*/) : ((object)GetPageFromSpellType(IItemInteraction_SecondType))); if ((Object)(object)val2 != (Object)null) { MonoBehaviour val3 = (MonoBehaviour)((!typeof(ISpell).IsAssignableFrom(IItemInteraction_SecondType)) ? ((object)/*isinst with value type is only supported in some contexts*/) : ((object)GetPageFromSpellType(IItemInteraction_ResultType))); if ((Object)(object)val3 != (Object)null) { if (CraftingForgePatch.RegisterRecipe(((Component)val).gameObject, ((Component)val2).gameObject, ((Component)val3).gameObject)) { BMAPlugin.Log.LogInfo((object)$"Successfully registered ({IItemInteraction_FirstType}, {IItemInteraction_SecondType} => {IItemInteraction_ResultType} recipe from {baseUnity.Info.Metadata.GUID}"); } else { BMAPlugin.Log.LogError((object)("Failed to register item recipe from " + baseUnity.Info.Metadata.Name + ": You cannot register a recipe that's already been registered!")); ModSyncManager.FailedRecipes.Add((baseUnity, IItemInteraction_FirstType, IItemInteraction_SecondType, IItemInteraction_ResultType)); } } else { BMAPlugin.Log.LogError((object)("Failed to register item recipe from " + baseUnity.Info.Metadata.Name + ": Unable to find item prefab for " + IItemInteraction_ResultType.Name + "!")); ModSyncManager.FailedRecipes.Add((baseUnity, IItemInteraction_FirstType, IItemInteraction_SecondType, IItemInteraction_ResultType)); } } else { BMAPlugin.Log.LogError((object)("Failed to register item recipe from " + baseUnity.Info.Metadata.Name + ": Unable to find item prefab for " + IItemInteraction_SecondType.Name + "!")); ModSyncManager.FailedRecipes.Add((baseUnity, IItemInteraction_FirstType, IItemInteraction_SecondType, IItemInteraction_ResultType)); } } else { BMAPlugin.Log.LogError((object)("Failed to register item recipe from " + baseUnity.Info.Metadata.Name + ": Unable to find item prefab for " + IItemInteraction_FirstType.Name + "!")); ModSyncManager.FailedRecipes.Add((baseUnity, IItemInteraction_FirstType, IItemInteraction_SecondType, IItemInteraction_ResultType)); } } private static MonoBehaviour? GetPageFromSpellType(Type spellType) { PageController[] array = Resources.FindObjectsOfTypeAll<PageController>(); foreach (PageController val in array) { object obj; if (val == null) { obj = null; } else { GameObject spellprefab = val.spellprefab; obj = ((spellprefab == null) ? null : ((object)spellprefab.GetComponent<ISpell>())?.GetType()); } if ((Type?)obj == spellType) { return (MonoBehaviour?)(object)val; } } return null; } internal static T? GetItemPrefab<T>() where T : IItemInteraction { return (T)(object)GetItemPrefab(typeof(T)); } internal static IItemInteraction? GetItemPrefab(Type IItemInteraction_Type) { //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Expected O, but got Unknown Type IItemInteraction_Type2 = IItemInteraction_Type; if (PrefabMapping.TryGetValue(IItemInteraction_Type2, out IItemInteraction value)) { return value; } IItemInteraction val = Mapping.Select<(ItemData, ItemBehavior), IItemInteraction>(((ItemData data, ItemBehavior behavior) map) => (IItemInteraction)(object)map.behavior)?.FirstOrDefault((Func<IItemInteraction, bool>)((IItemInteraction behavior) => ((object)behavior).GetType() == IItemInteraction_Type2)); if (val != null) { PrefabMapping[IItemInteraction_Type2] = val; return val; } IItemInteraction val2 = (IItemInteraction)Resources.FindObjectsOfTypeAll(IItemInteraction_Type2).FirstOrDefault(); if (val2 != null) { PrefabMapping[IItemInteraction_Type2] = val2; return val2; } throw new NullReferenceException("Item prefab could not be found!"); } internal static void RegisterItem(BaseUnityPlugin baseUnity, Type ItemDataType, Type? ItemBehaviorType = null) { if (ItemDataType.IsAbstract) { BMAPlugin.Log.LogError((object)("Failed to register item from " + baseUnity.Info.Metadata.Name + ": ItemDataType can not be abstract!")); ModSyncManager.FailedItems.Add((baseUnity, ItemDataType)); return; } if (!ItemDataType.IsSubclassOf(typeof(ItemData))) { BMAPlugin.Log.LogError((object)("Failed to register item from " + baseUnity.Info.Metadata.Name + ": ItemDataType must be inherited from SpellData!")); ModSyncManager.FailedItems.Add((baseUnity, ItemDataType)); return; } if (ItemBehaviorType != null) { if (ItemBehaviorType.IsAbstract) { BMAPlugin.Log.LogError((object)("Failed to register item from " + baseUnity.Info.Metadata.Name + ": ItemBehaviorType can not be abstract!")); ModSyncManager.FailedItems.Add((baseUnity, ItemDataType)); return; } if (!ItemBehaviorType.IsSubclassOf(typeof(ItemBehavior))) { BMAPlugin.Log.LogError((object)("Failed to register item from " + baseUnity.Info.Metadata.Name + ": ItemBehaviorType must be inherited from SpellLogic!")); ModSyncManager.FailedItems.Add((baseUnity, ItemDataType)); return; } } if (registeredTypes.Contains(ItemDataType)) { BMAPlugin.Log.LogError((object)("Failed to register item from " + baseUnity.Info.Metadata.Name + ": " + ItemDataType.Name + " has already been registered!")); ModSyncManager.FailedItems.Add((baseUnity, ItemDataType)); return; } switch (CompatibilityManager.CheckItemCompatibility(ItemDataType)) { case CompatibilityResult.NoProperty: BMAPlugin.Log.LogError((object)("Failed to register item from " + baseUnity.Info.Metadata.Name + ": Unable to find Compatibility property in " + ItemDataType.Name + ", this can be due to " + baseUnity.Info.Metadata.Name + " being outdated!")); ModSyncManager.FailedItems.Add((baseUnity, ItemDataType)); break; case CompatibilityResult.OldVersion: BMAPlugin.Log.LogError((object)("Failed to register item from " + baseUnity.Info.Metadata.Name + ": " + ItemDataType.Name + " Is incompatible with BlackMagicAPI v3.0.1!")); ModSyncManager.FailedItems.Add((baseUnity, ItemDataType)); break; case CompatibilityResult.Error: BMAPlugin.Log.LogError((object)("Failed to register item from " + baseUnity.Info.Metadata.Name + ": An error occurred when trying to get Compatibility Version from " + ItemDataType.Name + "!")); ModSyncManager.FailedItems.Add((baseUnity, ItemDataType)); break; default: RegisterItemTask(baseUnity, ItemDataType, ItemBehaviorType); break; } } private static async Task RegisterItemTask(BaseUnityPlugin baseUnity, Type itemDataType, Type? itemBehaviorType) { object obj = Activator.CreateInstance(itemDataType); if (!(obj is ItemData data)) { ModSyncManager.FailedItems.Add((baseUnity, itemDataType)); throw new InvalidCastException($"Failed to create or cast {itemDataType} to SpellData"); } data.Plugin = baseUnity; ItemBehavior itemBehavior = await data.GetItemPrefab(); if ((Object)(object)itemBehavior == (Object)null) { if (itemBehaviorType == null) { BMAPlugin.Log.LogError((object)("Failed to register item from " + baseUnity.Info.Metadata.Name + ": spellLogicType cannot be null without a loadable prefab!")); ModSyncManager.FailedItems.Add((baseUnity, itemDataType)); return; } itemBehavior = CreateItemBehavior(data, itemBehaviorType); } CreateItem(baseUnity, data, itemBehavior); } private static ItemBehavior CreateItemBehavior(ItemData itemData, Type itemBehaviorType) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown //IL_0063: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(itemData.Name.Replace(" ", "") + "Item"); Object.DontDestroyOnLoad((Object)(object)val); val.AddComponent<AudioSource>(); GameObject val2 = new GameObject("ItemRender"); val2.transform.SetParent(val.transform); val2.transform.rotation = Quaternion.Euler(-90f, 180f, 0f); ItemBehavior obj = (ItemBehavior)(object)val.AddComponent(itemBehaviorType); obj.Name = itemData.Name; obj.KeepOnDeath = itemData.KeepOnDeath; obj.ItemRender = val2; obj.EquipSound = itemData.GetPickupAudio(); obj.DropSound = itemData.GetEquipAudio(); obj.AddColliderToPrefab(val); obj.OnPrefabCreatedAutomatically(((Component)obj).gameObject); return obj; } private static void CreateItem(BaseUnityPlugin baseUnity, ItemData itemData, ItemBehavior itemBehavior) { ItemData itemData2 = itemData; ItemBehavior itemBehavior2 = itemBehavior; SynchronizeManager.SynchronizeItemId(baseUnity, itemData2.GetType(), itemData2.GetUiSprite, delegate(int id) { itemData2.Id = id; itemBehavior2.Id = id; }); FishManager.RegisterNetworkObjectPrefab((BaseUnityPlugin)(object)BMAPlugin.Instance, (MonoBehaviour)(object)itemBehavior2, itemData2.GetType().FullName, true); Mapping.Add((itemData2, itemBehavior2)); List<(ItemData, ItemBehavior)> list = new List<(ItemData, ItemBehavior)>(); foreach (var item in Mapping.OrderBy<(ItemData, ItemBehavior), int>(((ItemData data, ItemBehavior behavior) map) => map.data.Id)) { list.Add(item); } Mapping = list; registeredTypes.Add(itemData2.GetType()); SynchronizeManager.UpdateSyncHash(); BMAPlugin.Log.LogInfo((object)("Successfully registered " + itemData2.Name + " Item from " + baseUnity.Info.Metadata.GUID)); } } internal class ModSyncManager { internal static List<(BaseUnityPlugin plugin, Type type)> FailedSpells = new List<(BaseUnityPlugin, Type)>(); internal static List<(BaseUnityPlugin plugin, Type type)> FailedItems = new List<(BaseUnityPlugin, Type)>(); internal static List<(BaseUnityPlugin plugin, Type type, Type type2, Type type3)> FailedRecipes = new List<(BaseUnityPlugin, Type, Type, Type)>(); internal static List<(BaseUnityPlugin plugin, Type type)> FailedSoups = new List<(BaseUnityPlugin, Type)>(); internal static void LogAll() { ((MonoBehaviour)BMAPlugin.Instance).StartCoroutine(CoLogAll()); } private static IEnumerator CoLogAll() { foreach (var failedSpell in FailedSpells) { BaseUnityPlugin item = failedSpell.plugin; Type item2 = failedSpell.type; float time4 = 0.1f; ModSyncUI.ShowMessage("BlackMagicAPI: " + item2.Name + " spell from " + item.Info.Metadata.Name + " failed to load!", (MessageType)3); while (time4 > 0f) { time4 -= Time.deltaTime; yield return null; } } foreach (var failedItem in FailedItems) { BaseUnityPlugin item3 = failedItem.plugin; Type item4 = failedItem.type; float time4 = 0.1f; ModSyncUI.ShowMessage("BlackMagicAPI: " + item4.Name + " item from " + item3.Info.Metadata.Name + " failed to load!", (MessageType)3); while (time4 > 0f) { time4 -= Time.deltaTime; yield return null; } } foreach (var failedRecipe in FailedRecipes) { BaseUnityPlugin item5 = failedRecipe.plugin; Type item6 = failedRecipe.type; Type item7 = failedRecipe.type2; Type item8 = failedRecipe.type3; float time4 = 0.1f; ModSyncUI.ShowMessage("BlackMagicAPI: Recipe (" + item6.Name + ", " + item7.Name + " -> " + item8.Name + ") from " + item5.Info.Metadata.Name + " failed to load!", (MessageType)3); while (time4 > 0f) { time4 -= Time.deltaTime; yield return null; } } foreach (var failedSoup in FailedSoups) { BaseUnityPlugin item9 = failedSoup.plugin; Type item10 = failedSoup.type; float time4 = 0.1f; ModSyncUI.ShowMessage("BlackMagicAPI: " + item10.Name + " soup from " + item9.Info.Metadata.Name + " failed to load!", (MessageType)3); while (time4 > 0f) { time4 -= Time.deltaTime; yield return null; } } } } internal class SoupManager { private static readonly List<Type> registeredTypes = new List<Type>(); internal static List<(SoupData data, CrystalSoup itemPrefab, GameObject? render, SoupEffect effect)> Mapping = new List<(SoupData, CrystalSoup, GameObject, SoupEffect)>(); internal static (SoupData data, CrystalSoup itemPrefab, GameObject? render, SoupEffect effect)? GetMapFromItemId(int id) { return Mapping.FirstOrDefault<(SoupData, CrystalSoup, GameObject, SoupEffect)>(((SoupData data, CrystalSoup itemPrefab, GameObject render, SoupEffect effect) map) => map.data.ItemId == id); } internal static void RegisterSoup(BaseUnityPlugin baseUnity, Type IItemInteraction, Type soupDataType, Type? soupEffectType = null) { if (IItemInteraction.IsInterface) { BMAPlugin.Log.LogError((object)("Failed to register soup from " + baseUnity.Info.Metadata.Name + ": IItemInteraction can not be directly IItemInteraction interface!")); ModSyncManager.FailedSoups.Add((baseUnity, soupDataType)); } else if (!soupDataType.IsSubclassOf(typeof(SoupData))) { BMAPlugin.Log.LogError((object)("Failed to register soup from " + baseUnity.Info.Metadata.Name + ": soupDataType must be inherited from SoupData!")); ModSyncManager.FailedSoups.Add((baseUnity, soupDataType)); } else if (soupEffectType != null && !soupEffectType.IsSubclassOf(typeof(SoupEffect))) { BMAPlugin.Log.LogError((object)("Failed to register soup from " + baseUnity.Info.Metadata.Name + ": soupEffectType must be inherited from SoupEffect!")); ModSyncManager.FailedSoups.Add((baseUnity, soupDataType)); } else if (registeredTypes.Contains(soupDataType)) { BMAPlugin.Log.LogError((object)("Failed to register soup from " + baseUnity.Info.Metadata.Name + ": " + soupDataType.Name + " has already been registered!")); ModSyncManager.FailedSoups.Add((baseUnity, soupDataType)); } else { RegisterSoupTask(baseUnity, IItemInteraction, soupDataType, soupEffectType); } } private static async Task RegisterSoupTask(BaseUnityPlugin baseUnity, Type IItemInteraction, Type soupDataType, Type? soupEffectType) { object obj = Activator.CreateInstance(soupDataType); if (!(obj is SoupData data)) { ModSyncManager.FailedSoups.Add((baseUnity, soupDataType)); throw new InvalidCastException($"Failed to create or cast {soupDataType} to SoupData"); } data.Plugin = baseUnity; IItemInteraction? itemPrefab = ItemManager.GetItemPrefab(IItemInteraction); data.RequiredItemId = ((itemPrefab != null) ? itemPrefab.GetItemID() : (-1)); SoupEffect soupEffect = await data.GetEffectPrefab(); if ((Object)(object)soupEffect == (Object)null) { if (soupEffectType == null) { BMAPlugin.Log.LogError((object)("Failed to register soup from " + baseUnity.Info.Metadata.Name + ": soupEffectType cannot be null without a loadable prefab!")); ModSyncManager.FailedSoups.Add((baseUnity, soupDataType)); return; } soupEffect = CreateSoupEffect(data, soupEffectType); } ((Component)soupEffect).gameObject.SetActive(false); CreateSoupItem(baseUnity, IItemInteraction, data, soupEffect); } private static SoupEffect CreateSoupEffect(SoupData soupData, Type SoupEffectType) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown GameObject val = new GameObject(soupData.Name.Replace(" ", "") + "Effect"); Object.DontDestroyOnLoad((Object)val); SoupEffect obj = (SoupEffect)(object)val.AddComponent(SoupEffectType); obj.OnPrefabCreatedAutomatically(((Component)obj).gameObject); return obj; } private static void CreateSoupItem(BaseUnityPlugin baseUnity, Type IItemInteraction, SoupData soupData, SoupEffect soupEffect) { //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) SoupData soupData2 = soupData; SoupEffect soupEffect2 = soupEffect; CrystalSoup val = Resources.FindObjectsOfTypeAll<CrystalSoup>().First(); CrystalSoup prefab = Object.Instantiate<CrystalSoup>(val); Object.DontDestroyOnLoad((Object)(object)prefab); ((Object)prefab).name = soupData2.Name.Replace(" ", "") + "BowlItem"; prefab.stewid = -1; ((Renderer)prefab.mrend).materials[1].color = soupData2.SoupColor - Color.cyan; NetworkObject val2 = default(NetworkObject); if (((Component)prefab).TryGetComponent<NetworkObject>(ref val2) && (Object)(object)val2 != (Object)null) { Object.DestroyImmediate((Object)(object)val2); } Object.Destroy((Object)(object)((Component)((Component)prefab.mrend).transform.GetChild(0)).gameObject); IItemInteraction? itemPrefab = ItemManager.GetItemPrefab(IItemInteraction); IItemInteraction? obj = ((itemPrefab is MonoBehaviour) ? itemPrefab : null); GameObject val3 = Object.Instantiate<GameObject>((obj != null) ? ((Component)((Component)obj).transform.GetChild(0)).gameObject : null); if ((Object)(object)val3 != (Object)null) { soupData2.SetObjectVisualTransform(val3); } if (val3 != null) { val3.transform.SetParent(((Component)prefab.mrend).transform, false); } SynchronizeManager.SynchronizeItemId(baseUnity, soupData2.GetType(), soupData2.GetUiSprite, delegate(int id) { soupData2.ItemId = id; soupEffect2.Id = id; prefab.itemid = id; }); FishManager.RegisterNetworkObjectPrefab((BaseUnityPlugin)(object)BMAPlugin.Instance, (MonoBehaviour)(object)prefab, soupData2.GetType().FullName ?? "", true); Mapping.Add((soupData2, prefab, val3, soupEffect2)); List<(SoupData, CrystalSoup, GameObject, SoupEffect)> list = new List<(SoupData, CrystalSoup, GameObject, SoupEffect)>(); foreach (var item in Mapping.OrderBy<(SoupData, CrystalSoup, GameObject, SoupEffect), int>(((SoupData data, CrystalSoup itemPrefab, GameObject render, SoupEffect effect) map) => map.data.ItemId)) { list.Add(item); } Mapping = list; SynchronizeManager.UpdateSyncHash(); BMAPlugin.Log.LogInfo((object)("Successfully registered " + soupData2.Name + " Soup from " + baseUnity.Info.Metadata.GUID)); foreach (IGrouping<int, (SoupData, CrystalSoup, GameObject, SoupEffect)> item2 in from g in Mapping.ToLookup<(SoupData, CrystalSoup, GameObject, SoupEffect), int>(((SoupData data, CrystalSoup itemPrefab, GameObject render, SoupEffect effect) map) => map.data.RequiredItemId) where g.Count() > 1 select g) { string text = item2.OrderBy<(SoupData, CrystalSoup, GameObject, SoupEffect), int>(((SoupData data, CrystalSoup itemPrefab, GameObject render, SoupEffect effect) map) => map.data.ItemId).FirstOrDefault().Item1.GetType().FullName ?? ""; BMAPlugin.Log.LogWarning((object)("Warning multiple soups have been registered to the same item, " + text + " will override (" + string.Join(", ", from map in item2.OrderBy<(SoupData, CrystalSoup, GameObject, SoupEffect), int>(((SoupData data, CrystalSoup itemPrefab, GameObject render, SoupEffect effect) map) => map.data.ItemId).Skip(1) select map.data.GetType().FullName) + ") soups.")); } } } internal static class SpellManager { private static readonly List<Type> registeredTypes = new List<Type>(); internal static List<(SpellData data, PageController page)> Mapping = new List<(SpellData, PageController)>(); internal static readonly Dictionary<Type, PageController> PrefabMapping = new Dictionary<Type, PageController>(); internal static T GetSpellLogicPrefab<T>() where T : ISpell { T result = default(T); if (GetSpellPagePrefab<T>().spellprefab.TryGetComponent<T>(ref result)) { return result; } throw new NullReferenceException("Logic prefab could not be found!"); } internal static PageController GetSpellPagePrefab<T>() where T : ISpell { //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Expected O, but got Unknown if (PrefabMapping.TryGetValue(typeof(T), out PageController value)) { return value; } PageController val = Mapping.Select<(SpellData, PageController), PageController>(((SpellData data, PageController page) map) => map.page)?.FirstOrDefault((Func<PageController, bool>)((PageController page) => ((object)page.spellprefab.GetComponent<ISpell>())?.GetType() == typeof(T))); if ((Object)(object)val != (Object)null) { PrefabMapping[typeof(T)] = val; return val; } PageController val2 = (PageController)((IEnumerable<Object>)Resources.FindObjectsOfTypeAll(typeof(PageController))).FirstOrDefault((Func<Object, bool>)delegate(Object page) { PageController val3 = (PageController)(object)((page is PageController) ? page : null); return val3 != null && ((object)val3.spellprefab.GetComponent<ISpell>())?.GetType() == typeof(T); }); if ((Object)(object)val2 != (Object)null) { PrefabMapping[typeof(T)] = val2; return val2; } throw new NullReferenceException("Page prefab could not be found!"); } internal static void RegisterSpell(BaseUnityPlugin baseUnity, Type SpellDataType, Type? SpellLogicType = null) { if (SpellDataType.IsAbstract) { BMAPlugin.Log.LogError((object)("Failed to register spell from " + baseUnity.Info.Metadata.Name + ": SpellDataType can not be abstract!")); ModSyncManager.FailedSpells.Add((baseUnity, SpellDataType)); return; } if (!SpellDataType.IsSubclassOf(typeof(SpellData))) { BMAPlugin.Log.LogError((object)("Failed to register spell from " + baseUnity.Info.Metadata.Name + ": SpellDataType must be inherited from SpellData!")); ModSyncManager.FailedSpells.Add((baseUnity, SpellDataType)); return; } if (SpellLogicType != null) { if (SpellLogicType.IsAbstract) { BMAPlugin.Log.LogError((object)("Failed to register spell from " + baseUnity.Info.Metadata.Name + ": SpellLogicType can not be abstract!")); ModSyncManager.FailedSpells.Add((baseUnity, SpellDataType)); return; } if (!SpellLogicType.IsSubclassOf(typeof(SpellLogic))) { BMAPlugin.Log.LogError((object)("Failed to register spell from " + baseUnity.Info.Metadata.Name + ": SpellDataType must be inherited from SpellLogic!")); ModSyncManager.FailedSpells.Add((baseUnity, SpellDataType)); return; } } if (registeredTypes.Contains(SpellDataType)) { BMAPlugin.Log.LogError((object)("Failed to register spell from " + baseUnity.Info.Metadata.Name + ": " + SpellDataType.Name + " has already been registered!")); ModSyncManager.FailedSpells.Add((baseUnity, SpellDataType)); return; } switch (CompatibilityManager.CheckSpellCompatibility(SpellDataType)) { case CompatibilityResult.NoProperty: BMAPlugin.Log.LogError((object)("Failed to register spell from " + baseUnity.Info.Metadata.Name + ": Unable to find Compatibility property in " + SpellDataType.Name + ", this can be due to " + baseUnity.Info.Metadata.Name + " being outdated!")); ModSyncManager.FailedSpells.Add((baseUnity, SpellDataType)); break; case CompatibilityResult.OldVersion: BMAPlugin.Log.LogError((object)("Failed to register spell from " + baseUnity.Info.Metadata.Name + ": " + SpellDataType.Name + " Is incompatible with BlackMagicAPI v3.0.1!")); ModSyncManager.FailedSpells.Add((baseUnity, SpellDataType)); break; case CompatibilityResult.Error: BMAPlugin.Log.LogError((object)("Failed to register spell from " + baseUnity.Info.Metadata.Name + ": An error occurred when trying to get Compatibility Version from " + SpellDataType.Name + "!")); ModSyncManager.FailedSpells.Add((baseUnity, SpellDataType)); break; default: RegisterSpellTask(baseUnity, SpellDataType, SpellLogicType); break; } } private static async Task RegisterSpellTask(BaseUnityPlugin baseUnity, Type spellDataType, Type? spellLogicType) { object obj = Activator.CreateInstance(spellDataType); if (!(obj is SpellData data)) { ModSyncManager.FailedSpells.Add((baseUnity, spellDataType)); throw new InvalidCastException($"Failed to create or cast {spellDataType} to SpellData"); } data.Plugin = baseUnity; SpellLogic spellLogic = await data.GetLogicPrefab(); if ((Object)(object)spellLogic == (Object)null) { if (spellLogicType == null) { ModSyncManager.FailedSpells.Add((baseUnity, spellDataType)); BMAPlugin.Log.LogError((object)("Failed to register spell from " + baseUnity.Info.Metadata.Name + ": spellLogicType cannot be null without a loadable prefab!")); return; } spellLogic = CreateSpellLogic(data, spellLogicType); } ((Component)spellLogic).gameObject.SetActive(false); spellLogic.SpellDataTypeName = spellDataType.FullName; spellLogic.KeepOnDeath = data.KeepOnDeath; CreateSpell(baseUnity, data, spellLogic); } private static SpellLogic CreateSpellLogic(SpellData spellData, Type spellLogicType) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown GameOb