Decompiled source of ArmorStandEnchant v1.0.0

Cjayride.ArmorStandEnchant.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 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.ArmorStandEnchant")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Cjayride.ArmorStandEnchant")]
[assembly: AssemblyTitle("Cjayride.ArmorStandEnchant")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.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.ArmorStandEnchant
{
	[BepInPlugin("cjayride.ArmorStandEnchant", "Armor Stand Enchant", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "cjayride.ArmorStandEnchant";

		public const string PluginName = "Armor Stand Enchant";

		public const string PluginVersion = "1.0.0";

		private void Awake()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			new Harmony("cjayride.ArmorStandEnchant").PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Armor stand items keep the enchantment, quality, and durability they had when they were placed.");
		}
	}
	internal sealed class Backup
	{
		public int Slot;

		public int Quality;

		public float Durability;

		public int Variant;

		public int WorldLevel;

		public long CrafterId;

		public string CrafterName;

		public Dictionary<string, string> Custom = new Dictionary<string, string>();

		public static Backup From(ItemData item, int slot)
		{
			Backup backup = new Backup
			{
				Slot = slot,
				Quality = item.m_quality,
				Durability = item.m_durability,
				Variant = item.m_variant,
				WorldLevel = item.m_worldLevel,
				CrafterId = item.m_crafterID,
				CrafterName = (item.m_crafterName ?? "")
			};
			foreach (KeyValuePair<string, string> customDatum in item.m_customData)
			{
				backup.Custom[customDatum.Key] = customDatum.Value;
			}
			return backup;
		}

		public byte[] Pack()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			val.Write(Quality);
			val.Write(Durability);
			val.Write(Variant);
			val.Write(WorldLevel);
			val.Write(CrafterId);
			val.Write(CrafterName ?? "");
			val.Write(Custom.Count);
			foreach (KeyValuePair<string, string> item in Custom)
			{
				val.Write(item.Key);
				val.Write(item.Value ?? "");
			}
			return val.GetArray();
		}

		public static Backup Unpack(int slot, byte[] bytes)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			if (bytes == null || bytes.Length < 8)
			{
				return null;
			}
			ZPackage val = new ZPackage(bytes);
			Backup backup = new Backup
			{
				Slot = slot
			};
			backup.Quality = val.ReadInt();
			backup.Durability = val.ReadSingle();
			backup.Variant = val.ReadInt();
			backup.WorldLevel = val.ReadInt();
			backup.CrafterId = val.ReadLong();
			backup.CrafterName = val.ReadString();
			int num = val.ReadInt();
			for (int i = 0; i < num; i++)
			{
				backup.Custom[val.ReadString()] = val.ReadString();
			}
			return backup;
		}
	}
	internal static class StandMemory
	{
		public static int Key(int slot)
		{
			int num = 17;
			string text = "cjay_ase" + slot;
			for (int i = 0; i < text.Length; i++)
			{
				num = num * 31 + text[i];
			}
			return num;
		}

		public static void Write(ZDO zdo, Backup backup)
		{
			if (zdo != null && backup != null)
			{
				zdo.Set(Key(backup.Slot), backup.Pack());
			}
		}

		public static Backup Read(ZDO zdo, int slot)
		{
			if (zdo == null)
			{
				return null;
			}
			return Backup.Unpack(slot, zdo.GetByteArray(Key(slot), (byte[])null));
		}

		public static void Clear(ZDO zdo, int slot)
		{
			if (zdo != null)
			{
				zdo.Set(Key(slot), Array.Empty<byte>());
			}
		}
	}
	internal static class MagicReload
	{
		private static MethodInfo dataMethod;

		private static MethodInfo loadAll;

		private static MethodInfo getMagic;

		private static MethodInfo loadMagic;

		private static bool lookedUp;

		public static void Apply(ItemData item)
		{
			if (item == null)
			{
				return;
			}
			Lookup();
			if (dataMethod == null)
			{
				return;
			}
			object obj;
			try
			{
				obj = dataMethod.Invoke(null, new object[1] { item });
			}
			catch (Exception)
			{
				return;
			}
			if (obj == null)
			{
				return;
			}
			try
			{
				loadAll?.Invoke(obj, null);
				if (getMagic != null)
				{
					object obj2 = getMagic.Invoke(obj, new object[1] { "" });
					loadMagic?.Invoke(obj2, null);
				}
			}
			catch (Exception)
			{
			}
		}

		private static void Lookup()
		{
			if (lookedUp)
			{
				return;
			}
			lookedUp = true;
			Type type = AccessTools.TypeByName("EpicLoot.Data.ItemExtensions");
			dataMethod = ((type == null) ? null : AccessTools.Method(type, "Data", new Type[1] { typeof(ItemData) }, (Type[])null));
			if (dataMethod == null)
			{
				return;
			}
			Type returnType = dataMethod.ReturnType;
			loadAll = AccessTools.Method(returnType, "LoadAll", (Type[])null, (Type[])null);
			Type type2 = AccessTools.TypeByName("EpicLoot.MagicItemComponent");
			if (type2 == null)
			{
				return;
			}
			MethodInfo methodInfo = null;
			MethodInfo[] methods = returnType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (MethodInfo methodInfo2 in methods)
			{
				if (methodInfo2.Name == "Get" && methodInfo2.IsGenericMethodDefinition)
				{
					methodInfo = methodInfo2;
					break;
				}
			}
			if (!(methodInfo == null))
			{
				getMagic = methodInfo.MakeGenericMethod(type2);
				loadMagic = AccessTools.Method(type2, "Load", (Type[])null, (Type[])null);
			}
		}
	}
	[HarmonyPatch(typeof(ArmorStand), "UpdateAttach")]
	internal static class RememberOnAttach
	{
		private static void Prefix(ArmorStand __instance, out Backup __state)
		{
			__state = null;
			if (!((Object)(object)__instance == (Object)null) && Object.op_Implicit((Object)(object)__instance.m_nview) && __instance.m_nview.IsOwner())
			{
				Traverse val = Traverse.Create((object)__instance);
				ItemData value = val.Field("m_queuedItem").GetValue<ItemData>();
				if (value != null)
				{
					int value2 = val.Field("m_queuedSlot").GetValue<int>();
					__state = Backup.From(value, value2);
				}
			}
		}

		private static void Postfix(ArmorStand __instance, Backup __state)
		{
			if (__state != null && !((Object)(object)__instance == (Object)null) && Object.op_Implicit((Object)(object)__instance.m_nview) && __instance.m_nview.IsValid())
			{
				StandMemory.Write(__instance.m_nview.GetZDO(), __state);
			}
		}
	}
	[HarmonyPatch(typeof(ItemDrop), "LoadFromZDO")]
	internal static class NoteLoadedItem
	{
		public static ItemData Last;

		[HarmonyPriority(0)]
		private static void Postfix(ItemData itemData, int index)
		{
			if (index >= 0)
			{
				Last = itemData;
			}
		}
	}
	[HarmonyPatch(typeof(ArmorStand), "DropItem")]
	internal static class RestoreOnDrop
	{
		private static void Prefix()
		{
			NoteLoadedItem.Last = null;
		}

		private static void Postfix(ArmorStand __instance, int index)
		{
			if ((Object)(object)__instance == (Object)null || !Object.op_Implicit((Object)(object)__instance.m_nview) || !__instance.m_nview.IsOwner())
			{
				return;
			}
			ItemData last = NoteLoadedItem.Last;
			NoteLoadedItem.Last = null;
			ZDO zDO = __instance.m_nview.GetZDO();
			Backup backup = StandMemory.Read(zDO, index);
			if (last != null && backup != null)
			{
				if (backup.Quality > last.m_quality)
				{
					last.m_quality = backup.Quality;
				}
				if (backup.Durability > last.m_durability)
				{
					last.m_durability = backup.Durability;
				}
				if (last.m_crafterID == 0L && backup.CrafterId != 0L)
				{
					last.m_crafterID = backup.CrafterId;
					last.m_crafterName = backup.CrafterName;
				}
				if (last.m_variant == 0 && backup.Variant != 0)
				{
					last.m_variant = backup.Variant;
				}
				if (last.m_worldLevel == 0 && backup.WorldLevel != 0)
				{
					last.m_worldLevel = backup.WorldLevel;
				}
				foreach (KeyValuePair<string, string> item in backup.Custom)
				{
					if (!last.m_customData.ContainsKey(item.Key) || string.IsNullOrEmpty(last.m_customData[item.Key]))
					{
						last.m_customData[item.Key] = item.Value;
					}
				}
				last.m_equipped = false;
			}
			if (last != null)
			{
				MagicReload.Apply(last);
			}
			if (last != null)
			{
				ItemDrop[] array = Object.FindObjectsByType<ItemDrop>((FindObjectsInactive)0, (FindObjectsSortMode)0);
				foreach (ItemDrop val in array)
				{
					if ((Object)(object)val != (Object)null && val.m_itemData == last)
					{
						val.SetQuality(last.m_quality);
						val.Save();
						break;
					}
				}
			}
			StandMemory.Clear(zDO, index);
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}