From 2ff3fba9bcff7797dbf866006b9c02a496eba35a Mon Sep 17 00:00:00 2001 From: Tyfon <29051038+tyfon7@users.noreply.github.com> Date: Fri, 20 Sep 2024 11:45:29 -0700 Subject: [PATCH] Initial interop --- Multiselect/MultiSelectController.cs | 31 ++++++++ Multiselect/MultiSelectInterop.cs | 115 +++++++++++++++++++++++++++ UIFixes.csproj | 2 +- server/package.json | 2 +- 4 files changed, 148 insertions(+), 2 deletions(-) create mode 100644 Multiselect/MultiSelectController.cs create mode 100644 Multiselect/MultiSelectInterop.cs diff --git a/Multiselect/MultiSelectController.cs b/Multiselect/MultiSelectController.cs new file mode 100644 index 0000000..c1b05fc --- /dev/null +++ b/Multiselect/MultiSelectController.cs @@ -0,0 +1,31 @@ +using EFT.InventoryLogic; +using EFT.UI; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace UIFixes; + +// This class exists to create a layer between MultiSelectInterop and the MultiSelect implementation. +public static class MultiSelectController +{ + public static int GetCount() + { + return MultiSelect.Count; + } + + public static IEnumerable GetItems() + { + return MultiSelect.SortedItemContexts().Select(ic => ic.Item); + } + + public static Task Apply(Func func, ItemUiContext itemUiContext = null) + { + itemUiContext ??= ItemUiContext.Instance; + var taskSerializer = itemUiContext.gameObject.AddComponent(); + return taskSerializer.Initialize(GetItems(), func); + } +} + +public class ItemTaskSerializer : TaskSerializer { } diff --git a/Multiselect/MultiSelectInterop.cs b/Multiselect/MultiSelectInterop.cs new file mode 100644 index 0000000..c374ce1 --- /dev/null +++ b/Multiselect/MultiSelectInterop.cs @@ -0,0 +1,115 @@ +using BepInEx; +using BepInEx.Bootstrap; +using EFT.InventoryLogic; +using EFT.UI; +using HarmonyLib; +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Threading.Tasks; + +namespace UIFixesInterop; + +/// +/// Provides access to UI Fixes' multiselect functionality. +/// +internal class MultiSelect +{ + private static readonly Version RequiredVersion = new(2, 5); + + private static bool? UIFixesLoaded; + + private static Type MultiSelectType; + private static MethodInfo GetCountMethod; + private static MethodInfo GetItemsMethod; + private static MethodInfo ApplyMethod; + + /// Count represents the number of items in the current selection, 0 if UI Fixes is not present. + public int Count + { + get + { + if (!Loaded()) + { + return 0; + } + + return (int)GetCountMethod.Invoke(null, []); + } + } + + /// Items is an enumerable list of items in the current selection, empty if UI Fixes is not present + public IEnumerable Items + { + get + { + if (!Loaded()) + { + return []; + } + + return (IEnumerable)GetItemsMethod.Invoke(null, []); + } + } + + /// + /// This method takes an Action and calls it *sequentially* on each item in the current selection. + /// Will no-op if UI Fixes is not present. + /// + /// The action to call on each item. + /// Optional ItemUiContext; will use ItemUiContext.Instance if not provided. + public void Apply(Action action, ItemUiContext itemUiContext = null) + { + if (!Loaded()) + { + return; + } + + Func func = item => + { + action(item); + return Task.CompletedTask; + }; + + ApplyMethod.Invoke(null, [func, itemUiContext]); + } + + /// + /// This method takes an Func that returns a Task and calls it *sequentially* on each item in the current selection. + /// Will return a completed task immediately if UI Fixes is not present. + /// + /// The function to call on each item + /// Optional ItemUiContext; will use ItemUiContext.Instance if not provided. + /// A Task that will complete when all the function calls are complete. + public Task Apply(Func func, ItemUiContext itemUiContext = null) + { + if (!Loaded()) + { + return Task.CompletedTask; + } + + return (Task)ApplyMethod.Invoke(null, [func, itemUiContext]); + } + + private bool Loaded() + { + if (!UIFixesLoaded.HasValue) + { + bool present = Chainloader.PluginInfos.TryGetValue("Tyfon.UIFixes", out PluginInfo pluginInfo); + UIFixesLoaded = present && pluginInfo.Metadata.Version >= RequiredVersion; + + if (UIFixesLoaded.Value) + { + MultiSelectType = Type.GetType("UIFixes.MultiSelectController, UIFixes"); + if (MultiSelectType != null) + { + GetCountMethod = AccessTools.Method(MultiSelectType, "GetCount"); + GetItemsMethod = AccessTools.Method(MultiSelectType, "GetItems"); + ApplyMethod = AccessTools.Method(MultiSelectType, "Apply"); + } + } + } + + return UIFixesLoaded.Value; + } +} \ No newline at end of file diff --git a/UIFixes.csproj b/UIFixes.csproj index e36208e..e0fa01e 100644 --- a/UIFixes.csproj +++ b/UIFixes.csproj @@ -4,7 +4,7 @@ net471 Tyfon.UIFixes SPT UI Fixes - 2.4.5 + 2.5.0 true latest Debug;Release diff --git a/server/package.json b/server/package.json index 24f0f1e..a51f217 100644 --- a/server/package.json +++ b/server/package.json @@ -1,6 +1,6 @@ { "name": "uifixes", - "version": "2.4.5", + "version": "2.5.0", "main": "src/mod.js", "license": "MIT", "author": "Tyfon",