using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
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.Logging;
using BlackMagicAPI.Enums;
using BlackMagicAPI.Helpers;
using BlackMagicAPI.Managers;
using BlackMagicAPI.Modules.Items;
using BlackMagicAPI.Modules.Spells;
using BlackMagicAPI.Network;
using BlackMagicAPI.Patches.Items;
using BlackMagicAPI.Patches.Managers;
using BlackMagicAPI.Patches.Voice;
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 Microsoft.CodeAnalysis;
using Recognissimo;
using Recognissimo.Components;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("BlackMagicAPI")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+411806cfbeb49e6089b6f569131b620e662560f9")]
[assembly: AssemblyProduct("BlackMagicAPI")]
[assembly: AssemblyTitle("BlackMagicAPI")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.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", "2.4.0")]
public class BMAPlugin : BaseUnityPlugin
{
private const string MyGUID = "com.d1gq.black.magic.api";
internal const string PluginName = "BlackMagicAPI";
private const string VersionString = "2.4.0";
private static Harmony? Harmony;
private ManualLogSource? _log;
public static string modsync = "all";
internal static BMAPlugin Instance { get; private set; }
internal static ManualLogSource Log => Instance._log;
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)"BlackMagicAPI v2.4.0 loaded!");
BlackMagicManager.UpdateSyncHash();
}
}
}
namespace BlackMagicAPI.Patches.Voice
{
[HarmonyPatch(typeof(PlayerInventory))]
internal class PlayerInventoryPatch
{
[HarmonyPatch]
private static class PlaceOnCraftingTablePatch
{
private static MethodBase TargetMethod()
{
return Utils.PatchRpcMethod<PlayerInventory>("RpcLogic___PlaceOnCraftingTableObserver");
}
[HarmonyPostfix]
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]
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]
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;
}
}
}
namespace BlackMagicAPI.Patches.Managers
{
[HarmonyPatch(typeof(ColoseumManager))]
internal class ColoseumManagerPatch
{
[HarmonyPatch("OnStartClient")]
[HarmonyPrefix]
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]
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]
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]
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]
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]
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, 78f, 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]
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.Generation
{
[HarmonyPatch(typeof(DungeonGenerator))]
internal class DungeonGeneratorPatch
{
[HarmonyPatch("Start")]
[HarmonyPrefix]
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;
}
}
}
namespace BlackMagicAPI.Patches.Items
{
[HarmonyPatch(typeof(ChestNetController))]
internal class ChestNetControllerPatch
{
[HarmonyPatch]
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]
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(ChestNetController1))]
internal class ChestNetController1Patch
{
[HarmonyPatch]
private static class ServerPlaceItemPatch
{
private static MethodBase TargetMethod()
{
return Utils.PatchRpcMethod<ChestNetController1>("RpcLogic___ServerPlaceItem");
}
[HarmonyPrefix]
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]
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]
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>();
resultPrefap.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]
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(Generator2D))]
internal class Generator2DPatch
{
[HarmonyPatch]
private static class ServerPlaceItemPatch
{
private static MethodBase TargetMethod()
{
return Utils.PatchRpcMethod<Generator2D>("RpcLogic___ServerPlaceItem");
}
[HarmonyPrefix]
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]
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]
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()
{
List<MethodInfo> list = (from m in typeof(PageController).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
where m.Name.StartsWith("RpcReader___Observers_CastSpellObs")
select m).ToList();
if (list.Count == 0)
{
throw new Exception("Could not find RpcReader___Observers_CastSpellObs method");
}
return list[0];
}
[HarmonyPrefix]
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]
private static void Interaction_Prefix(PageController __instance, GameObject player)
{
if (IsCustomSpell(__instance))
{
__instance.spellprefab.GetComponent<SpellLogic>()?.OnPageItemUse(player, __instance);
}
}
[HarmonyPatch("CastSpellServer")]
[HarmonyPrefix]
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_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_006f: 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, 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_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)ownerobj != (Object)null)
{
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();
spellLogic.CastSpell(ownerobj, __instance, spawnpos, fwdVector, level);
}
}
}
}
}
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.Spells
{
public abstract class ItemData
{
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; }
internal BaseUnityPlugin? Plugin { get; 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);
}
}
internal class CustomSpellCommand : MonoBehaviour, ISpellCommand
{
internal string SpellName { get; set; } = "[]";
internal SpellData SpellData { get; 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 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
{
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; }
internal BaseUnityPlugin? Plugin { get; 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 void CastSpell(GameObject playerObj, PageController page, Vector3 spawnPos, Vector3 viewDirectionVector, int castingLevel);
public virtual void OnPageItemUse(GameObject itemOwner, PageController page)
{
}
public virtual void OnPrefabCreatedAutomatically(GameObject prefab)
{
}
public virtual void WriteData(DataWriter dataWriter, PageController page, GameObject playerObj, 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 virtual void OnItemUse(PlayerMovement itemOwner)
{
OnItemUse(((Component)itemOwner).gameObject);
}
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
if (!netInit)
{
netInit = true;
((NetworkBehaviour)this).RegisterObserversRpc(0u, new ClientRpcDelegate(HandleSyncClientRpc));
}
}
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(0u, 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();
}
[Obsolete("This method is deprecated. Please override OnItemUse(PlayerMovement) instead.")]
protected virtual void OnItemUse(GameObject itemOwner)
{
}
}
}
namespace BlackMagicAPI.Managers
{
public class BlackMagicManager
{
internal static void UpdateSyncHash()
{
StringBuilder stringBuilder = new StringBuilder();
foreach (var item3 in from map in SpellManager.Mapping
orderby map.data.Plugin?.GetUniqueHash(), map.data.GetType().FullName
select map)
{
SpellData item = item3.Item1;
AppendMappingData(stringBuilder, item?.Plugin?.GetUniqueHash(), item?.Id.ToString(), item?.GetType().FullName);
}
foreach (var item4 in from map in ItemManager.Mapping
orderby map.data.Plugin?.GetUniqueHash(), map.data.GetType().FullName
select map)
{
ItemData item2 = item4.Item1;
AppendMappingData(stringBuilder, item2?.Plugin?.GetUniqueHash(), item2?.Id.ToString(), item2?.GetType().FullName);
}
string text = stringBuilder.ToString();
string text2 = ((text.Length > 0) ? Utils.Generate9DigitHash(text) : "000 | 000 | 000");
MainMenuManagerPatch.UpdateHash("(Black Magic Sync)\n" + text2);
}
private static void AppendMappingData(StringBuilder builder, params string?[] values)
{
builder.Append('[');
foreach (string text in values)
{
builder.Append(text ?? "");
}
builder.Append(']');
}
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 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 static class ItemManager
{
private static readonly List<Type> registeredTypes = new List<Type>();
internal static readonly 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!"));
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!"));
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!"));
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!"));
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!"));
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!"));
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_FirstType)));
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_FirstType)));
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!"));
}
}
else
{
BMAPlugin.Log.LogError((object)("Failed to register item recipe from " + baseUnity.Info.Metadata.Name + ": Unable to find item prefab for " + IItemInteraction_ResultType.Name + "!"));
}
}
else
{
BMAPlugin.Log.LogError((object)("Failed to register item recipe from " + baseUnity.Info.Metadata.Name + ": Unable to find item prefab for " + IItemInteraction_SecondType.Name + "!"));
}
}
else
{
BMAPlugin.Log.LogError((object)("Failed to register item recipe from " + baseUnity.Info.Metadata.Name + ": Unable to find item prefab for " + IItemInteraction_FirstType.Name + "!"));
}
}
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
{
//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
if (PrefabMapping.TryGetValue(typeof(T), out IItemInteraction value))
{
return (T)(object)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() == typeof(T)));
if (val != null)
{
PrefabMapping[typeof(T)] = val;
return (T)(object)val;
}
T val2 = (T)(IItemInteraction)Resources.FindObjectsOfTypeAll(typeof(T)).FirstOrDefault();
if (val2 != null)
{
PrefabMapping[typeof(T)] = (IItemInteraction)(object)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!"));
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!"));
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!"));
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!"));
return;
}
}
if (registeredTypes.Contains(ItemDataType))
{
BMAPlugin.Log.LogError((object)("Failed to register item from " + baseUnity.Info.Metadata.Name + ": " + ItemDataType.Name + " has already been registered!"));
}
else
{
RegisterItemTask(baseUnity, ItemDataType, ItemBehaviorType);
}
}
private static async Task RegisterItemTask(BaseUnityPlugin baseUnity, Type spellItemType, Type? itemBehaviorType)
{
object obj = Activator.CreateInstance(spellItemType);
if (!(obj is ItemData data))
{
throw new InvalidCastException($"Failed to create or cast {spellItemType} 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!"));
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_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Expected O, but got Unknown
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Expected O, but got Unknown
//IL_006b: Unknown result type (might be due to invalid IL or missing references)
GameObject val = new GameObject(itemData.Name.Replace(" ", "") + "Item")
{
hideFlags = (HideFlags)61
};
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;
NetworkObjectManager.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));
registeredTypes.Add(itemData2.GetType());
BlackMagicManager.UpdateSyncHash();
BMAPlugin.Log.LogInfo((object)("Successfully registered " + itemData2.Name + " Item from " + baseUnity.Info.Metadata.GUID));
}
}
internal class NetworkObjectManager
{
private static readonly List<(BaseUnityPlugin plugin, Type type, Func<Sprite?> getSpriteCallback, Action<int> setIdCallback)> Mapping = new List<(BaseUnityPlugin, Type, Func<Sprite>, Action<int>)>();
internal static void SynchronizeItemId(BaseUnityPlugin baseUnity, Type type, Func<Sprite?> sprite, Action<int> SetIdCallback)
{
Mapping.Add((baseUnity, type, sprite, SetIdCallback));
int num = Resources.FindObjectsOfTypeAll<PlayerInventory>().First().ItemIcons.Length + 1;
foreach (var item in from m in Mapping
orderby m.plugin.GetUniqueHash(), m.type.FullName
select m)
{
PlayerInventoryPatch.SetUiSprite(item.Item3(), num);
item.Item4(num);
num++;
}
}
}
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!"));
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!"));
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!"));
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!"));
return;
}
}
if (registeredTypes.Contains(SpellDataType))
{
BMAPlugin.Log.LogError((object)("Failed to register spell from " + baseUnity.Info.Metadata.Name + ": " + SpellDataType.Name + " has already been registered!"));
}
else
{
RegisterSpellTask(baseUnity, SpellDataType, SpellLogicType);
}
}
private static async Task RegisterSpellTask(BaseUnityPlugin baseUnity, Type spellDataType, Type? spellLogicType)
{
object obj = Activator.CreateInstance(spellDataType);
if (!(obj is SpellData data))
{
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)
{
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_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Expected O, but got Unknown
GameObject val = new GameObject(spellData.Name.Replace(" ", "") + "Spell")
{
hideFlags = (HideFlags)61
};
Object.DontDestroyOnLoad((Object)val);
SpellLogic obj = (SpellLogic)(object)val.AddComponent(spellLogicType);
obj.OnPrefabCreatedAutomatically(((Component)obj).gameObject);
return obj;
}
private static void CreateSpell(BaseUnityPlugin baseUnity, SpellData spellData, SpellLogic spellLogic)
{
SpellData spellData2 = spellData;
if (spellData2.SpellType == SpellType.Page)
{
PageController val = Resources.FindObjectsOfTypeAll<PageController>().First();
if ((Object)(object)val != (Object)null)
{
PageController prefab = Object.Instantiate<PageController>(val);
((Object)prefab).hideFlags = (HideFlags)61;
Object.DontDestroyOnLoad((Object)(object)prefab);
((Object)prefab).name = "Page" + spellData2.Name.Replace(" ", "");
NetworkObjectManager.SynchronizeItemId(baseUnity, spellData2.GetType(), spellData2.GetUiSprite, delegate(int id)
{
spellData2.Id = id;
prefab.ItemID = id;
});
FishManager.RegisterNetworkObjectPrefab((BaseUnityPlugin)(object)BMAPlugin.Instance, (MonoBehaviour)(object)prefab, spellData2.GetType().FullName, true);
spellData2.SetUpPage(((Component)prefab).GetComponent<PageController>(), spellLogic);
spellData2.SetLight(((Component)prefab).GetComponentInChildren<Light>(true));
Mapping.Add((spellData2, prefab));
registeredTypes.Add(spellData2.GetType());
BlackMagicManager.UpdateSyncHash();
}
}
BMAPlugin.Log.LogInfo((object)("Successfully registered " + spellData2.Name + " Spell from " + baseUnity.Info.Metadata.GUID));
}
}
}
namespace BlackMagicAPI.Helpers
{
public static class Utils
{
internal static Dictionary<string, Sprite> CachedSprites = new Dictionary<string, Sprite>();
public static Sprite? LoadSpriteFromDisk(string path, float pixelsPerUnit = 1f)
{
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
//IL_0073: Unknown result type (might be due to invalid IL or missing references)
try
{
if (CachedSprites.TryGetValue(path + pixelsPerUnit, out Sprite value))
{
return value;
}
Texture2D val = LoadTextureFromDisk(path);
if ((Object)(object)val == (Object)null)
{
return null;
}
value = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), pixelsPerUnit);
Sprite obj = value;
((Object)obj).hideFlags = (HideFlags)(((Object)obj).hideFlags | 0x3D);
return CachedSprites[path + pixelsPerUnit] = value;
}
catch (Exception ex)
{
BMAPlugin.Log.LogError((object)ex);
return null;
}
}
public static Texture2D? LoadTextureFromDisk(string path)
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Expected O, but got Unknown
try
{
if (File.Exists(path))
{
Texture2D val = new Texture2D(2, 2, (TextureFormat)5, false);
byte[] array = File.ReadAllBytes(path);
if (ImageConversion.LoadImage(val, array, false))
{
return val;
}
BMAPlugin.Log.LogError((object)"Failed to load image data into texture.");
}
else
{
BMAPlugin.Log.LogError((object)("File does not exist: " + path));
}
}
catch (Exception ex)
{
BMAPlugin.Log.LogError((object)("Exception while loading texture: " + ex));
}
return null;
}
public static Sprite? LoadSpriteFromResources(this Assembly assembly, string path, float pixelsPerUnit = 1f)
{
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
//IL_006d: 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)
try
{
if (CachedSprites.TryGetValue(path + pixelsPerUnit, out Sprite value))
{
return value;
}
Texture2D val = assembly.LoadTextureFromResources(path);
if ((Object)(object)val == (Object)null)
{
return null;
}
value = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), pixelsPerUnit);
Sprite obj = value;
((Object)obj).hideFlags = (HideFlags)(((Object)obj).hideFlags | 0x3D);
return CachedSprites[path + pixelsPerUnit] = value;
}
catch (Exception ex)
{
BMAPlugin.Log.LogError((object)ex);
return null;
}
}
public static Texture2D? LoadTextureFromResources(this Assembly assembly, string path)
{
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Expected O, but got Unknown
try
{
Stream manifestResourceStream = assembly.GetManifestResourceStream(path);
if (manifestResourceStream == null)
{
return null;
}
Texture2D val = new Texture2D(1, 1, (TextureFormat)5, false);
using (MemoryStream memoryStream = new MemoryStream())
{
manifestResourceStream.CopyTo(memoryStream);
if (!ImageConversion.LoadImage(val, memoryStream.ToArray(), false))
{
return null;
}
}
return val;
}
catch (Exception ex)
{
BMAPlugin.Log.LogError((object)ex);
return null;
}
}
public static AudioClip? LoadWavFromDisk(string filePath)
{
if (!File.Exists(filePath))
{
Debug.LogError((object)("File not found: " + filePath));
return null;
}
if (Path.GetExtension(filePath).ToLower() != ".wav")
{
Debug.LogError((object)"Only .wav files are supported.");
return null;
}
try
{
return WavUtility.ToAudioClip(File.ReadAllBytes(filePath));
}
catch (Exception arg)
{
Debug.LogError((object)$"Failed to load WAV: {arg}");
return null;
}
}
public static AudioClip? LoadWavFromResources(this Assembly assembly, string resourcePath)
{
try
{
using Stream stream = assembly.GetManifestResourceStream(resourcePath);
if (stream == null)
{
Debug.LogError((object)("Resource not found: " + resourcePath));
return null;
}
using MemoryStream memoryStream = new MemoryStream();
stream.CopyTo(memoryStream);
return WavUtility.ToAudioClip(memoryStream.ToArray());
}
catch (Exception arg)
{
Debug.LogError((object)$"Failed to load WAV from resources: {arg}");
return null;
}
}
public static AssetBundle? LoadAssetBundleFromDisk(string path)
{
try
{
if (!File.Exists(path))
{
Debug.LogError((object)("AssetBundle file not found at: " + path));
return null;
}
AssetBundle obj = AssetBundle.LoadFromFile(path);
if ((Object)(object)obj == (Object)null)
{
Debug.LogError((object)("Failed to load AssetBundle from: " + path));
}
return obj;
}
catch (Exception ex)
{
Debug.LogError((object)("Exception loading AssetBundle: " + ex.Message));
return null;
}
}
public static AssetBundle? LoadAssetBundleFromResources(this Assembly assembly, string resourcePath)
{
try
{
using Stream stream = assembly.GetManifestResourceStream(resourcePath);
if (stream == null)
{
Debug.LogError((object)("Resource not found: " + resourcePath));
return null;
}
using MemoryStream memoryStream = new MemoryStream();
stream.CopyTo(memoryStream);
AssetBundle obj = AssetBundle.LoadFromMemory(memoryStream.ToArray());
if ((Object)(object)obj == (Object)null)
{
Debug.LogError((object)("Failed to load AssetBundle from embedded resource: " + resourcePath));
}
return obj;
}
catch (Exception ex)
{
Debug.LogError((object)("Exception loading AssetBundle from resources: " + ex.Message));
return null;
}
}
internal static string Generate9DigitHash(string input)
{
using SHA256 sHA = SHA256.Create();
return ((long)BitConverter.ToUInt32(sHA.ComputeHash(Encoding.UTF8.GetBytes(input)), 0) % 1000000000L).ToString("000 | 000 | 000");
}
internal static string GenerateHash(string input)
{
using SHA256 sHA = SHA256.Create();
return BitConverter.ToString(sHA.ComputeHash(Encoding.UTF8.GetBytes(input))).Trim();
}
internal static string GetUniqueHash(this BaseUnityPlugin baseUnity)
{
return GenerateHash(baseUnity.Info.Metadata.GUID + "|" + baseUnity.Info.Metadata.Name);
}
internal static MethodBase PatchRpcMethod<T>(string rpcNamePrefix)
{
string rpcNamePrefix2 = rpcNamePrefix;
List<MethodInfo> list = (from m in typeof(T).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
where m.Name.StartsWith(rpcNamePrefix2)
select m).ToList();
if (list.Count == 0)
{
throw new Exception($"Could not find method that starts with {rpcNamePrefix2} in {typeof(T)}");
}
return list[0];
}
internal static GameObject? FindInactive(string path, string sceneName = null)
{
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
if (string.IsNullOrEmpty(path))
{
Debug.LogError((object)"[FindInactive] Path is null or empty");
return null;
}
string[] array = path.Split('/');
if (array.Length == 0)
{
Debug.LogError((object)"[FindInactive] Path has no valid segments");
return null;
}
bool flag = string.IsNullOrEmpty(sceneName);
Transform val = null;
for (int i = 0; i < SceneManager.sceneCount; i++)
{
Scene sceneAt = SceneManager.GetSceneAt(i);
if (!flag && !((Scene)(ref sceneAt)).name.Equals(sceneName))
{
continue;
}
GameObject[] rootGameObjects = ((Scene)(ref sceneAt)).GetRootGameObjects();
foreach (GameObject val2 in rootGameObjects)
{
if (((Object)val2).name.Equals(array[0]))
{
val = val2.transform;
Debug.Log((object)("[FindInactive] Found root '" + array[0] + "' in scene '" + ((Scene)(ref sceneAt)).name + "'"));
break;
}
}
if ((Object)(object)val != (Object)null)
{
break;
}
}
if ((Object)(object)val == (Object)null)
{
Debug.LogError((object)("[FindInactive] Root object '" + array[0] + "' not found " + (flag ? "in any scene" : ("in scene '" + sceneName + "'"))));
return null;
}
for (int k = 1; k < array.Length; k++)
{
val = val.Find(array[k]);
if ((Object)(object)val == (Object)null)
{
Debug.LogError((object)("[FindInactive] Child '" + array[k] + "' not found under '" + array[k - 1] + "'"));
return null;
}
}
Debug.Log((object)("[FindInactive] Successfully found '" + path + "' " + (flag ? "" : ("in scene '" + sceneName + "'"))));
return ((Component)val).gameObject;
}
}
internal class WavUtility
{
public static AudioClip? ToAudioClip(byte[] wavBytes)
{
//IL_0190: Unknown result type (might be due to invalid IL or missing references)
//IL_0197: Expected O, but got Unknown
if (wavBytes.Length < 44)
{
BMAPlugin.Log.LogError((object)"Invalid WAV file (too short)");
return null;
}
if (wavBytes[0] != 82 || wavBytes[1] != 73 || wavBytes[2] != 70 || wavBytes[3] != 70)
{
BMAPlugin.Log.LogError((object)"Invalid WAV file (missing RIFF header)");
return null;
}
int num = BitConverter.ToInt32(wavBytes, 24);
int num2 = BitConverter.ToInt16(wavBytes, 22);
int num3 = BitConverter.ToInt32(wavBytes, 40) / 2;
int i;
for (i = 36; i < wavBytes.Length - 8; i++)
{
if (wavBytes[i] == 100 && wavBytes[i + 1] == 97 && wavBytes[i + 2] == 116 && wavBytes[i + 3] == 97)
{
i += 4;
BitConverter.ToInt32(wavBytes, i);
i += 4;
break;
}
}
float[] array = new float[num3];
for (int j = 0; j < num3; j++)
{
short num4 = BitConverter.ToInt16(wavBytes, i + j * 2);
array[j] = (float)num4 / 32768f;
}
Type typeFromHandle = typeof(AudioClip);
Type[] types = new Type[5]
{
typeof(string),
typeof(int),
typeof(int),
typeof(int),
typeof(bool)
};
MethodInfo? method = typeFromHandle.GetMethod("Create", BindingFlags.Static | BindingFlags.Public, null, types, null);
if (method == null)
{
throw new MissingMethodException("AudioClip.Create method not found!");
}
AudioClip val = (AudioClip)method.Invoke(null, new object[5]
{
"LoadedWav",
num3 / num2,
num2,
num,
false
});
MethodInfo? method2 = typeFromHandle.GetMethod("SetData", BindingFlags.Instance | BindingFlags.Public, null, new Type[2]
{
typeof(float[]),
typeof(int)
}, null);
if (method2 == null)
{
throw new MissingMethodException("AudioClip.SetData method not found!");
}
method2.Invoke(val, new object[2] { array, 0 });
return val;
}
}
}
namespace BlackMagicAPI.Enums
{
public enum SpellType
{
Page
}
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class IgnoresAccessChecksToAttribute : Attribute
{
public IgnoresAccessChecksToAttribute(string assemblyName)
{
}
}
}