using EFT.InventoryLogic; using EFT.UI; using JetBrains.Annotations; using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Reflection; using UnityEngine; using DynamicInteraction = GClass2654; using EmptyInteractions = GClass2655; namespace IcyClawz.CustomInteractions { [EditorBrowsable(EditorBrowsableState.Never)] public interface ICustomInteractionsProvider { } // Do not implement this directly public interface IItemCustomInteractionsProvider : ICustomInteractionsProvider { IEnumerable GetCustomInteractions(ItemUiContext uiContext, EItemViewType viewType, Item item); } public static class CustomInteractionsManager { internal static readonly List Providers = new List(); public static void Register(ICustomInteractionsProvider provider) { if (!Providers.Contains(provider)) { Providers.Add(provider); } } } public class CustomInteraction { internal readonly CustomInteractionImpl Impl; public CustomInteraction() { Impl = new CustomInteractionImpl(); } public Func Caption { get => Impl.Caption; set => Impl.Caption = value; } public Func Icon { get => Impl.Icon; set => Impl.Icon = value; } public Action Action { get => Impl.Action; set => Impl.Action = value; } public Func SubMenu { get => Impl.SubMenu; set => Impl.SubMenu = value; } public Func Enabled { get => Impl.Enabled; set => Impl.Enabled = value; } public Func Error { get => Impl.Error; set => Impl.Error = value; } } internal sealed class CustomInteractionImpl : DynamicInteraction { public CustomInteractionImpl() : base(UnityEngine.Random.Range(0, int.MaxValue).ToString("x4")) { } public Func Caption { get; set; } public new Func Icon { get; set; } public Action Action { get => action_0; set => action_0 = value; } public Func SubMenu { get; set; } public Func Enabled { get; set; } public Func Error { get; set; } public bool IsInteractive() => Enabled?.Invoke() ?? true; } public abstract class CustomSubInteractions { internal readonly CustomSubInteractionsImpl Impl; public CustomSubInteractions(ItemUiContext uiContext) { Impl = new CustomSubInteractionsImpl(uiContext); } public bool ExaminationRequired { get => Impl._ExaminationRequired; set => Impl._ExaminationRequired = value; } public void Add(CustomInteraction customInteraction) => Impl.AddCustomInteraction(customInteraction); public void Remove(CustomInteraction customInteraction) => Impl.RemoveCustomInteraction(customInteraction); public void CallRedraw() => Impl.CallRedraw(); public void CallRedraw(string templateId) => Impl.CallRedraw(templateId); } internal sealed class CustomSubInteractionsImpl : EmptyInteractions { public CustomSubInteractionsImpl(ItemUiContext uiContext) : base(uiContext) { } public IEnumerable CustomInteractions => DynamicInteractions.OfType(); public bool _ExaminationRequired { get; set; } = true; public override bool ExaminationRequired => _ExaminationRequired; public override bool HasIcons => CustomInteractions.Any(customInteraction => customInteraction.Icon != null); public void CallRedraw() => itemUiContext_0.RedrawContextMenus(null); } internal static class AbstractInteractionsExtensions { private static Dictionary GetDynamicInteractions(this GClass2655 instance) where T : Enum => typeof(GClass2655).GetField("dictionary_1", BindingFlags.NonPublic | BindingFlags.Instance) .GetValue(instance) as Dictionary; public static void AddCustomInteraction(this GClass2655 instance, CustomInteraction customInteraction) where T : Enum => instance.GetDynamicInteractions()[customInteraction.Impl.Key] = customInteraction.Impl; public static void RemoveCustomInteraction(this GClass2655 instance, CustomInteraction customInteraction) where T : Enum => instance.GetDynamicInteractions().Remove(customInteraction.Impl.Key); } internal static class InteractionButtonsContainerExtensions { private static readonly FieldInfo ButtonsContainerField = typeof(InteractionButtonsContainer).GetField("_buttonsContainer", BindingFlags.NonPublic | BindingFlags.Instance); private static RectTransform GetButtonsContainer(this InteractionButtonsContainer instance) => ButtonsContainerField.GetValue(instance) as RectTransform; private static readonly FieldInfo ButtonTemplateField = typeof(InteractionButtonsContainer).GetField("_buttonTemplate", BindingFlags.NonPublic | BindingFlags.Instance); private static SimpleContextMenuButton GetButtonTemplate(this InteractionButtonsContainer instance) => ButtonTemplateField.GetValue(instance) as SimpleContextMenuButton; private static readonly FieldInfo CurrentButtonField = typeof(InteractionButtonsContainer).GetField("simpleContextMenuButton_0", BindingFlags.NonPublic | BindingFlags.Instance); private static void SetCurrentButton(this InteractionButtonsContainer instance, SimpleContextMenuButton button) => CurrentButtonField.SetValue(instance, button); private static readonly MethodInfo CreateButtonMethod = typeof(InteractionButtonsContainer).GetMethod("method_1", BindingFlags.NonPublic | BindingFlags.Instance); private static SimpleContextMenuButton CreateButton(this InteractionButtonsContainer instance, string key, string caption, SimpleContextMenuButton template, RectTransform container, [CanBeNull] Sprite sprite, [CanBeNull] Action onButtonClicked, [CanBeNull] Action onMouseHover, bool subMenu = false, bool autoClose = true) => (SimpleContextMenuButton)CreateButtonMethod.Invoke(instance, new object[] { key, caption, template, container, sprite, onButtonClicked, onMouseHover, subMenu, autoClose }); private static readonly MethodInfo CloseSubMenuMethod = typeof(InteractionButtonsContainer).GetMethod("method_4", BindingFlags.NonPublic | BindingFlags.Instance); private static void CloseSubMenu(this InteractionButtonsContainer instance) => CloseSubMenuMethod.Invoke(instance, null); private static readonly MethodInfo AddButtonMethod = typeof(InteractionButtonsContainer).GetMethod("method_5", BindingFlags.NonPublic | BindingFlags.Instance); private static void AddButton(this InteractionButtonsContainer instance, SimpleContextMenuButton button) => AddButtonMethod.Invoke(instance, new object[] { button }); public static void AddCustomButton(this InteractionButtonsContainer instance, CustomInteractionImpl customInteractionImpl) { bool isInteractive = customInteractionImpl.IsInteractive(); SimpleContextMenuButton button = null; button = instance.CreateButton( customInteractionImpl.Key, customInteractionImpl.Caption?.Invoke() ?? string.Empty, instance.GetButtonTemplate(), instance.GetButtonsContainer(), customInteractionImpl.Icon?.Invoke(), () => { if (isInteractive) { customInteractionImpl.Execute(); } }, () => { instance.SetCurrentButton(button); instance.CloseSubMenu(); if (isInteractive) { var subMenu = customInteractionImpl.SubMenu?.Invoke(); if (subMenu != null) { instance.SetSubInteractions(subMenu.Impl); } } }, customInteractionImpl.SubMenu != null, false ); button.SetButtonInteraction( (isInteractive, customInteractionImpl.Error?.Invoke() ?? string.Empty) ); instance.AddButton(button); } } }