Decompiled source of SenealCapeOnLogin v1.0.2

Cjayride.SenealCapeOnLogin.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: AssemblyCompany("Cjayride.SenealCapeOnLogin")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.2.0")]
[assembly: AssemblyInformationalVersion("1.0.2")]
[assembly: AssemblyProduct("Cjayride.SenealCapeOnLogin")]
[assembly: AssemblyTitle("Cjayride.SenealCapeOnLogin")]
[assembly: AssemblyVersion("1.0.2.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Cjayride.SenealCapeOnLogin
{
	[BepInPlugin("cjayride.SenealCapeOnLogin", "SeneaL Cape On Login", "1.0.2")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "cjayride.SenealCapeOnLogin";

		public const string PluginName = "SeneaL Cape On Login";

		public const string PluginVersion = "1.0.2";

		private void Awake()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			new Harmony("cjayride.SenealCapeOnLogin").PatchAll();
			if (!SenealCapeSlot.Available)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"SeneaL CapeSlot API not found; cape re-apply will not run.");
			}
			else
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Re-applies SeneaL UI cape slot after load when a backpack uses the shoulder slot.");
			}
		}
	}
	internal static class SenealInventorySlots
	{
		private static readonly MethodInfo ReadyMethod;

		private static readonly MethodInfo RelocateMethod;

		private static readonly MethodInfo ChangedMethod;

		internal static bool Available
		{
			get
			{
				if (RelocateMethod != null)
				{
					return ReadyMethod != null;
				}
				return false;
			}
		}

		static SenealInventorySlots()
		{
			Type type = AccessTools.TypeByName("SeneaLUI.Inv.Slots");
			if (!(type == null))
			{
				ReadyMethod = AccessTools.Method(type, "Ready", (Type[])null, (Type[])null);
				RelocateMethod = AccessTools.Method(type, "Relocate", (Type[])null, (Type[])null);
				ChangedMethod = AccessTools.Method(type, "Changed", (Type[])null, (Type[])null);
			}
		}

		internal static void PlaceInEquipRow(Inventory inventory, ItemData item)
		{
			if (!Available || inventory == null || item == null)
			{
				return;
			}
			try
			{
				if ((bool)ReadyMethod.Invoke(null, new object[1] { inventory }))
				{
					RelocateMethod.Invoke(null, new object[2] { inventory, item });
					ChangedMethod?.Invoke(null, new object[1] { inventory });
				}
			}
			catch
			{
			}
		}
	}
	internal static class SenealBackpacks
	{
		private static readonly MethodInfo IsBackpackMethod;

		private static readonly FieldInfo OnField;

		internal static bool Ready
		{
			get
			{
				if (OnField != null)
				{
					return (bool)OnField.GetValue(null);
				}
				return false;
			}
		}

		static SenealBackpacks()
		{
			Type type = AccessTools.TypeByName("SeneaLUI.Mods.Backpacks");
			IsBackpackMethod = ((type != null) ? AccessTools.Method(type, "IsBackpack", (Type[])null, (Type[])null) : null);
			OnField = ((type != null) ? AccessTools.Field(type, "On") : null);
		}

		internal static bool IsBackpack(ItemData item)
		{
			if (item == null || IsBackpackMethod == null)
			{
				return false;
			}
			try
			{
				return (bool)IsBackpackMethod.Invoke(null, new object[1] { item });
			}
			catch
			{
				return false;
			}
		}
	}
	internal static class SenealCapeSlot
	{
		private static readonly MethodInfo SetMethod;

		private static readonly MethodInfo UpdateModifiersMethod;

		private static readonly MethodInfo UpdateEquipmentMethod;

		private static readonly FieldInfo ItemField;

		private static readonly FieldInfo OwnerField;

		private static readonly FieldRef<Humanoid, ItemData> ShoulderItem;

		internal static bool Available
		{
			get
			{
				if (SetMethod != null && ItemField != null)
				{
					return UpdateModifiersMethod != null;
				}
				return false;
			}
		}

		static SenealCapeSlot()
		{
			ShoulderItem = AccessTools.FieldRefAccess<Humanoid, ItemData>("m_shoulderItem");
			Type type = AccessTools.TypeByName("SeneaLUI.Mods.CapeSlot");
			if (!(type == null))
			{
				SetMethod = AccessTools.Method(type, "Set", (Type[])null, (Type[])null);
				UpdateModifiersMethod = AccessTools.Method(type, "UpdateModifiers", (Type[])null, (Type[])null);
				UpdateEquipmentMethod = AccessTools.Method(type, "UpdateEquipment", (Type[])null, (Type[])null);
				ItemField = AccessTools.Field(type, "Item");
				OwnerField = AccessTools.Field(type, "_owner");
			}
		}

		internal static bool TryReapply(Player player)
		{
			if (!Available || (Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)Player.m_localPlayer)
			{
				return false;
			}
			if (!SenealBackpacks.Ready)
			{
				return false;
			}
			Inventory inventory = ((Humanoid)player).GetInventory();
			if (inventory == null)
			{
				return false;
			}
			ItemData val = ShoulderItem.Invoke((Humanoid)(object)player);
			if (val != null && !SenealBackpacks.IsBackpack(val))
			{
				return false;
			}
			object? value = ItemField.GetValue(null);
			ItemData val2 = (ItemData)((value is ItemData) ? value : null);
			ItemData val3 = ResolveCape(inventory, val2);
			if (val3 == null)
			{
				return false;
			}
			object? obj = OwnerField?.GetValue(null);
			if ((Object)((obj is Humanoid) ? obj : null) != (Object)(object)player || val2 != val3 || !val3.m_equipped)
			{
				SetMethod.Invoke(null, new object[3] { player, val3, false });
			}
			UpdateModifiersMethod.Invoke(null, new object[1] { player });
			if (UpdateEquipmentMethod != null)
			{
				UpdateEquipmentMethod.Invoke(null, new object[2] { player, 0f });
			}
			SenealInventorySlots.PlaceInEquipRow(inventory, val3);
			return ItemField.GetValue(null) == val3;
		}

		private static ItemData ResolveCape(Inventory inventory, ItemData slotItem)
		{
			if (slotItem != null && inventory.ContainsItem(slotItem))
			{
				return slotItem;
			}
			ItemData val = null;
			ItemData val2 = null;
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				if (IsCape(allItem))
				{
					if (val2 == null)
					{
						val2 = allItem;
					}
					if (allItem.m_equipped)
					{
						val = allItem;
					}
				}
			}
			return val ?? val2;
		}

		private static bool IsCape(ItemData item)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Invalid comparison between Unknown and I4
			if (item?.m_shared == null)
			{
				return false;
			}
			if ((int)item.m_shared.m_itemType == 17)
			{
				return !SenealBackpacks.IsBackpack(item);
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(Player), "Load")]
	internal static class PlayerLoadReapplyCape
	{
		private static void Postfix(Player __instance)
		{
			CapeReapplyScheduler.ScheduleReapply(__instance);
		}
	}
	[HarmonyPatch(typeof(Player), "OnSpawned")]
	internal static class PlayerOnSpawnedReapplyCape
	{
		private static void Postfix(Player __instance)
		{
			CapeReapplyScheduler.ScheduleReapply(__instance);
		}
	}
	[HarmonyPatch(typeof(Player), "OnRespawn")]
	internal static class PlayerOnRespawnReapplyCape
	{
		private static void Postfix(Player __instance)
		{
			CapeReapplyScheduler.ScheduleReapply(__instance);
		}
	}
	internal static class CapeReapplyScheduler
	{
		internal static void ScheduleReapply(Player player)
		{
			if (!((Object)(object)player != (Object)(object)Player.m_localPlayer) && SenealCapeSlot.Available)
			{
				((MonoBehaviour)player).StartCoroutine(ReapplyAfterLoad(player));
			}
		}

		private static IEnumerator ReapplyAfterLoad(Player player)
		{
			for (int i = 0; i < 180; i++)
			{
				if ((Object)(object)player == (Object)null)
				{
					break;
				}
				if ((Object)(object)player != (Object)(object)Player.m_localPlayer)
				{
					break;
				}
				if (SenealCapeSlot.TryReapply(player))
				{
					break;
				}
				yield return null;
			}
		}
	}
}