Decompiled source of LanternTrinket v1.0.6

BepInEx/plugins/Cjayride.LanternTrinket.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Cjayride.LanternTrinket
{
	[BepInPlugin("cjayride.LanternTrinket", "Lantern Trinket", "1.0.6")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "cjayride.LanternTrinket";

		public const string PluginName = "Lantern Trinket";

		public const string PluginVersion = "1.0.6";

		public static ConfigEntry<bool> EnchantsOnlyWhileLit;

		public static ConfigEntry<string> SeneaLSlot;

		private static Harmony _harmony;

		private static MethodInfo _resetCache;

		private static MethodInfo _setLight;

		private static MethodInfo _setState;

		private static bool _wispPatched;

		private static bool _sawLight;

		private static bool _haveLight;

		private void Awake()
		{
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Expected O, but got Unknown
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Expected O, but got Unknown
			EnchantsOnlyWhileLit = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnchantsOnlyWhileLit", true, "EpicLoot effects on the hip lantern count only while its light is on.");
			SeneaLSlot = ((BaseUnityPlugin)this).Config.Bind<string>("General", "SeneaL slot", "Charm", new ConfigDescription("SeneaL UI equipment slot the hip lantern equips into. Charm is the wisplight and wishbone cell.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[7] { "Charm", "Belt", "Trinket", "Head", "Cape", "Chest", "Legs" }), Array.Empty<object>()));
			_harmony = new Harmony("cjayride.LanternTrinket");
			_harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Hip lantern slot comes from the SeneaL slot config. Enchants count only while the light is on.");
		}

		private void LateUpdate()
		{
			WispSlot.Apply();
			EnsureWispPatch();
			Player localPlayer = Player.m_localPlayer;
			ItemData val = (((Object)(object)localPlayer == (Object)null) ? null : Lit.EquippedLantern(localPlayer));
			if (val != null)
			{
				WispSlot.Move(localPlayer, val);
			}
		}

		private void EnsureWispPatch()
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Expected O, but got Unknown
			if (_wispPatched || _harmony == null)
			{
				return;
			}
			MethodInfo methodInfo = AccessTools.Method("SeneaLUI.Inv.Slots:IsCharm", (Type[])null, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method("SeneaLUI.Inv.Slots:SlotFor", (Type[])null, (Type[])null);
			if (!(methodInfo == null) && !(methodInfo2 == null))
			{
				_harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(CountLanternAsCharm), "Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				_harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(typeof(CountLanternAsCharm), "Slot", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				_wispPatched = true;
				Player localPlayer = Player.m_localPlayer;
				ItemData val = (((Object)(object)localPlayer == (Object)null) ? null : Lit.EquippedLantern(localPlayer));
				if (val != null)
				{
					WispSlot.Move(localPlayer, val);
				}
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Hip lantern uses the SeneaL " + ((SeneaLSlot != null) ? SeneaLSlot.Value : "Charm") + " slot."));
			}
		}

		private void Update()
		{
			if (EnchantsOnlyWhileLit == null || !EnchantsOnlyWhileLit.Value)
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				_haveLight = false;
				return;
			}
			ItemData val = Lit.EquippedLantern(localPlayer);
			if (val == null)
			{
				_haveLight = false;
				_sawLight = false;
				return;
			}
			bool flag = Lit.LightOn(val);
			if (!_haveLight)
			{
				_haveLight = true;
				_sawLight = flag;
			}
			else if (flag != _sawLight)
			{
				_sawLight = flag;
				Lit.ResetMagicTotals(localPlayer);
				((Character)localPlayer).Message((MessageType)1, flag ? "Lantern on" : "Lantern off", 0, (Sprite)null, false);
			}
		}

		internal static void StartDark(Player player, ItemData item)
		{
			if (!Lit.IsLantern(item))
			{
				return;
			}
			if (_setLight == null)
			{
				_setLight = AccessTools.Method("HipLantern.LanternItem:SetLightEnabled", (Type[])null, (Type[])null);
			}
			if (_setState == null)
			{
				_setState = AccessTools.Method("HipLantern.VisEquipmentExtension:SetLanternState", (Type[])null, (Type[])null);
			}
			try
			{
				_setLight?.Invoke(null, new object[2] { item, false });
				VisEquipment val = (((Object)(object)player != (Object)null) ? ((Component)player).GetComponent<VisEquipment>() : null);
				if ((Object)(object)val != (Object)null)
				{
					_setState?.Invoke(null, new object[2] { val, item });
				}
			}
			catch (Exception)
			{
			}
			_haveLight = true;
			_sawLight = false;
			if ((Object)(object)player != (Object)null)
			{
				((Character)player).Message((MessageType)1, "Lantern off", 0, (Sprite)null, false);
			}
		}

		internal static void ResetMagicTotals(Player player)
		{
			if (_resetCache == null)
			{
				Type type = AccessTools.TypeByName("EpicLoot.EquipmentEffectCache");
				_resetCache = ((type == null) ? null : AccessTools.Method(type, "Reset", (Type[])null, (Type[])null));
			}
			try
			{
				_resetCache?.Invoke(null, new object[1] { player });
			}
			catch (Exception)
			{
			}
		}
	}
	internal static class WispSlot
	{
		private static FieldInfo _useUtility;

		private static FieldInfo _slotType;

		private static MethodInfo _apply;

		private static MethodInfo _slotCell;

		private static bool _lookedUp;

		private static bool _synced;

		public static bool CharmChosen()
		{
			return string.Equals(ChosenName(), "Charm", StringComparison.OrdinalIgnoreCase);
		}

		public static void Apply()
		{
			Lookup();
			if (_synced || _useUtility == null)
			{
				return;
			}
			SetConfig(_useUtility, false);
			_synced = true;
			try
			{
				_apply?.Invoke(null, null);
			}
			catch (Exception)
			{
			}
			Player localPlayer = Player.m_localPlayer;
			ItemData val = WornLantern(localPlayer);
			if ((Object)(object)localPlayer != (Object)null && val != null)
			{
				if (((Humanoid)localPlayer).IsItemEquiped(val))
				{
					((Humanoid)localPlayer).UnequipItem(val, false);
				}
				((Humanoid)localPlayer).EquipItem(val, false);
			}
		}

		public static void Move(Player player, ItemData item)
		{
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null || !Lit.IsLantern(item) || item.m_shared == null)
			{
				return;
			}
			Lookup();
			Inventory inventory = ((Humanoid)player).GetInventory();
			if (inventory == null || _slotCell == null)
			{
				return;
			}
			object obj = null;
			try
			{
				obj = _slotCell.Invoke(null, new object[2]
				{
					inventory,
					SlotId()
				});
			}
			catch (Exception)
			{
				return;
			}
			int num = (int)obj.GetType().GetField("x").GetValue(obj);
			int num2 = (int)obj.GetType().GetField("y").GetValue(obj);
			if (num < 0 || (item.m_gridPos.x == num && item.m_gridPos.y == num2))
			{
				return;
			}
			ItemData itemAt = inventory.GetItemAt(num, num2);
			if (itemAt != null && itemAt != item)
			{
				if (itemAt.m_equipped)
				{
					((Humanoid)player).UnequipItem(itemAt, false);
				}
				itemAt.m_gridPos = item.m_gridPos;
			}
			item.m_gridPos = new Vector2i(num, num2);
			inventory.Changed(false, false);
		}

		private static string ChosenName()
		{
			string text = ((Plugin.SeneaLSlot != null) ? Plugin.SeneaLSlot.Value : "Charm");
			if (!string.IsNullOrEmpty(text))
			{
				return text;
			}
			return "Charm";
		}

		public static int SlotId()
		{
			return ChosenName().ToLowerInvariant() switch
			{
				"belt" => 3, 
				"trinket" => 5, 
				"head" => 0, 
				"cape" => 1, 
				"chest" => 2, 
				"legs" => 4, 
				_ => 7, 
			};
		}

		private static ItemData WornLantern(Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return null;
			}
			ItemData val = Lit.EquippedLantern(player);
			if (val != null)
			{
				return val;
			}
			Inventory inventory = ((Humanoid)player).GetInventory();
			List<ItemData> list = ((inventory != null) ? inventory.GetAllItems() : null);
			if (list == null)
			{
				return null;
			}
			ItemData result = null;
			for (int i = 0; i < list.Count; i++)
			{
				if (Lit.IsLantern(list[i]))
				{
					result = list[i];
					if (list[i].m_equipped)
					{
						return list[i];
					}
				}
			}
			return result;
		}

		private static void SetConfig(FieldInfo field, object next)
		{
			if (!(field == null))
			{
				object value = field.GetValue(null);
				PropertyInfo propertyInfo = value?.GetType().GetProperty("Value");
				if (!(propertyInfo == null) && !object.Equals(propertyInfo.GetValue(value, null), next))
				{
					propertyInfo.SetValue(value, next, null);
				}
			}
		}

		private static void Lookup()
		{
			if (!_lookedUp)
			{
				_lookedUp = true;
				Type type = AccessTools.TypeByName("HipLantern.HipLantern");
				Type type2 = AccessTools.TypeByName("HipLantern.LanternItem");
				Type type3 = AccessTools.TypeByName("SeneaLUI.Inv.Slots");
				_useUtility = ((type == null) ? null : AccessTools.Field(type, "itemSlotUtility"));
				_slotType = ((type == null) ? null : AccessTools.Field(type, "itemSlotType"));
				_apply = ((type2 == null) ? null : AccessTools.Method(type2, "PatchLanternItemOnConfigChange", (Type[])null, (Type[])null));
				_slotCell = ((type3 == null) ? null : AccessTools.Method(type3, "SlotCell", (Type[])null, (Type[])null));
			}
		}
	}
	[HarmonyPatch(typeof(Humanoid), "EquipItem")]
	internal static class EquipIntoWisp
	{
		private static void Postfix(Humanoid __instance, ItemData item, bool __result)
		{
			if (__result)
			{
				Player val = (Player)(object)((__instance is Player) ? __instance : null);
				if (val != null)
				{
					WispSlot.Move(val, item);
					Plugin.StartDark(val, item);
				}
			}
		}
	}
	internal static class CountLanternAsCharm
	{
		public static void Postfix(ItemData item, ref bool __result)
		{
			if (WispSlot.CharmChosen() && Lit.IsLantern(item))
			{
				__result = true;
			}
		}

		public static void Slot(ItemData item, ref int __result)
		{
			if (Lit.IsLantern(item))
			{
				__result = WispSlot.SlotId();
			}
		}
	}
	[HarmonyPatch]
	internal static class QuietEnchantCue
	{
		private static readonly string[] CuePrefabs = new string[3] { "sfx_Potion_eitr_Start", "sfx_Potion_stamina_Start", "sfx_gui_craft" };

		private static bool Prepare()
		{
			return AccessTools.Method("HipLantern.LanternLightController:EmitSwitchEffect", (Type[])null, (Type[])null) != null;
		}

		private static MethodBase TargetMethod()
		{
			return AccessTools.Method("HipLantern.LanternLightController:EmitSwitchEffect", (Type[])null, (Type[])null);
		}

		private static bool Prefix(Component __instance, int variant)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			if (variant != 0 && variant != 2)
			{
				return true;
			}
			Play(__instance.transform.position);
			return false;
		}

		private static void Play(Vector3 position)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ZNetScene.instance == (Object)null)
			{
				return;
			}
			for (int i = 0; i < CuePrefabs.Length; i++)
			{
				GameObject prefab = ZNetScene.instance.GetPrefab(CuePrefabs[i]);
				if (!((Object)(object)prefab == (Object)null))
				{
					ZSFX componentInChildren = Object.Instantiate<GameObject>(prefab, position, Quaternion.identity).GetComponentInChildren<ZSFX>();
					if ((Object)(object)componentInChildren != (Object)null)
					{
						componentInChildren.SetVolumeModifier(0.35f);
					}
					break;
				}
			}
		}
	}
	internal static class Lit
	{
		public static bool IsLantern(ItemData item)
		{
			if (item?.m_shared == null)
			{
				return false;
			}
			if (item.m_shared.m_name == "$item_hiplantern")
			{
				return true;
			}
			if ((Object)(object)item.m_dropPrefab != (Object)null)
			{
				return ((Object)item.m_dropPrefab).name == "HipLantern";
			}
			return false;
		}

		public static bool LightOn(ItemData item)
		{
			if (item?.m_customData != null && item.m_customData.TryGetValue("HipLanternState", out var value) && !string.IsNullOrEmpty(value))
			{
				if (value.IndexOf("\"lightEnabled\":false", StringComparison.Ordinal) < 0)
				{
					return value.IndexOf("\"lightEnabled\": false", StringComparison.Ordinal) < 0;
				}
				return false;
			}
			if (item != null)
			{
				return item.m_variant != 1;
			}
			return true;
		}

		public static ItemData EquippedLantern(Player player)
		{
			Inventory inventory = ((Humanoid)player).GetInventory();
			List<ItemData> list = ((inventory != null) ? inventory.GetEquippedItems() : null);
			if (list == null)
			{
				return null;
			}
			for (int i = 0; i < list.Count; i++)
			{
				if (IsLantern(list[i]))
				{
					return list[i];
				}
			}
			return null;
		}

		public static void ResetMagicTotals(Player player)
		{
			Plugin.ResetMagicTotals(player);
		}
	}
	[HarmonyPatch]
	internal static class HideDarkLanternMagic
	{
		private static bool Prepare()
		{
			return AccessTools.Method("EpicLoot.PlayerExtensions:GetMagicEquipment", (Type[])null, (Type[])null) != null;
		}

		private static MethodBase TargetMethod()
		{
			return AccessTools.Method("EpicLoot.PlayerExtensions:GetMagicEquipment", (Type[])null, (Type[])null);
		}

		private static void Postfix(List<ItemData> __result)
		{
			if (Plugin.EnchantsOnlyWhileLit == null || !Plugin.EnchantsOnlyWhileLit.Value || __result == null)
			{
				return;
			}
			for (int num = __result.Count - 1; num >= 0; num--)
			{
				ItemData item = __result[num];
				if (Lit.IsLantern(item) && !Lit.LightOn(item))
				{
					__result.RemoveAt(num);
				}
			}
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}