using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using JetBrains.Annotations;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;
using Zen.Compatibility;
using Zen.Config;
using Zen.Lib;
using Zen.Logging;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ZenItemStands")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ZenItemStands")]
[assembly: AssemblyCopyright("Copyright \ufffd 2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")]
[assembly: AssemblyFileVersion("0.0.1.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.1.0")]
[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 ZenItemStands
{
public class ArmorStandContainer : StandContainer
{
internal ArmorStand Stand;
protected override void Awake()
{
if (!Object.op_Implicit((Object)(object)Stand) && !((Component)this).TryGetComponent<ArmorStand>(ref Stand))
{
throw new Exception("ArmorStand component not found on " + ((Object)this).name);
}
((Container)this).m_name = Stand.m_name;
((Container)this).m_width = Stand.m_slots.Count;
((Container)this).m_height = 1;
((Component)this).GetComponentInChildren<Switch>().m_name = Stand.m_name;
base.Awake();
}
public override void ShowErrorMessage()
{
((Character)Player.m_localPlayer).Message((MessageType)2, "$piece_armorstand_cantattach", 0, (Sprite)null);
}
public override bool IsSameType(ItemData armorItem, ItemData compareItem)
{
ArmorStandSlot slot = GetSlot(armorItem);
if (slot != null)
{
return Stand.CanAttach(slot, compareItem);
}
return false;
}
private ArmorStandSlot? GetSlot(ItemData item)
{
ItemData item2 = item;
return ((IEnumerable<ArmorStandSlot>)Stand.m_slots).FirstOrDefault((Func<ArmorStandSlot, bool>)((ArmorStandSlot slot) => slot.m_currentItemName == ItemDataExt.GetName(item2)));
}
private ItemData? GetAttachedItemData(int index)
{
string attachedItem = Stand.GetAttachedItem(index);
Log.Debug((object)$"Index: {index} Item: {attachedItem}", (ushort)0);
return GetItemData(attachedItem, index);
}
protected override bool IsStandInventoryDiff()
{
int num = 0;
for (int i = 0; i < Stand.m_slots.Count; i++)
{
ItemData attachedItemData = GetAttachedItemData(i);
if (attachedItemData != null)
{
if (!ItemDataExt.HaveItemData(((Container)this).m_inventory, attachedItemData))
{
Log.Info((object)("Diff Item: " + ItemDataExt.GetName(attachedItemData)), (ushort)0);
return true;
}
num++;
}
}
bool num2 = num != ((Container)this).m_inventory.NrOfItems();
if (!num2)
{
Log.Debug((object)$"Container and stand are identical: {num} items", (ushort)0);
}
return num2;
}
public override bool CanAttach(ItemData item, bool ignoreExisting)
{
int index;
return CanAttach(item, out index, ignoreExisting);
}
private bool CanAttach(ItemData item, out int index, bool ignoreExisting)
{
ItemData item2 = item;
index = -1;
for (int i = 0; i < Stand.m_slots.Count; i++)
{
if (CanAttachAt(i))
{
index = i;
return true;
}
}
return false;
bool CanAttachAt(int index)
{
//IL_004b: 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)
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: Invalid comparison between Unknown and I4
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Invalid comparison between Unknown and I4
//IL_0083: Unknown result type (might be due to invalid IL or missing references)
ArmorStandSlot val = Stand.m_slots[index];
if (!Stand.CanAttach(val, item2))
{
return false;
}
if (!ignoreExisting && Stand.HaveAttachment(index))
{
return false;
}
ItemType itemType = item2.m_shared.m_itemType;
if (((int)itemType == 7 || (int)itemType == 11) ? true : false)
{
return true;
}
foreach (Transform item3 in item2.m_dropPrefab.transform)
{
if (((Object)item3).name.StartsWith("attach"))
{
return true;
}
}
return false;
}
}
public override bool CanSwap(ItemData externItem, out ItemData swapItem)
{
if (CanAttach(externItem, ignoreExisting: true))
{
foreach (ItemData allItem in ((Container)this).m_inventory.GetAllItems())
{
if (IsSameType(allItem, externItem))
{
swapItem = allItem;
return true;
}
}
}
swapItem = null;
return false;
}
public override void SwapEquip()
{
Inventory inventory = ((Container)this).m_inventory;
Player localPlayer = Player.m_localPlayer;
List<ItemData> equippedItems = ((Humanoid)localPlayer).GetInventory().GetEquippedItems();
if (((Humanoid)localPlayer).m_hiddenLeftItem != null)
{
equippedItems.Add(((Humanoid)localPlayer).m_hiddenLeftItem);
}
if (((Humanoid)localPlayer).m_hiddenRightItem != null)
{
equippedItems.Add(((Humanoid)localPlayer).m_hiddenRightItem);
}
ItemData[] array = inventory.GetAllItems().ToArray();
foreach (ItemData standItem in array)
{
((Humanoid)(object)localPlayer).EquipContainerStandItem(standItem);
}
((Humanoid)localPlayer).HideHandItems(false, true);
Inventory inventory2 = ((Humanoid)localPlayer).GetInventory();
foreach (ItemData item in equippedItems)
{
if (inventory2.ContainsItem(item) && CanAttach(item, ignoreExisting: false))
{
((Humanoid)localPlayer).UnequipItem(item, false);
inventory.MoveItemToThis(inventory2, item);
}
}
}
private bool AttachItem(ItemData item)
{
if (!CanAttach(item, out var index, ignoreExisting: false))
{
return false;
}
if (((Container)this).m_nview.IsOwner())
{
ZDO zDO = ((Container)this).m_nview.GetZDO();
zDO.Set(index + "_item", ((Object)item.m_dropPrefab).name);
ItemDrop.SaveToZDO(index, item, zDO);
}
return true;
}
protected override void UpdateVisualFromContainer()
{
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
if (IsStandInventoryDiff())
{
Log.Info((object)"Updating visuals and slot data", (ushort)0);
ClearArmorStand();
int num = ((Container)this).m_inventory.GetAllItems().Count(AttachItem);
Stand.UpdateVisual();
Transform transform = ((Component)this).transform;
Stand.m_effects.Create(transform.position, transform.rotation, (Transform)null, 1f, -1);
Log.Info((object)string.Format("{0} loaded {1} items from container", "ArmorStand", num), (ushort)0);
}
void ClearArmorStand()
{
for (int i = 0; i < Stand.m_slots.Count; i++)
{
Stand.SetVisualItem(i, string.Empty, 0);
if (((Container)this).m_nview.IsOwner())
{
((Container)this).m_nview.GetZDO().Set(i + "_item", string.Empty);
}
}
Stand.UpdateSupports();
}
}
protected override bool FillContainer()
{
Log.Info((object)"Fill inventory from slots", (ushort)0);
((Container)this).m_inventory.RemoveAll();
for (int i = 0; i < Stand.m_slots.Count; i++)
{
if (Stand.HaveAttachment(i))
{
ItemData attachedItemData = GetAttachedItemData(i);
if (attachedItemData != null)
{
((Container)this).m_inventory.AddItem(attachedItemData);
Log.Info((object)("Added item to container from ArmorStand slot: " + ItemDataExt.GetName(attachedItemData)), (ushort)0);
}
}
}
return true;
}
public override void ShowHideStackAllButton()
{
InventoryGuiExt.ShowStackAllButton(InventoryGui.instance, true);
}
}
public static class ArmorStandExt
{
public static void UpdateContainer(this ArmorStand armorStand)
{
StandContainer.UpdateContainer(((Component)armorStand).gameObject);
}
public static void ResetPose(this ArmorStand armorStand)
{
if (armorStand.m_pose != 0)
{
armorStand.m_nview.InvokeRPC(ZNetView.Everybody, "RPC_SetPose", new object[1] { 0 });
}
}
public static void NextPose(this ArmorStand armorStand)
{
armorStand.m_nview.InvokeRPC(ZNetView.Everybody, "RPC_SetPose", new object[1] { (armorStand.m_pose + 1) % armorStand.m_poseCount });
}
public static bool HasChestAndLegItem(this ArmorStand armorStand)
{
bool flag = false;
bool flag2 = false;
for (int i = 0; i < armorStand.m_slots.Count; i++)
{
string attachedItem = armorStand.GetAttachedItem(i);
if (!Utility.IsNullOrWhiteSpace(attachedItem))
{
ItemDrop component = ObjectDB.instance.GetItemPrefab(attachedItem).GetComponent<ItemDrop>();
if (ItemDataExt.IsItemType(component.m_itemData, (ItemType)7))
{
flag = true;
}
if (ItemDataExt.IsItemType(component.m_itemData, (ItemType)11))
{
flag2 = true;
}
if (flag && flag2)
{
return true;
}
}
}
return false;
}
}
[HarmonyPatch]
public static class ArmorStandPatch
{
[HarmonyPatch(typeof(ArmorStand), "SetPose")]
private static class ArmorStandSetPose
{
[UsedImplicitly]
private static void Prefix(ref bool effect)
{
effect = false;
}
[UsedImplicitly]
private static void Postfix(ArmorStand __instance)
{
__instance.UpdateSupports();
Log.Info((object)string.Format("{0} index: {1}", "SetPose", __instance.m_pose), (ushort)0);
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(ArmorStand), "Awake")]
private static void ArmorStand_Awake(ArmorStand __instance)
{
if (__instance.HasContainer(out ArmorStandContainer _) && !Configs.EnableArmorStandPoseChange.Value)
{
__instance.ResetPose();
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(Switch), "GetHoverText")]
private static void ArmorStand_Switch_GetHoverText(Switch __instance, ref string __result)
{
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
ArmorStand componentInParent = ((Component)__instance).GetComponentInParent<ArmorStand>();
if (Object.op_Implicit((Object)(object)componentInParent) && componentInParent.HasContainer(out ArmorStandContainer c))
{
__result = StandUI.GetHoverText(c);
if (WardAccessExt.CanAccessWard(((Component)__instance).transform.position, false) && Configs.EnableArmorStandPoseChange.Value && componentInParent.HasChestAndLegItem())
{
__result += Localization.instance.Localize("\n" + UI.PromptInteractAlt + " Change pose");
}
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(ArmorStand), "UpdateSupports")]
private static void ArmorStand_UpdateSupports(ArmorStand __instance)
{
if (!Configs.EnableArmorStandPoseChange.Value)
{
return;
}
if (__instance.m_supports.Count == 0)
{
Log.Warning((object)"m_supports is length 0 when it should be at least 1, aborting.", (ushort)0);
return;
}
ArmorStandSupport obj = __instance.m_supports[0];
int pose = __instance.m_pose;
foreach (GameObject support in obj.m_supports)
{
support.SetActive(pose == 0);
}
((Component)((Component)__instance).transform.Find("New/Lod1/ArmorStand")).gameObject.SetActive(pose < 4);
}
[HarmonyPrefix]
[HarmonyPatch(typeof(Switch), "Interact")]
private static void ArmorStand_Switch_Interact(Switch __instance, Humanoid character, bool hold, bool alt, ref bool __result, ref bool __runOriginal)
{
ArmorStand componentInParent = ((Component)__instance).GetComponentInParent<ArmorStand>();
if (Object.op_Implicit((Object)(object)componentInParent) && componentInParent.HasContainer(out ArmorStandContainer c))
{
__runOriginal = false;
if (alt && !hold && Configs.EnableArmorStandPoseChange.Value)
{
componentInParent.NextPose();
__result = true;
}
else
{
__result = StandUI.Open(c, character, hold);
}
}
}
[HarmonyPrefix]
[HarmonyPatch(typeof(ArmorStand), "UseItem")]
private static void ArmorStand_UseItem(ArmorStand __instance, ref bool __result, ref bool __runOriginal)
{
if (__instance.HasContainer(out ArmorStandContainer c) && !StandUI.CanUseHotbarItem(((Container)c).IsInUse()))
{
__runOriginal = false;
__result = false;
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(ArmorStand), "RPC_DropItemByName")]
private static void ArmorStand_RPC_DropItemByName(ArmorStand __instance)
{
if (__instance.IsOpenContainer())
{
InventoryGui.instance.Hide();
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(ArmorStand), "UpdateVisual")]
private static void ArmorStand_UpdateVisual(ArmorStand __instance)
{
__instance.UpdateContainer();
}
}
public static class Configs
{
private const string SECTION_GENERAL = "General";
public static readonly ConfigEntry<StringList> StandPrefabNames;
public static readonly ConfigEntry<bool> EnableHotbarUseItem;
private const string SECTION_ARMORSTAND = "Piece: ArmorStand";
public static readonly ConfigEntry<bool> EnableArmorStandPoseChange;
public static readonly ConfigEntry<bool> EnableArmorStandHoldToEquip;
public static readonly ConfigEntry<bool> EnableArmorStandAmericanSpelling;
private const string SECTION_ITEMSTAND = "Piece: ItemStand";
public static readonly ConfigEntry<bool> EnableItemStandHoldToEquip;
static Configs()
{
//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_0020: Expected O, but got Unknown
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Expected O, but got Unknown
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Expected O, but got Unknown
//IL_0040: Expected O, but got Unknown
StringList val = new StringList(Array.Empty<IEnumerable<string>>());
((List<string>)val).Add("itemstand");
((List<string>)val).Add("itemstandh");
((List<string>)val).Add("ArmorStand");
StandPrefabNames = Config.Define<StringList>(true, "General", "Stand Prefabs", val, "List of all the prefabs that are item stands or armor stands.\nThese prefabs must have an ItemStand or ArmorStand component attached to them.");
EnableHotbarUseItem = Config.Define<bool>(true, "General", "Enable Hotbar Use Item", false, "If enabled you can also use traditional 1-8 hotbar buttons to assign items to stands (Vanilla: true)");
EnableArmorStandPoseChange = Config.Define<bool>(true, "Piece: ArmorStand", "Enable Pose Changing", false, "Enable chaging poses of armor stands. NOTE: Stand must have chest and legs armor.");
EnableArmorStandHoldToEquip = Config.Define<bool>(true, "Piece: ArmorStand", "Enable Hold To Equip", false, "Should (Hold to equip) be available on Armor Stands hover text?");
EnableArmorStandAmericanSpelling = Config.Define<bool>(false, "Piece: ArmorStand", "American Spelling", true, "Change the spelling to 'Armor Stand' instead of 'Armour Stand'");
EnableItemStandHoldToEquip = Config.Define<bool>(true, "Piece: ItemStand", "Enable Hold To Equip", false, "Should (Hold to equip) be available on Item Stands hover text?");
}
}
public static class ItemStandExt
{
public static void UpdateContainer(this ItemStand itemStand)
{
StandContainer.UpdateContainer(((Component)itemStand).gameObject);
}
}
public static class Startup
{
public static List<StandContainer> InitPrefabs()
{
Log.Info((object)"Initializing", (ushort)0);
List<StandContainer> containers = new List<StandContainer>();
foreach (string item in (List<string>)(object)Configs.StandPrefabNames.Value)
{
if (!InitPrefab<ArmorStand>(item) && !InitPrefab<ItemStand>(item))
{
Log.Error((object)("Prefab is not ArmorStand or ItemStand: " + item), (ushort)0);
}
}
return containers;
bool InitPrefab<T>(string prefabName) where T : notnull, Component
{
GameObject prefab = ZNetScene.instance.GetPrefab(prefabName);
if (!Object.op_Implicit((Object)(object)prefab))
{
throw new Exception("Prefab not found: " + prefabName);
}
T component = prefab.GetComponent<T>();
if (!Object.op_Implicit((Object)(object)component))
{
return false;
}
if (!(component is ArmorStand))
{
if (!(component is ItemStand))
{
throw new Exception($"Unknown component type: {((object)component).GetType()}");
}
containers.Add(AddContainer<ItemStandContainer>(prefab));
}
else
{
containers.Add(AddContainer<ArmorStandContainer>(prefab));
}
return true;
}
}
public static T AddContainer<T>(GameObject targetObject) where T : StandContainer
{
T result = default(T);
if (targetObject.TryGetComponent<T>(ref result))
{
return result;
}
result = targetObject.AddComponent<T>();
((Container)result).m_checkGuardStone = true;
return result;
}
}
[HarmonyPatch(typeof(Container))]
internal static class StandContainerPatch
{
[HarmonyPrefix]
[HarmonyPatch("DropAllItems", new Type[] { })]
private static void DropAllItems(Container __instance, ref bool __runOriginal)
{
if (__instance is StandContainer)
{
__instance.GetInventory().RemoveAll();
__runOriginal = false;
}
}
[HarmonyPrefix]
[HarmonyPatch("Save")]
private static void Save(Container __instance, ref bool __runOriginal)
{
if (__instance is StandContainer standContainer)
{
Log.Info((object)$"NON-PERSISTANT: {((object)standContainer).GetType()}", (ushort)0);
__runOriginal = false;
}
}
}
public static class StandContainerExt
{
public static bool HasContainer(this ArmorStand s, out ArmorStandContainer c)
{
return ((Component)s).TryGetComponent<ArmorStandContainer>(ref c);
}
public static bool HasContainer(this ItemStand s, out ItemStandContainer c)
{
return ((Component)s).TryGetComponent<ItemStandContainer>(ref c);
}
public static bool HasContainerStand(this GameObject g, out StandContainer c)
{
return g.TryGetComponent<StandContainer>(ref c);
}
}
public static class StandUI
{
private static StandContainer? _opened;
private static float _closeTime;
public static bool IsOpen => Object.op_Implicit((Object)(object)_opened);
public static bool IsRecentlyClosed => Time.time < _closeTime + 0.5f;
public static StandContainer Opened
{
get
{
if (!IsOpen)
{
throw new Exception("Can not access container, not open");
}
return _opened;
}
}
private static bool IsOpenContainer(GameObject g)
{
if (g.HasContainerStand(out StandContainer c))
{
return c.IsOpen;
}
return false;
}
public static bool IsOpenContainer(this ItemStand s)
{
return IsOpenContainer(((Component)s).gameObject);
}
public static bool IsOpenContainer(this ArmorStand s)
{
return IsOpenContainer(((Component)s).gameObject);
}
internal static void Translations(string language)
{
if (Configs.EnableArmorStandAmericanSpelling.Value && language == "English")
{
Localization.instance.m_translations["piece_armorstand"] = "Armor Stand";
}
}
public static bool CanUseHotbarItem(bool isInUse)
{
if (Configs.EnableHotbarUseItem.Value && !isInUse)
{
return true;
}
if (isInUse)
{
((Character)Player.m_localPlayer).Message((MessageType)2, "$msg_inuse", 0, (Sprite)null);
}
return false;
}
public static bool Open(StandContainer container, Humanoid user, bool hold)
{
//IL_007c: 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_0081: Unknown result type (might be due to invalid IL or missing references)
if (IsOpen || IsRecentlyClosed)
{
InventoryGui.instance.Hide();
return false;
}
if (!ZenMod<Plugin>.IsOnServerAndAllClients)
{
((Container)container).m_nview.ClaimOwnership();
}
if (!((Container)container).Interact(user, hold, false))
{
return false;
}
_opened = container;
_opened.ShowHideStackAllButton();
Log.Info((object)$"Opened Stand: {((object)_opened).GetType()}", (ushort)0);
Game instance = Game.instance;
PlayerStatType val;
if (!(container is ArmorStandContainer))
{
if (!(container is ItemStandContainer))
{
throw new Exception($"Invalid type of stand: {((object)container).GetType()}");
}
val = (PlayerStatType)24;
}
else
{
val = (PlayerStatType)25;
}
instance.IncrementPlayerStat(val, 1f);
return true;
}
public static void OnShowUI(InventoryGui gui, StandContainer? container)
{
container?.TryFill();
InventoryGridExt.ShowAmountText(gui.ContainerGrid, false, -1);
}
public static void OnHideUI(InventoryGui gui)
{
InventoryGui gui2 = gui;
if (_opened is ArmorStandContainer armorStandContainer && Configs.EnableArmorStandPoseChange.Value && !armorStandContainer.Stand.HasChestAndLegItem())
{
armorStandContainer.Stand.ResetPose();
}
Timing.WhenNot((Func<bool>)InventoryGui.IsVisible, (Action)delegate
{
Timing.Delay(0.5f, (Action)delegate
{
InventoryGridExt.ShowAmountText(gui2.ContainerGrid, true, -1);
});
});
Close();
}
private static void Close()
{
if (IsOpen)
{
_closeTime = Time.time;
_opened = null;
}
}
public static bool CanSwap(ItemData item, out ItemData swapItem)
{
swapItem = null;
if (Object.op_Implicit((Object)(object)_opened))
{
return _opened.CanSwap(item, out swapItem);
}
return false;
}
public static void SwapEquip(bool isButtonPressed)
{
Log.Info((object)"Swap equipment", (ushort)0);
StandContainer opened = _opened;
if (!(opened is ArmorStandContainer))
{
if (opened is ItemStandContainer && (isButtonPressed || Configs.EnableItemStandHoldToEquip.Value))
{
_opened.SwapEquip();
}
}
else if (isButtonPressed || Configs.EnableArmorStandHoldToEquip.Value)
{
_opened.SwapEquip();
}
}
public static void EquipContainerStandItem(this Humanoid player, ItemData standItem)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: Expected I4, but got Unknown
ItemType itemType = standItem.m_shared.m_itemType;
ItemData val = (ItemData)((itemType - 3) switch
{
3 => player.m_helmetItem,
4 => player.m_chestItem,
8 => player.m_legItem,
14 => player.m_shoulderItem,
15 => player.m_utilityItem,
2 => player.m_leftItem ?? player.m_hiddenLeftItem,
1 => player.m_leftItem ?? player.m_hiddenLeftItem,
19 => player.m_leftItem ?? player.m_hiddenLeftItem,
0 => player.m_rightItem ?? player.m_hiddenRightItem,
11 => player.m_rightItem ?? player.m_hiddenRightItem,
16 => player.m_rightItem ?? player.m_hiddenRightItem,
17 => player.m_rightItem ?? player.m_hiddenRightItem,
12 => player.m_rightItem ?? player.m_hiddenRightItem,
_ => throw new ArgumentOutOfRangeException(),
});
Inventory inventory = player.GetInventory();
Inventory inventory2 = ((Container)Opened).GetInventory();
if (val == null)
{
inventory.MoveItemToThis(inventory2, standItem);
}
else if (Opened.CanAttach(val, ignoreExisting: true) && Opened.IsSameType(standItem, val))
{
ItemDataExt.SwapItem(inventory, val, inventory2, standItem);
}
player.EquipItem(standItem, false);
}
private static bool CanHoldToEquip(StandContainer stand)
{
if (!(stand is ArmorStandContainer))
{
if (stand is ItemStandContainer)
{
if (Configs.EnableItemStandHoldToEquip.Value)
{
return stand.IsAnyItemEquipable();
}
return false;
}
throw new Exception($"Unknown stand type: {((object)stand).GetType()}");
}
return Configs.EnableArmorStandHoldToEquip.Value;
}
public static string GetHoverText(StandContainer container)
{
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
string hoverName = ((Container)container).GetHoverName();
hoverName = ((!WardAccessExt.CanAccessWard(((Component)container).transform.position, false)) ? (hoverName + "\n$piece_noaccess") : ((!CanHoldToEquip(container)) ? (hoverName + "\n" + UI.PromptInteract + " $piece_use") : (hoverName + "\n" + UI.PromptInteract + " $piece_use (Hold to equip)")));
return Localization.instance.Localize(hoverName);
}
}
[HarmonyPatch]
internal static class StandUIPatch
{
[HarmonyPatch(typeof(InventoryGui), "OnStackAll")]
private static class InventoryGuiOnStackAll
{
private static bool _isButtonPressed;
[UsedImplicitly]
private static void Prefix()
{
_isButtonPressed = true;
}
[UsedImplicitly]
private static void Postfix()
{
_isButtonPressed = false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(Inventory), "StackAll")]
private static void Inventory_StackAll(ref bool __runOriginal)
{
if (StandUI.IsOpen)
{
StandUI.SwapEquip(_isButtonPressed);
__runOriginal = false;
}
}
}
[HarmonyPrefix]
[HarmonyPatch(typeof(InventoryGrid), "DropItem")]
private static void InventoryGrid_DropItem(InventoryGrid __instance, Inventory fromInventory, ref int amount)
{
if (StandUI.IsOpen && __instance.GetInventory() != fromInventory && __instance.GetInventory() == InventoryGui.instance.ContainerGrid.GetInventory())
{
amount = 1;
}
}
[HarmonyPrefix]
[HarmonyPatch(typeof(InventoryGui), "OnSelectedItem")]
private static void InventoryGui_OnSelectedItem(InventoryGui __instance, InventoryGrid grid, ItemData item, Modifier mod, Vector2i pos, ref bool __runOriginal)
{
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Invalid comparison between Unknown and I4
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
//IL_00e9: Invalid comparison between Unknown and I4
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
if (!StandUI.IsOpen)
{
return;
}
Player localPlayer = Player.m_localPlayer;
if (((Character)localPlayer).IsTeleporting() || ((int)mod != 2 && (int)mod != 0))
{
return;
}
if ((int)mod == 0)
{
Inventory inventory = grid.GetInventory();
Inventory dragInventory = __instance.m_dragInventory;
ItemData dragItem = __instance.m_dragItem;
if (dragItem == null || inventory == dragInventory)
{
return;
}
bool flag = false;
ItemData itemAt = inventory.GetItemAt(pos.x, pos.y);
if (inventory == ((Container)StandUI.Opened).GetInventory())
{
flag = ((itemAt == null || !StandUI.Opened.IsSameType(itemAt, dragItem)) ? StandUI.Opened.CanAttach(dragItem, ignoreExisting: false) : StandUI.Opened.CanAttach(dragItem, ignoreExisting: true));
}
if (inventory == ((Humanoid)localPlayer).GetInventory())
{
flag = itemAt == null || StandUI.Opened.CanAttach(itemAt, StandUI.Opened.IsSameType(dragItem, itemAt));
}
if (flag)
{
if (itemAt != null)
{
ItemDataExt.SwapItem(dragInventory, dragItem, inventory, itemAt);
__instance.SetupDragItem((ItemData)null, (Inventory)null, 0);
__runOriginal = false;
}
return;
}
}
if ((int)mod == 2)
{
if ((Object)(object)grid == (Object)(object)__instance.ContainerGrid || StandUI.Opened.CanAttach(item, ignoreExisting: false))
{
return;
}
if (StandUI.CanSwap(item, out ItemData swapItem))
{
ItemDataExt.SwapItem(grid.GetInventory(), item, ((Container)StandUI.Opened).GetInventory(), swapItem);
__runOriginal = false;
return;
}
}
StandUI.Opened.ShowErrorMessage();
__runOriginal = false;
}
[HarmonyPostfix]
[HarmonyPatch(typeof(InventoryGui), "Show")]
private static void InventoryGui_Show(InventoryGui __instance, Container? container)
{
if (container is StandContainer container2)
{
StandUI.OnShowUI(__instance, container2);
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(InventoryGui), "Hide")]
private static void InventoryGui_Hide(InventoryGui __instance)
{
if (StandUI.IsOpen)
{
StandUI.OnHideUI(__instance);
}
}
[HarmonyPrefix]
[HarmonyPatch(typeof(Localization), "Localize", new Type[] { typeof(string) })]
private static void Localization_Localize(ref string text)
{
if (StandUI.IsOpen || StandUI.IsRecentlyClosed)
{
text = text.Replace("$inventory_stackall", "$inventory_use");
}
}
}
public class ItemStandContainer : StandContainer
{
internal ItemStand Stand;
protected override void Awake()
{
if (!Object.op_Implicit((Object)(object)Stand) && !((Component)this).TryGetComponent<ItemStand>(ref Stand))
{
throw new Exception("ItemStand component not found on " + ((Object)this).name);
}
((Container)this).m_width = 1;
((Container)this).m_height = 1;
((Container)this).m_name = Stand.m_name;
base.Awake();
}
public override void ShowErrorMessage()
{
((Character)Player.m_localPlayer).Message((MessageType)2, "$piece_itemstand_cantattach", 0, (Sprite)null);
}
public override bool IsSameType(ItemData standItem, ItemData compareItem)
{
if (Stand.CanAttach(standItem))
{
return Stand.CanAttach(compareItem);
}
return false;
}
public override bool CanAttach(ItemData itemData, bool ignoreExisting)
{
if (!ignoreExisting)
{
if (Stand.CanAttach(itemData))
{
return ((Container)this).m_inventory.NrOfItems() == 0;
}
return false;
}
return Stand.CanAttach(itemData);
}
public override bool CanSwap(ItemData externItem, out ItemData swapItem)
{
ItemData val = (swapItem = GetContainerItem());
if (val != null && IsSameType(val, externItem))
{
return true;
}
return false;
}
public override void SwapEquip()
{
ItemData containerItem = GetContainerItem();
if (containerItem != null)
{
if (!containerItem.IsEquipable())
{
Log.Info((object)"Item stand item is not equipable, aborting swap.", (ushort)0);
}
else
{
((Humanoid)(object)Player.m_localPlayer).EquipContainerStandItem(containerItem);
}
}
}
private ItemData? GetContainerItem()
{
if (((Container)this).m_inventory.NrOfItems() <= 0)
{
return null;
}
return ((Container)this).m_inventory.GetItem(0);
}
private bool AttachItem(ItemData item)
{
if (!Stand.CanAttach(item))
{
return false;
}
if (((Container)this).m_nview.IsOwner())
{
Log.Info((object)("Attaching item: " + ItemDataExt.GetPrefabName(item)), (ushort)0);
ZDO zDO = ((Container)this).m_nview.GetZDO();
zDO.Set(ZDOVars.s_item, ItemDataExt.GetPrefabName(item));
ItemDrop.SaveToZDO(item, zDO);
}
return true;
}
private ItemData? GetAttachedItemData()
{
string attachedItem = Stand.GetAttachedItem();
return GetItemData(attachedItem);
}
protected override bool IsStandInventoryDiff()
{
if (((Container)this).m_inventory.NrOfItems() == 0)
{
return Stand.HaveAttachment();
}
if (!Stand.HaveAttachment())
{
return true;
}
ItemData attachedItemData = GetAttachedItemData();
int num;
if (attachedItemData == null)
{
num = 0;
}
else
{
num = ((!ItemDataExt.IsEqual(attachedItemData, ((Container)this).m_inventory.GetItem(0))) ? 1 : 0);
if (num != 0)
{
goto IL_0072;
}
}
Log.Debug((object)("Container and stand are identical: " + (((attachedItemData != null) ? ItemDataExt.GetName(attachedItemData) : null) ?? "No Item")), (ushort)0);
goto IL_0072;
IL_0072:
return (byte)num != 0;
}
protected override bool FillContainer()
{
Log.Info((object)"Fill inventory from item stand", (ushort)0);
((Container)this).m_inventory.RemoveAll();
ItemData attachedItemData = GetAttachedItemData();
if (attachedItemData == null)
{
return false;
}
((Container)this).m_inventory.AddItem(attachedItemData);
Log.Info((object)("Added item to container from ItemStand: " + ItemDataExt.GetName(attachedItemData)), (ushort)0);
return true;
}
protected override void UpdateVisualFromContainer()
{
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
if (IsStandInventoryDiff())
{
Log.Info((object)"Updating visuals data", (ushort)0);
ClearItemStand();
ItemData containerItem = GetContainerItem();
if (containerItem == null || AttachItem(containerItem))
{
UpdateVisualEveryone();
Transform transform = ((Component)this).transform;
Stand.m_effects.Create(transform.position, transform.rotation, (Transform)null, 1f, -1);
Log.Info((object)("ItemStand updated visual from container: " + ((containerItem != null) ? ItemDataExt.GetPrefabName(containerItem) : null)), (ushort)0);
}
}
void ClearItemStand()
{
Stand.SetVisualItem(string.Empty, 0, 0);
if (((Container)this).m_nview.IsOwner())
{
((Container)this).m_nview.GetZDO().Set(ZDOVars.s_item, string.Empty);
}
}
}
private void UpdateVisualEveryone()
{
ZDO zDO = ((Container)this).m_nview.GetZDO();
string @string = zDO.GetString(ZDOVars.s_item, "");
int @int = zDO.GetInt(ZDOVars.s_variant, 0);
int int2 = zDO.GetInt(ZDOVars.s_quality, 0);
((Container)this).m_nview.InvokeRPC(ZNetView.Everybody, "SetVisualItem", new object[3]
{
string.Empty,
0,
0
});
((Container)this).m_nview.InvokeRPC(ZNetView.Everybody, "SetVisualItem", new object[3] { @string, @int, int2 });
}
}
[HarmonyPatch]
public static class ItemStandPatch
{
[HarmonyPostfix]
[HarmonyPatch(typeof(ItemStand), "GetHoverText")]
private static void ItemStand_GetHoverText(ItemStand __instance, ref string __result)
{
if (__instance.HasContainer(out ItemStandContainer c))
{
__result = StandUI.GetHoverText(c);
}
}
[HarmonyPrefix]
[HarmonyPatch(typeof(ItemStand), "UseItem")]
private static void ItemStand_UseItem(ItemStand __instance, ref bool __runOriginal, ref bool __result)
{
if (__instance.HasContainer(out ItemStandContainer c) && !StandUI.CanUseHotbarItem(((Container)c).IsInUse()))
{
__runOriginal = false;
__result = false;
}
}
[HarmonyPrefix]
[HarmonyPatch(typeof(ItemStand), "Interact")]
private static void ItemStand_Interact(ItemStand __instance, Humanoid user, bool hold, ref bool __result, ref bool __runOriginal)
{
if (__instance.HasContainer(out ItemStandContainer c))
{
__result = StandUI.Open(c, user, hold);
__runOriginal = false;
}
}
[HarmonyPrefix]
[HarmonyPatch(typeof(ItemStand), "SetVisualItem")]
private static void ItemStand_SetVisualItem(ItemStand __instance, string itemName, int variant)
{
if (__instance.m_visualName != itemName || __instance.m_visualVariant != variant)
{
Object.Destroy((Object)(object)__instance.m_visualItem);
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(ItemStand), "RPC_DropItem")]
private static void ItemStand_RPC_DropItem(ItemStand __instance)
{
if (__instance.IsOpenContainer())
{
InventoryGui.instance.Hide();
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(ItemStand), "UpdateVisual")]
private static void ItemStand_UpdateVisual(ItemStand __instance)
{
__instance.UpdateContainer();
}
}
[Disable(new Type[] { typeof(StandContainer) })]
[BepInPlugin("ZenDragon.ZenItemStands", "ZenItemStands", "0.5.2")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[SynchronizationMode(/*Could not decode attribute arguments.*/)]
[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
internal class Plugin : ZenMod<Plugin>
{
public const string PluginName = "ZenItemStands";
public const string PluginVersion = "0.5.2";
public const string PluginGUID = "ZenDragon.ZenItemStands";
protected override void Setup()
{
((ZenMod)this).LanguageChanged += StandUI.Translations;
ZenMod<Plugin>.Hotload.PrefabInit += Startup.InitPrefabs;
}
protected override void TitleScene(bool isFirstBoot)
{
}
protected override void WorldStart()
{
}
protected override void Shutdown()
{
}
protected override void HotRestore()
{
GameObject[] array = Object.FindObjectsByType<GameObject>((FindObjectsSortMode)0);
foreach (GameObject val in array)
{
switch (((Object)val).name)
{
case "ArmorStand(Clone)":
Startup.AddContainer<ArmorStandContainer>(val);
break;
case "itemstand(Clone)":
case "itemstandh(Clone)":
Startup.AddContainer<ItemStandContainer>(val);
break;
}
}
}
}
public abstract class StandContainer : Container
{
public bool IsOpen
{
get
{
if (StandUI.IsOpen)
{
return (Object)(object)StandUI.Opened == (Object)(object)this;
}
return false;
}
}
public abstract void ShowErrorMessage();
public abstract bool IsSameType(ItemData standItem, ItemData compareItem);
public abstract bool CanAttach(ItemData itemData, bool ignoreExisting);
public abstract bool CanSwap(ItemData externItem, out ItemData swapItem);
public abstract void SwapEquip();
protected abstract void UpdateVisualFromContainer();
protected abstract bool FillContainer();
protected abstract bool IsStandInventoryDiff();
internal static void UpdateContainer(GameObject g)
{
if (g.HasContainerStand(out StandContainer c) && !c.IsOpen)
{
Log.Debug((object)$"Updating container: {((object)c).GetType()}", (ushort)0);
c.TryFill();
}
}
protected virtual void Awake()
{
((Container)this).Awake();
if (ZNetView.m_forceDisableInit)
{
Object.Destroy((Object)(object)this);
return;
}
Inventory inventory = ((Container)this).GetInventory();
inventory.m_onChanged = (Action)Delegate.Combine(inventory.m_onChanged, new Action(OnInventoryChanged));
ZenMod<Plugin>.Hotload.Track((Object)(object)this);
}
private void OnInventoryChanged()
{
if (IsOpen)
{
UpdateVisualFromContainer();
ShowHideStackAllButton();
}
}
private void OnDestroy()
{
base.m_nview.Unregister("RequestOpen");
base.m_nview.Unregister("OpenRespons");
base.m_nview.Unregister("RPC_RequestStack");
base.m_nview.Unregister("RPC_StackResponse");
base.m_nview.Unregister("RequestTakeAll");
base.m_nview.Unregister("TakeAllRespons");
ZenMod<Plugin>.Hotload.Untrack((Object)(object)this);
}
public bool TryFill()
{
bool loading = base.m_loading;
base.m_loading = true;
bool result = IsStandInventoryDiff() && FillContainer();
base.m_loading = loading;
return result;
}
private bool CanFill()
{
if (((Container)this).IsOwner() || base.m_loading)
{
return true;
}
Log.Error((object)"Not Container owner && m_loading is false", (ushort)0);
return false;
}
protected ItemData? GetItemData(string itemName, int index = -1)
{
//IL_001a: Expected O, but got Unknown
try
{
return ZdoExt.GetItemData(base.m_nview.GetZDO(), itemName, index);
}
catch (MissingItemException val)
{
Log.Warning((object)((Exception)val).Message, (ushort)0);
return null;
}
}
public bool IsAnyItemEquipable()
{
return ((Container)this).GetInventory().GetAllItems().Any((ItemData item) => item.IsEquipable());
}
public virtual void ShowHideStackAllButton()
{
InventoryGuiExt.ShowStackAllButton(InventoryGui.instance, IsAnyItemEquipable());
}
}
}