Decompiled source of EnchantGlowToggle v1.3.0

EnchantGlowToggle.dll

Decompiled 17 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using EpicLoot;
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("EnchantGlowToggle")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("EnchantGlowToggle")]
[assembly: AssemblyTitle("EnchantGlowToggle")]
[assembly: AssemblyVersion("1.0.0.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 EnchantGlowToggle
{
	[BepInPlugin("pieter.valheim.enchantglowtoggle", "Enchant Glow Toggle", "1.3.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		private enum Match
		{
			SameItem,
			AnyAppearance,
			Off
		}

		public const string Guid = "pieter.valheim.enchantglowtoggle";

		public const string Name = "Enchant Glow Toggle";

		public const string Version = "1.3.0";

		private const string EpicLootGuid = "randyknapp.mods.epicloot";

		private const string EquipmentSlotsGuid = "cdev.equipmentslots";

		private const string LookKey = "CDEV_EquipmentSlots_look";

		private const string GlowFx = "GlowingAura";

		private static readonly int HiddenKey = StringExtensionMethods.GetStableHashCode("pieter_enchantglowtoggle_hidden");

		private static readonly int FxKey = StringExtensionMethods.GetStableHashCode("pieter_enchantglowtoggle_fx");

		private static ConfigEntry<bool> _legendaryFallback;

		private static ConfigEntry<bool> _shareAuras;

		[ThreadStatic]
		private static bool _publishing;

		private static readonly Dictionary<Player, Dictionary<string, GameObject>> RemoteFx = new Dictionary<Player, Dictionary<string, GameObject>>();

		private static ConfigEntry<Match> _appearance;

		private static ConfigEntry<bool> _hideGlowing;

		private static ConfigEntry<bool> _hideAll;

		private static ConfigEntry<bool> _hideTextures;

		private static ConfigEntry<bool> _effectsBehind;

		private static ConfigEntry<bool> _texturesBehind;

		private static MethodInfo _refreshFx;

		private static readonly FieldRef<Humanoid, ItemData> Helmet = AccessTools.FieldRefAccess<Humanoid, ItemData>("m_helmetItem");

		private static readonly FieldRef<Humanoid, ItemData> Chest = AccessTools.FieldRefAccess<Humanoid, ItemData>("m_chestItem");

		private static readonly FieldRef<Humanoid, ItemData> Legs = AccessTools.FieldRefAccess<Humanoid, ItemData>("m_legItem");

		private static readonly FieldRef<Humanoid, ItemData> Cape = AccessTools.FieldRefAccess<Humanoid, ItemData>("m_shoulderItem");

		private static readonly FieldRef<Humanoid, VisEquipment> Vis = AccessTools.FieldRefAccess<Humanoid, VisEquipment>("m_visEquipment");

		private static readonly string[] VisHashFields = new string[4] { "m_currentHelmetItemHash", "m_currentChestItemHash", "m_currentLegItemHash", "m_currentShoulderItemHash" };

		[ThreadStatic]
		private static Player _dressing;

		private static readonly Dictionary<Player, int> KnownMasks = new Dictionary<Player, int>();

		private float _nextCheck;

		private void Awake()
		{
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Expected O, but got Unknown
			_appearance = ((BaseUnityPlugin)this).Config.Bind<Match>("Appearance tab", "When to hide", Match.SameItem, "When a slot's Appearance tab choice hides the enchant look below. SameItem: only when the appearance is the same item. AnyAppearance: whenever an appearance is set. Off: never. Shared with other players who have this mod.");
			_effectsBehind = ((BaseUnityPlugin)this).Config.Bind<bool>("Appearance tab", "Hide glow and effects", true, "Hide the item's enchantment effects (e.g. the Glowing aura) behind the appearance.");
			_texturesBehind = ((BaseUnityPlugin)this).Config.Bind<bool>("Appearance tab", "Hide legendary texture", true, "Hide the item's legendary texture (e.g. the blue Heimdall/Ragnar armor) behind the appearance.");
			_hideGlowing = ((BaseUnityPlugin)this).Config.Bind<bool>("Always", "Hide Glowing aura", false, "Never show the light and sparkles of the Glowing enchantment (on anyone, on your screen).");
			_hideAll = ((BaseUnityPlugin)this).Config.Bind<bool>("Always", "Hide all enchantment effects", false, "Never show any equip effect of Epic Loot enchantments or legendaries (on anyone, on your screen).");
			_hideTextures = ((BaseUnityPlugin)this).Config.Bind<bool>("Always", "Hide legendary textures", false, "Never show Epic Loot's legendary texture replacements (on anyone, on your screen).");
			_legendaryFallback = ((BaseUnityPlugin)this).Config.Bind<bool>("Effects", "Show enchant effects on legendaries", true, "Legendary items without an effect of their own show the effect of their enchantments (e.g. Glowing). Epic Loot normally shows nothing for them.");
			_shareAuras = ((BaseUnityPlugin)this).Config.Bind<bool>("Effects", "Show auras on other players", true, "Show the enchantment auras (e.g. Glowing) other players with this mod are wearing. Epic Loot alone only shows your own.");
			_legendaryFallback.SettingChanged += delegate
			{
				RefreshAll();
			};
			Type type = AccessTools.TypeByName("EpicLoot.VisEquipment_Patch");
			MethodInfo methodInfo = ((type == null) ? null : AccessTools.Method(type, "GetEquipFxName", (Type[])null, (Type[])null));
			MethodInfo methodInfo2 = ((type == null) ? null : AccessTools.Method(type, "SetTextureOverrides", (Type[])null, (Type[])null));
			_refreshFx = ((type == null) ? null : AccessTools.Method(type, "RefreshPlayerFx", (Type[])null, (Type[])null));
			if (methodInfo == null || methodInfo2 == null || _refreshFx == null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"Disabled, Epic Loot's equipment visuals were not found.");
				return;
			}
			Harmony val = new Harmony("pieter.valheim.enchantglowtoggle");
			val.Patch((MethodBase)methodInfo, (HarmonyMethod)null, Hook("EquipFxPostfix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)methodInfo2, Hook("TexturePrefix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)_refreshFx, Hook("DressPlayerPrefix"), (HarmonyMethod)null, (HarmonyMethod)null, Hook("DressFinalizer"), (HarmonyMethod)null);
			string[] array = new string[2] { "AttachItem_Postfix", "AttachArmor_Postfix" };
			foreach (string text in array)
			{
				MethodInfo methodInfo3 = AccessTools.Method(type, text, (Type[])null, (Type[])null);
				if (methodInfo3 != null)
				{
					val.Patch((MethodBase)methodInfo3, Hook("DressVisPrefix"), (HarmonyMethod)null, (HarmonyMethod)null, Hook("DressFinalizer"), (HarmonyMethod)null);
				}
			}
			_appearance.SettingChanged += delegate
			{
				RefreshAll();
			};
			_effectsBehind.SettingChanged += delegate
			{
				RefreshAll();
			};
			_texturesBehind.SettingChanged += delegate
			{
				RefreshAll();
			};
			_hideGlowing.SettingChanged += delegate
			{
				RefreshAll();
			};
			_hideAll.SettingChanged += delegate
			{
				RefreshAll();
			};
			_hideTextures.SettingChanged += delegate
			{
				RefreshAll();
			};
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Enchantment looks hide behind Appearance tab choices (shared with other players).");
		}

		private static HarmonyMethod Hook(string name)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			return new HarmonyMethod(typeof(Plugin).GetMethod(name, BindingFlags.Static | BindingFlags.NonPublic));
		}

		private static int SlotBit(ItemData item)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: 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)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Invalid comparison between Unknown and I4
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Invalid comparison between Unknown and I4
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Invalid comparison between Unknown and I4
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Invalid comparison between Unknown and I4
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Invalid comparison between Unknown and I4
			ItemType? val = item?.m_shared?.m_itemType;
			if (val.HasValue)
			{
				ItemType valueOrDefault = val.GetValueOrDefault();
				if ((int)valueOrDefault <= 7)
				{
					if ((int)valueOrDefault == 6)
					{
						return 1;
					}
					if ((int)valueOrDefault == 7)
					{
						return 2;
					}
				}
				else
				{
					if ((int)valueOrDefault == 11)
					{
						return 4;
					}
					if ((int)valueOrDefault == 17)
					{
						return 8;
					}
				}
			}
			return 0;
		}

		private static int LocalMask(Player player)
		{
			if (_appearance.Value == Match.Off || player?.m_customData == null)
			{
				return 0;
			}
			if (!player.m_customData.TryGetValue("CDEV_EquipmentSlots_look", out var value) || string.IsNullOrEmpty(value))
			{
				return 0;
			}
			string[] array = value.Split(new char[1] { '|' });
			ItemData[] array2 = (ItemData[])(object)new ItemData[4]
			{
				Helmet.Invoke((Humanoid)(object)player),
				Chest.Invoke((Humanoid)(object)player),
				Legs.Invoke((Humanoid)(object)player),
				Cape.Invoke((Humanoid)(object)player)
			};
			int num = 0;
			for (int i = 0; i < array2.Length && i < array.Length; i++)
			{
				if (array[i].Length != 0 && array2[i] != null && (_appearance.Value == Match.AnyAppearance || ((Object)(object)array2[i].m_dropPrefab != (Object)null && ((Object)array2[i].m_dropPrefab).name == array[i])))
				{
					num |= 1 << i;
				}
			}
			return (_effectsBehind.Value ? num : 0) | (_texturesBehind.Value ? (num << 4) : 0);
		}

		private static int MaskOf(Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return 0;
			}
			if ((Object)(object)player == (Object)(object)Player.m_localPlayer)
			{
				return LocalMask(player);
			}
			ZNetView component = ((Component)player).GetComponent<ZNetView>();
			ZDO obj = (((Object)(object)component != (Object)null && component.IsValid()) ? component.GetZDO() : null);
			if (obj == null)
			{
				return 0;
			}
			return obj.GetInt(HiddenKey, 0);
		}

		private static bool Hidden(Player player, ItemData item, bool texture)
		{
			if ((Object)(object)player == (Object)null && item != null && (Object)(object)Player.m_localPlayer != (Object)null && ((Humanoid)Player.m_localPlayer).IsItemEquiped(item))
			{
				player = Player.m_localPlayer;
			}
			int num = SlotBit(item) << (texture ? 4 : 0);
			if (num != 0)
			{
				return (MaskOf(player) & num) != 0;
			}
			return false;
		}

		private static void DressPlayerPrefix(Player player)
		{
			_dressing = player;
		}

		private static void DressVisPrefix(VisEquipment __0)
		{
			_dressing = (((Object)(object)__0 != (Object)null) ? ((Component)__0).GetComponent<Player>() : null);
		}

		private static Exception DressFinalizer(Exception __exception)
		{
			_dressing = null;
			return __exception;
		}

		private static void EquipFxPostfix(ItemData equippedItem, ref string __result, ref FxAttachMode mode)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected I4, but got Unknown
			if (equippedItem == null)
			{
				return;
			}
			MagicItem val = default(MagicItem);
			if (string.IsNullOrEmpty(__result) && _legendaryFallback.Value && ItemDataExtensions.IsMagic(equippedItem, ref val) && val.IsUniqueLegendary() && string.IsNullOrEmpty(val.GetLegendaryInfo()?.EquipFx))
			{
				FxAttachMode val2 = default(FxAttachMode);
				string firstEquipEffect = val.GetFirstEquipEffect(ref val2);
				if (!string.IsNullOrEmpty(firstEquipEffect))
				{
					__result = firstEquipEffect;
					mode = (FxAttachMode)(int)val2;
				}
			}
			if (!string.IsNullOrEmpty(__result) && ((!_publishing && (_hideAll.Value || (_hideGlowing.Value && __result == "GlowingAura"))) || Hidden(_dressing, equippedItem, texture: false)))
			{
				__result = null;
			}
		}

		private static string LocalAuras(Player player)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Invalid comparison between Unknown and I4
			SortedSet<string> sortedSet = new SortedSet<string>(StringComparer.Ordinal);
			_publishing = true;
			try
			{
				FxAttachMode val = default(FxAttachMode);
				foreach (ItemData equippedItem in ((Humanoid)player).GetInventory().GetEquippedItems())
				{
					if (equippedItem != null && ItemDataExtensions.IsMagic(equippedItem))
					{
						string equipFxName = VisEquipment_Patch.GetEquipFxName(equippedItem, ref val);
						if ((int)val == 1 && !string.IsNullOrEmpty(equipFxName))
						{
							sortedSet.Add(equipFxName);
						}
					}
				}
			}
			finally
			{
				_publishing = false;
			}
			return string.Join(",", sortedSet);
		}

		private static void UpdateRemoteAuras(Player player, string shared)
		{
			if (!RemoteFx.TryGetValue(player, out var value))
			{
				value = (RemoteFx[player] = new Dictionary<string, GameObject>());
			}
			HashSet<string> hashSet = new HashSet<string>((_shareAuras.Value && !_hideAll.Value && !string.IsNullOrEmpty(shared)) ? (from n in shared.Split(new char[1] { ',' })
				where n.Length > 0 && (!_hideGlowing.Value || !(n == "GlowingAura"))
				select n) : Enumerable.Empty<string>());
			foreach (string item in value.Keys.ToList())
			{
				if (!hashSet.Contains(item) || !((Object)(object)value[item] != (Object)null))
				{
					if ((Object)(object)value[item] != (Object)null)
					{
						Object.Destroy((Object)(object)value[item]);
					}
					value.Remove(item);
				}
			}
			foreach (string item2 in hashSet)
			{
				if (value.ContainsKey(item2))
				{
					continue;
				}
				GameObject val = EpicLoot.LoadAsset<GameObject>(item2);
				if (!((Object)(object)val == (Object)null))
				{
					bool forceDisableInit = ZNetView.m_forceDisableInit;
					ZNetView.m_forceDisableInit = true;
					try
					{
						GameObject val2 = Object.Instantiate<GameObject>(val, ((Component)player).transform, false);
						((Object)val2).name = item2;
						value[item2] = val2;
					}
					finally
					{
						ZNetView.m_forceDisableInit = forceDisableInit;
					}
				}
			}
		}

		private static bool TexturePrefix(VisEquipment __0, ItemData __3)
		{
			if (_hideTextures.Value)
			{
				return false;
			}
			return !Hidden(((Object)(object)__0 != (Object)null) ? ((Component)__0).GetComponent<Player>() : null, __3, texture: true);
		}

		private void Update()
		{
			if (Time.time < _nextCheck || (Object)(object)Player.m_localPlayer == (Object)null)
			{
				return;
			}
			_nextCheck = Time.time + 0.5f;
			Player localPlayer = Player.m_localPlayer;
			int num = LocalMask(localPlayer);
			ZNetView component = ((Component)localPlayer).GetComponent<ZNetView>();
			ZDO val = (((Object)(object)component != (Object)null && component.IsValid()) ? component.GetZDO() : null);
			if (val != null && component.IsOwner() && val.GetInt(HiddenKey, 0) != num)
			{
				val.Set(HiddenKey, num, false);
			}
			if (val != null && component.IsOwner())
			{
				string text = LocalAuras(localPlayer);
				if (val.GetString(FxKey, "") != text)
				{
					val.Set(FxKey, text);
				}
			}
			foreach (Player allPlayer in Player.GetAllPlayers())
			{
				if ((Object)(object)allPlayer == (Object)null)
				{
					continue;
				}
				if ((Object)(object)allPlayer != (Object)(object)localPlayer)
				{
					ZNetView component2 = ((Component)allPlayer).GetComponent<ZNetView>();
					ZDO val2 = (((Object)(object)component2 != (Object)null && component2.IsValid()) ? component2.GetZDO() : null);
					UpdateRemoteAuras(allPlayer, ((val2 != null) ? val2.GetString(FxKey, "") : null) ?? "");
				}
				int num2 = MaskOf(allPlayer);
				if (!KnownMasks.TryGetValue(allPlayer, out var value) || value != num2)
				{
					bool num3 = !KnownMasks.ContainsKey(allPlayer);
					KnownMasks[allPlayer] = num2;
					if (!num3 || num2 != 0)
					{
						Redress(allPlayer);
					}
				}
			}
			if (KnownMasks.Count > 32)
			{
				List<Player> list = new List<Player>();
				foreach (Player key in KnownMasks.Keys)
				{
					if ((Object)(object)key == (Object)null)
					{
						list.Add(key);
					}
				}
				foreach (Player item in list)
				{
					KnownMasks.Remove(item);
				}
			}
			foreach (Player item2 in RemoteFx.Keys.Where((Player p) => (Object)(object)p == (Object)null).ToList())
			{
				RemoteFx.Remove(item2);
			}
		}

		private static void RefreshAll()
		{
			foreach (Player allPlayer in Player.GetAllPlayers())
			{
				Redress(allPlayer);
			}
		}

		private static void Redress(Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return;
			}
			try
			{
				VisEquipment val = Vis.Invoke((Humanoid)(object)player);
				if ((Object)(object)val != (Object)null)
				{
					string[] visHashFields = VisHashFields;
					foreach (string text in visHashFields)
					{
						Traverse.Create((object)val).Field(text).SetValue((object)(-1));
					}
				}
				_refreshFx.Invoke(null, new object[1] { player });
			}
			catch (Exception)
			{
			}
		}
	}
}