From f7caaaadaf9a6a8fdb951d4c014bccb73ab4e03d Mon Sep 17 00:00:00 2001 From: kmyuhkyuk <2451614940@qq.com> Date: Mon, 8 Apr 2024 10:45:58 +0800 Subject: [PATCH] Depend on EFTApi and refactor code --- SkinHide.sln => HideDress.sln | 2 +- .../HideDress.csproj | 19 +- HideDress/HideDress.csproj.DotSettings | 2 + HideDress/HideDressPlugin.cs | 107 +++++ HideDress/Models/HideDressModel.cs | 25 + HideDress/Models/ReflectionModel.cs | 38 ++ HideDress/Models/SettingsModel.cs | 50 ++ HideDress/Patches/PlayerModelViewShow.cs | 16 + .../Properties/AssemblyInfo.cs | 7 +- SkinHide/Patches/PlayerModelViewPatch.cs | 24 - SkinHide/Patches/PlayerPatch.cs | 75 --- SkinHide/SkinHidePlugin.cs | 206 --------- SkinHide/Utils/RefHelp.cs | 431 ------------------ 13 files changed, 255 insertions(+), 747 deletions(-) rename SkinHide.sln => HideDress.sln (87%) rename SkinHide/SkinHide.csproj => HideDress/HideDress.csproj (88%) create mode 100644 HideDress/HideDress.csproj.DotSettings create mode 100644 HideDress/HideDressPlugin.cs create mode 100644 HideDress/Models/HideDressModel.cs create mode 100644 HideDress/Models/ReflectionModel.cs create mode 100644 HideDress/Models/SettingsModel.cs create mode 100644 HideDress/Patches/PlayerModelViewShow.cs rename {SkinHide => HideDress}/Properties/AssemblyInfo.cs (87%) delete mode 100644 SkinHide/Patches/PlayerModelViewPatch.cs delete mode 100644 SkinHide/Patches/PlayerPatch.cs delete mode 100644 SkinHide/SkinHidePlugin.cs delete mode 100644 SkinHide/Utils/RefHelp.cs diff --git a/SkinHide.sln b/HideDress.sln similarity index 87% rename from SkinHide.sln rename to HideDress.sln index af85be7..5d836d5 100644 --- a/SkinHide.sln +++ b/HideDress.sln @@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.1.32407.343 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SkinHide", "SkinHide\SkinHide.csproj", "{E5DD6484-115E-4104-AADF-E5610EE4F397}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HideDress", "HideDress\HideDress.csproj", "{E5DD6484-115E-4104-AADF-E5610EE4F397}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/SkinHide/SkinHide.csproj b/HideDress/HideDress.csproj similarity index 88% rename from SkinHide/SkinHide.csproj rename to HideDress/HideDress.csproj index 0796b49..7ce00be 100644 --- a/SkinHide/SkinHide.csproj +++ b/HideDress/HideDress.csproj @@ -7,8 +7,8 @@ {E5DD6484-115E-4104-AADF-E5610EE4F397} Library Properties - SkinHide - SkinHide + HideDress + HideDress v4.7.2 512 true @@ -55,6 +55,12 @@ False R:\Battlestate Games\Client.0.12.12.15.17349\EscapeFromTarkov_Data\Managed\Comfort.dll + + ..\..\EFTApi\Build\bin\Current\EFTApi.dll + + + ..\..\EFTApi\Build\bin\Current\EFTReflection.dll + @@ -78,11 +84,12 @@ - - - + + + + + - diff --git a/HideDress/HideDress.csproj.DotSettings b/HideDress/HideDress.csproj.DotSettings new file mode 100644 index 0000000..3c607d0 --- /dev/null +++ b/HideDress/HideDress.csproj.DotSettings @@ -0,0 +1,2 @@ + + True \ No newline at end of file diff --git a/HideDress/HideDressPlugin.cs b/HideDress/HideDressPlugin.cs new file mode 100644 index 0000000..112fac7 --- /dev/null +++ b/HideDress/HideDressPlugin.cs @@ -0,0 +1,107 @@ +using System.Collections.Generic; +using System.Linq; +using BepInEx; +using EFT; +using EFT.Visual; +using HideDress.Models; +using static EFTApi.EFTHelpers; + +namespace HideDress +{ + [BepInPlugin("com.kmyuhkyuk.HideDress", "kmyuhkyuk-HideDress", "1.2.7")] + [BepInDependency("com.kmyuhkyuk.EFTApi", "1.2.0")] + public partial class HideDressPlugin : BaseUnityPlugin + { + private void Awake() + { + SettingsModel.Create(Config); + } + + private void Start() + { + ReflectionModel.Instance.PlayerModelViewShow.Add(this, nameof(PlayerModelViewShow)); + } + + private void Update() + { + var player = _PlayerHelper.Player; + var world = _GameWorldHelper.GameWorld; + var settingsModel = SettingsModel.Instance; + var hideDressModel = HideDressModel.Instance; + + if (settingsModel.KeyPlayerHideDressShortcut.Value.IsDown()) + { + settingsModel.KeyPlayerHideDress.Value = !settingsModel.KeyPlayerHideDress.Value; + } + + if (settingsModel.KeyOtherPlayerHideDressShortcut.Value.IsDown()) + { + settingsModel.KeyOtherPlayerHideDress.Value = !settingsModel.KeyOtherPlayerHideDress.Value; + } + + if (hideDressModel.PlayerModelViewBody != null) + { + EnabledPartDress(hideDressModel.PlayerModelViewBody, settingsModel.KeyPlayerHideDressPart.Value, !settingsModel.KeyPlayerHideDress.Value); + } + + if (player != null) + { + EnabledPartDress(player.PlayerBody, settingsModel.KeyPlayerHideDressPart.Value, !settingsModel.KeyPlayerHideDress.Value); + } + + if (world != null) + { + foreach (var otherPlayer in _GameWorldHelper.AllOtherPlayer) + { + EnabledPartDress(otherPlayer.PlayerBody, settingsModel.KeyOtherPlayerHideDressPart.Value, !settingsModel.KeyOtherPlayerHideDress.Value); + } + } + } + + private static void EnabledPartDress(PlayerBody playerBody, HideDressModel.DressPart part, bool enabled) + { + var reflectionModel = ReflectionModel.Instance; + + var slotViews = reflectionModel.RefSlotViews.GetValue(playerBody); + + var slotList = reflectionModel.RefSlotList.GetValue(slotViews); + + var dressList = new List(); + + foreach (var slot in slotList) + { + var dresses = reflectionModel.RefDresses.GetValue(slot); + + if (dresses == null) + continue; + + foreach (var dress in dresses) + { + dressList.Add(dress); + } + } + + EnabledDress(dressList.Where(x => x.GetType() == typeof(Dress)), part == HideDressModel.DressPart.SkinDress || enabled); + EnabledSkinDress(dressList.Where(x => x is SkinDress || x is ArmBandView), part == HideDressModel.DressPart.Dress || enabled); + } + + private static void EnabledDress(IEnumerable dressEnumerable, bool enabled) + { + foreach (var dress in dressEnumerable) + { + foreach (var renderer in ReflectionModel.Instance.RefRenderers.GetValue(dress)) + { + renderer.enabled = enabled; + } + } + } + + private static void EnabledSkinDress(IEnumerable skinDressEnumerable, bool enabled) + { + foreach (var skinDress in skinDressEnumerable) + { + skinDress.gameObject.SetActive(enabled); + } + } + } +} \ No newline at end of file diff --git a/HideDress/Models/HideDressModel.cs b/HideDress/Models/HideDressModel.cs new file mode 100644 index 0000000..13382e0 --- /dev/null +++ b/HideDress/Models/HideDressModel.cs @@ -0,0 +1,25 @@ +using System; +using EFT; + +namespace HideDress.Models +{ + internal class HideDressModel + { + private static readonly Lazy Lazy = new Lazy(() => new HideDressModel()); + + public static HideDressModel Instance => Lazy.Value; + + public PlayerBody PlayerModelViewBody; + + public enum DressPart + { + Both, + Dress, + SkinDress + } + + private HideDressModel() + { + } + } +} \ No newline at end of file diff --git a/HideDress/Models/ReflectionModel.cs b/HideDress/Models/ReflectionModel.cs new file mode 100644 index 0000000..8b12235 --- /dev/null +++ b/HideDress/Models/ReflectionModel.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using EFT; +using EFT.UI; +using EFT.Visual; +using EFTReflection; +using UnityEngine; + +namespace HideDress.Models +{ + internal class ReflectionModel + { + private static readonly Lazy Lazy = new Lazy(() => new ReflectionModel()); + + public static ReflectionModel Instance => Lazy.Value; + + public readonly RefHelper.FieldRef RefSlotViews; + + public readonly RefHelper.FieldRef> RefSlotList; + + public readonly RefHelper.FieldRef RefDresses; + + public readonly RefHelper.FieldRef RefRenderers; + + public readonly RefHelper.HookRef PlayerModelViewShow; + + private ReflectionModel() + { + RefSlotViews = RefHelper.FieldRef.Create("SlotViews"); + RefSlotList = RefHelper.FieldRef>.Create(RefSlotViews.FieldType, "list_0"); + RefDresses = + RefHelper.FieldRef.Create(RefSlotList.FieldType.GetGenericArguments()[0], "Dresses"); + RefRenderers = RefHelper.FieldRef.Create("Renderers"); + + PlayerModelViewShow = RefHelper.HookRef.Create(typeof(PlayerModelView), x => x.Name == "Show" && x.GetParameters()[0].ParameterType == typeof(PlayerVisualRepresentation)); + } + } +} \ No newline at end of file diff --git a/HideDress/Models/SettingsModel.cs b/HideDress/Models/SettingsModel.cs new file mode 100644 index 0000000..7b8f2c7 --- /dev/null +++ b/HideDress/Models/SettingsModel.cs @@ -0,0 +1,50 @@ +using System.Diagnostics.CodeAnalysis; +using BepInEx.Configuration; + +namespace HideDress.Models +{ + internal class SettingsModel + { + public static SettingsModel Instance { get; private set; } + + public readonly ConfigEntry KeyPlayerHideDress; + public readonly ConfigEntry KeyOtherPlayerHideDress; + + public readonly ConfigEntry KeyPlayerHideDressPart; + public readonly ConfigEntry KeyOtherPlayerHideDressPart; + + public readonly ConfigEntry KeyPlayerHideDressShortcut; + public readonly ConfigEntry KeyOtherPlayerHideDressShortcut; + + [SuppressMessage("ReSharper", "RedundantTypeArgumentsOfMethod")] + private SettingsModel(ConfigFile configFile) + { + const string hideDressSettings = "Hide Dress Settings"; + const string hideDressPartSettings = "Hide Dress Part Settings"; + const string shortcutSettings = "Keyboard Shortcut Settings"; + + KeyPlayerHideDress = configFile.Bind(hideDressSettings, "Hide Player Dress", false); + KeyOtherPlayerHideDress = configFile.Bind(hideDressSettings, "Hide Other Player Dress", false); + + KeyPlayerHideDressPart = + configFile.Bind(hideDressPartSettings, "Player", HideDressModel.DressPart.Both); + KeyOtherPlayerHideDressPart = + configFile.Bind(hideDressPartSettings, "Other Player", HideDressModel.DressPart.Both); + + KeyPlayerHideDressShortcut = + configFile.Bind(shortcutSettings, "Hide Player Dress", + KeyboardShortcut.Empty); + KeyOtherPlayerHideDressShortcut = + configFile.Bind(shortcutSettings, "Hide Other Player Dress", KeyboardShortcut.Empty); + } + + // ReSharper disable once UnusedMethodReturnValue.Global + public static SettingsModel Create(ConfigFile configFile) + { + if (Instance != null) + return Instance; + + return Instance = new SettingsModel(configFile); + } + } +} \ No newline at end of file diff --git a/HideDress/Patches/PlayerModelViewShow.cs b/HideDress/Patches/PlayerModelViewShow.cs new file mode 100644 index 0000000..ef51468 --- /dev/null +++ b/HideDress/Patches/PlayerModelViewShow.cs @@ -0,0 +1,16 @@ +using System.Threading.Tasks; +using EFT.UI; +using HideDress.Models; + +namespace HideDress +{ + public partial class HideDressPlugin + { + private static async void PlayerModelViewShow(Task __result, PlayerModelView __instance) + { + await __result; + + HideDressModel.Instance.PlayerModelViewBody = __instance.PlayerBody; + } + } +} \ No newline at end of file diff --git a/SkinHide/Properties/AssemblyInfo.cs b/HideDress/Properties/AssemblyInfo.cs similarity index 87% rename from SkinHide/Properties/AssemblyInfo.cs rename to HideDress/Properties/AssemblyInfo.cs index 4527eda..9a525d7 100644 --- a/SkinHide/Properties/AssemblyInfo.cs +++ b/HideDress/Properties/AssemblyInfo.cs @@ -1,15 +1,14 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // 有关程序集的一般信息由以下 // 控制。更改这些特性值可修改 // 与程序集关联的信息。 -[assembly: AssemblyTitle("kmyuhkyuk-SkinHide")] +[assembly: AssemblyTitle("kmyuhkyuk-HideDress")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("https://hub.sp-tarkov.com/files/file/583-skin-hide")] -[assembly: AssemblyProduct("SkinHide")] +[assembly: AssemblyProduct("HideDress")] [assembly: AssemblyCopyright("Copyright © 2022")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -33,4 +32,4 @@ using System.Runtime.InteropServices; //通过使用 "*",如下所示: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.2.7.0")] -[assembly: AssemblyFileVersion("1.2.7.0")] +[assembly: AssemblyFileVersion("1.2.7.0")] \ No newline at end of file diff --git a/SkinHide/Patches/PlayerModelViewPatch.cs b/SkinHide/Patches/PlayerModelViewPatch.cs deleted file mode 100644 index 90f6a02..0000000 --- a/SkinHide/Patches/PlayerModelViewPatch.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Aki.Reflection.Patching; -using Aki.Reflection.Utils; -using System.Reflection; -using System.Threading.Tasks; -using EFT.UI; - -namespace SkinHide.Patches -{ - public class PlayerModelViewPatch : ModulePatch - { - protected override MethodBase GetTargetMethod() - { - return typeof(PlayerModelView).GetMethod("method_0", PatchConstants.PrivateFlags); - } - - [PatchPostfix] - private static async void PatchPostfix(Task __result, PlayerModelView __instance) - { - await __result; - - SkinHidePlugin.PlayerModelView = __instance.PlayerBody; - } - } -} diff --git a/SkinHide/Patches/PlayerPatch.cs b/SkinHide/Patches/PlayerPatch.cs deleted file mode 100644 index bdbd2bf..0000000 --- a/SkinHide/Patches/PlayerPatch.cs +++ /dev/null @@ -1,75 +0,0 @@ -using Aki.Reflection.Patching; -using Aki.Reflection.Utils; -using System; -using System.Reflection; -using System.Threading.Tasks; -using EFT; - -namespace SkinHide.Patches -{ - public class PlayerInitPatch : ModulePatch - { - private static readonly bool Is231Up = SkinHidePlugin.GameVersion > new Version("0.12.12.17349"); - - protected override MethodBase GetTargetMethod() - { - return typeof(Player).GetMethod("Init", PatchConstants.PrivateFlags); - } - - [PatchPostfix] - private async static void PatchPostfix(Task __result, Player __instance) - { - await __result; - - bool isYouPlayer; - - if (Is231Up) - { - isYouPlayer = __instance.IsYourPlayer; - } - else - { - isYouPlayer = __instance.Id == 1; - } - - if (isYouPlayer) - { - SkinHidePlugin.Player = __instance.PlayerBody; - } - else - { - SkinHidePlugin.BotList.Add(__instance.PlayerBody); - } - } - } - - public class PlayerEndPatch : ModulePatch - { - private static readonly bool Is231Up = SkinHidePlugin.GameVersion > new Version("0.12.12.17349"); - - protected override MethodBase GetTargetMethod() - { - return typeof(Player).GetMethod("OnGameSessionEnd", BindingFlags.Public | BindingFlags.Instance); - } - - [PatchPostfix] - private static void PatchPostfix(Player __instance) - { - bool isYouPlayer; - - if (Is231Up) - { - isYouPlayer = __instance.IsYourPlayer; - } - else - { - isYouPlayer = __instance.Id == 1; - } - - if (isYouPlayer) - { - SkinHidePlugin.BotList.Clear(); - } - } - } -} diff --git a/SkinHide/SkinHidePlugin.cs b/SkinHide/SkinHidePlugin.cs deleted file mode 100644 index 9e506f0..0000000 --- a/SkinHide/SkinHidePlugin.cs +++ /dev/null @@ -1,206 +0,0 @@ -using BepInEx; -using BepInEx.Configuration; -using System; -using System.Linq; -using System.Diagnostics; -using System.Collections.Generic; -using UnityEngine; -using EFT; -using EFT.Visual; -using SkinHide.Patches; -using SkinHide.Utils; -using EFT.InventoryLogic; - -namespace SkinHide -{ - [BepInPlugin("com.kmyuhkyuk.SkinHide", "kmyuhkyuk-SkinHide", "1.2.7")] - public class SkinHidePlugin : BaseUnityPlugin - { - internal static PlayerBody Player; - - internal static PlayerBody PlayerModelView; - - internal static List BotList = new List(); - - private readonly SettingsData SettingsDatas = new SettingsData(); - - private readonly ReflectionData ReflectionDatas = new ReflectionData(); - - private bool PMVHideCache; - - private bool PlayerHideCache; - - private bool BotHideCache; - - internal static Version GameVersion { get; private set; } - - public enum Part - { - All, - Dress, - SkinDress - } - - private void Start() - { - Logger.LogInfo("Loaded: kmyuhkyuk-SkinHide"); - - FileVersionInfo exeInfo = Process.GetCurrentProcess().MainModule.FileVersionInfo; - - GameVersion = new Version(exeInfo.FileMajorPart, exeInfo.ProductMinorPart, exeInfo.ProductBuildPart, exeInfo.FilePrivatePart); - - const string skinHideSettings = "Skin Hide Settings"; - const string skinHidePartSettings = "隐藏部分设置 Skin Hide Part Settings"; - const string kbsSettings = "快捷键设置 Keyboard Shortcut Settings"; - - SettingsDatas.KeyPlayerSkinHide = Config.Bind(skinHideSettings, "玩家服装隐藏 Player Skin Hide", false); - SettingsDatas.KeyBotSkinHide = Config.Bind(skinHideSettings, "Bot服装隐藏 Bot Skin Hide", false); - - SettingsDatas.KeyPlayerSkinHidePart = Config.Bind(skinHidePartSettings, "Player", Part.All); - SettingsDatas.KeyBotSkinHidePart = Config.Bind(skinHidePartSettings, "Bot", Part.All); - - SettingsDatas.KBSPlayerSkinHide = Config.Bind(kbsSettings, "玩家服装隐藏快捷键 Player Skin Hide", KeyboardShortcut.Empty); - SettingsDatas.KBSBotSkinHide = Config.Bind(kbsSettings, "Bot服装隐藏快捷键 Bot Skin Hide", KeyboardShortcut.Empty); - - new PlayerModelViewPatch().Enable(); - new PlayerInitPatch().Enable(); - new PlayerEndPatch().Enable(); - - ReflectionDatas.RefSlotViews = RefHelp.FieldRef.Create("SlotViews"); - ReflectionDatas.RefSlotList = RefHelp.FieldRef>.Create(ReflectionDatas.RefSlotViews.FieldType, "list_0"); - ReflectionDatas.RefDresses = RefHelp.FieldRef.Create(ReflectionDatas.RefSlotList.FieldType.GetGenericArguments()[0], "Dresses"); - ReflectionDatas.RefRenderers = RefHelp.FieldRef.Create("Renderers"); - } - - void Update() - { - if (SettingsDatas.KBSPlayerSkinHide.Value.IsDown()) - { - SettingsDatas.KeyPlayerSkinHide.Value = !SettingsDatas.KeyPlayerSkinHide.Value; - } - if (SettingsDatas.KBSBotSkinHide.Value.IsDown()) - { - SettingsDatas.KeyBotSkinHide.Value = !SettingsDatas.KeyBotSkinHide.Value; - } - - //PlayerModelView Skin Hide - if (PlayerModelView != null) - { - if (SettingsDatas.KeyPlayerSkinHide.Value) - { - Hide(PlayerModelView, SettingsDatas.KeyPlayerSkinHidePart.Value, true); - - PMVHideCache = true; - } - else if (!SettingsDatas.KeyPlayerSkinHide.Value && PMVHideCache) - { - Hide(PlayerModelView, Part.All, false); - - PMVHideCache = false; - } - } - - //Player Skin Hide - if (Player != null) - { - if (SettingsDatas.KeyPlayerSkinHide.Value) - { - Hide(Player, SettingsDatas.KeyPlayerSkinHidePart.Value, true); - - PlayerHideCache = true; - } - else if (!SettingsDatas.KeyPlayerSkinHide.Value && PlayerHideCache) - { - Hide(Player, Part.All, false); - - PlayerHideCache = false; - } - } - - //Bot Skin Hide - if (BotList.Count > 0) - { - if (SettingsDatas.KeyBotSkinHide.Value) - { - foreach (PlayerBody bot in BotList) - { - Hide(bot, SettingsDatas.KeyBotSkinHidePart.Value, true); - } - - BotHideCache = true; - } - else if (!SettingsDatas.KeyBotSkinHide.Value && BotHideCache) - { - foreach (PlayerBody bot in BotList) - { - Hide(bot, Part.All, false); - } - - BotHideCache = false; - } - } - } - - void Hide(PlayerBody playerbody, Part part, bool hide) - { - object slotViews = ReflectionDatas.RefSlotViews.GetValue(playerbody); - - IEnumerable slotList = ReflectionDatas.RefSlotList.GetValue(slotViews); - - IEnumerable dresses = slotList.SelectMany(x => ReflectionDatas.RefDresses.GetValue(x)).Where(x => x != null); - - IEnumerable dress = dresses.Where(x => x.GetType() == typeof(Dress)); - - IEnumerable renDress = dress.SelectMany(x => ReflectionDatas.RefRenderers.GetValue(x)); - - IEnumerable skinDress = dresses.Where(x => x.GetType() == typeof(SkinDress) || x.GetType() == typeof(ArmBandView)).Select(x => x.gameObject); - - switch (part) - { - case Part.All: - foreach (GameObject gameobject in skinDress) - { - gameobject.SetActive(!hide); - } - - foreach (MeshRenderer renderer in renDress) - { - renderer.enabled = !hide; - } - break; - case Part.Dress: - foreach (MeshRenderer renderer in renDress) - { - renderer.enabled = !hide; - } - break; - case Part.SkinDress: - foreach (GameObject gameobject in skinDress) - { - gameobject.SetActive(!hide); - } - break; - } - } - - public class SettingsData - { - public ConfigEntry KeyPlayerSkinHide; - public ConfigEntry KeyBotSkinHide; - - public ConfigEntry KeyPlayerSkinHidePart; - public ConfigEntry KeyBotSkinHidePart; - - public ConfigEntry KBSPlayerSkinHide; - public ConfigEntry KBSBotSkinHide; - } - - public class ReflectionData - { - public RefHelp.FieldRef RefSlotViews; - public RefHelp.FieldRef> RefSlotList; - public RefHelp.FieldRef RefDresses; - public RefHelp.FieldRef RefRenderers; - } - } -} \ No newline at end of file diff --git a/SkinHide/Utils/RefHelp.cs b/SkinHide/Utils/RefHelp.cs deleted file mode 100644 index 8c60a04..0000000 --- a/SkinHide/Utils/RefHelp.cs +++ /dev/null @@ -1,431 +0,0 @@ -using Aki.Reflection.Utils; -using HarmonyLib; -using System; -using System.Linq; -using System.Reflection; -using System.Reflection.Emit; - -namespace SkinHide.Utils -{ - public class RefHelp - { - public static DelegateType ObjectMethodDelegate(MethodInfo method, bool virtualCall = true) where DelegateType : Delegate - { - if (method == null) - { - throw new ArgumentNullException(nameof(method)); - } - - var delegateType = typeof(DelegateType); - - var declaringType = method.DeclaringType; - - var delegateMethod = delegateType.GetMethod("Invoke"); - var delegateParameters = delegateMethod.GetParameters(); - var delegateParameterTypes = delegateParameters.Select(x => x.ParameterType).ToArray(); - - Type returnType; - bool needBox; - - if (delegateMethod.ReturnType == typeof(object) && method.ReturnType.IsValueType) - { - returnType = typeof(object); - - needBox = true; - } - else - { - returnType = method.ReturnType; - - needBox = false; - } - - var dmd = new DynamicMethod("OpenInstanceDelegate_" + method.Name, returnType, delegateParameterTypes); - - var ilGen = dmd.GetILGenerator(); - - Type[] parameterTypes; - int num; - - if (!method.IsStatic) - { - var parameters = method.GetParameters(); - var numParameters = parameters.Length; - parameterTypes = new Type[numParameters + 1]; - parameterTypes[0] = typeof(object); - - for (int i = 0; i < numParameters; i++) - { - parameterTypes[i + 1] = parameters[i].ParameterType; - } - - if (declaringType != null && declaringType.IsValueType) - { - ilGen.Emit(OpCodes.Ldarga_S, 0); - } - else - { - ilGen.Emit(OpCodes.Ldarg_0); - } - - ilGen.Emit(OpCodes.Castclass, declaringType); - - num = 1; - } - else - { - parameterTypes = method.GetParameters().Select(x => x.ParameterType).ToArray(); - - num = 0; - } - - for (int i = num; i < parameterTypes.Length; i++) - { - ilGen.Emit(OpCodes.Ldarg, i); - - Type parameterType = parameterTypes[i]; - - bool isValueType = parameterType.IsValueType; - - if (!isValueType) - { - ilGen.Emit(OpCodes.Castclass, parameterType); - } - //DelegateparameterTypes i == parameterTypes i - else if (delegateParameterTypes[i] == typeof(object) && isValueType) - { - ilGen.Emit(OpCodes.Unbox_Any, parameterType); - } - } - - if (method.IsStatic || !virtualCall) - { - ilGen.Emit(OpCodes.Call, method); - } - else - { - ilGen.Emit(OpCodes.Callvirt, method); - } - - if (needBox) - { - ilGen.Emit(OpCodes.Box, method.ReturnType); - } - - ilGen.Emit(OpCodes.Ret); - - return (DelegateType)dmd.CreateDelegate(delegateType); - } - - public class PropertyRef where T : class - { - private Func RefGetValue; - - private Action RefSetValue; - - private PropertyInfo PropertyInfo; - - private MethodInfo GetMethodInfo; - - private MethodInfo SetMethodInfo; - - private Type TType; - - private T Instance; - - public Type InType - { - get - { - return TType; - } - } - - public Type PropertyType - { - get - { - return PropertyInfo.PropertyType; - } - } - - public PropertyRef(PropertyInfo propertyinfo, object instance) - { - if (propertyinfo == null) - { - throw new Exception("PropertyInfo is null"); - } - - Init(propertyinfo, instance); - } - - public PropertyRef(Type type, string propertyname, bool declaredonly, object instance) - { - BindingFlags flags = declaredonly ? AccessTools.allDeclared : AccessTools.all; - - PropertyInfo propertyInfo = type.GetProperty(propertyname, flags); - - if (propertyInfo == null) - { - throw new Exception(propertyname + " is null"); - } - - Init(propertyInfo, instance); - } - - public PropertyRef(Type type, string[] propertynames, bool declaredonly, object instance) - { - BindingFlags flags = declaredonly ? AccessTools.allDeclared : AccessTools.all; - - PropertyInfo propertyInfo = propertyInfo = propertynames.Select(x => type.GetProperty(x, flags)).FirstOrDefault(x => x != null); - - if (propertyInfo == null) - { - throw new Exception(propertynames.First() + " is null"); - } - - Init(propertyInfo, instance); - } - - private void Init(PropertyInfo propertyinfo, object instance) - { - PropertyInfo = propertyinfo; - - TType = PropertyInfo.DeclaringType; - - Instance = (T)instance; - - if (PropertyInfo.CanRead) - { - GetMethodInfo = PropertyInfo.GetGetMethod(true); - - RefGetValue = ObjectMethodDelegate>(GetMethodInfo); - } - - if (PropertyInfo.CanWrite) - { - SetMethodInfo = PropertyInfo.GetSetMethod(true); - - RefSetValue = ObjectMethodDelegate>(SetMethodInfo); - } - } - - public static PropertyRef Create(PropertyInfo propertyinfo, object instance) - { - return new PropertyRef(propertyinfo, instance); - } - - public static PropertyRef Create(string propertyname, bool declaredonly = false, object instance = null) - { - return new PropertyRef(typeof(T), propertyname, declaredonly, instance); - } - - public static PropertyRef Create(string[] propertynames, bool declaredonly = false, object instance = null) - { - return new PropertyRef(typeof(T), propertynames, declaredonly, instance); - } - - public static PropertyRef Create(Type type, string propertyname, bool declaredonly = false, object instance = null) - { - return new PropertyRef(type, propertyname, declaredonly, instance); - } - - public static PropertyRef Create(Type type, string[] propertynames, bool declaredonly = false, object instance = null) - { - return new PropertyRef(type, propertynames, declaredonly, instance); - } - - public F GetValue(T instance) - { - if (RefGetValue == null) - { - throw new ArgumentNullException(nameof(RefGetValue)); - } - - if (instance != null && TType.IsAssignableFrom(instance.GetType())) - { - return RefGetValue(instance); - } - else if (Instance != null && instance == null) - { - return RefGetValue(Instance); - } - else - { - return default; - } - } - - public void SetValue(T instance, F value) - { - if (RefSetValue == null) - { - throw new ArgumentNullException(nameof(RefSetValue)); - } - - if (instance != null && TType.IsAssignableFrom(instance.GetType())) - { - RefSetValue(instance, value); - } - else if (Instance != null && instance == null) - { - RefSetValue(Instance, value); - } - } - } - - public class FieldRef where T : class - { - private AccessTools.FieldRef HarmonyFieldRef; - - private FieldInfo FieldInfo; - - private Type TType; - - private T Instance; - - public Type InType - { - get - { - return TType; - } - } - - public Type FieldType - { - get - { - return FieldInfo.FieldType; - } - } - - public FieldRef(FieldInfo fieldinfo, object instance) - { - if (fieldinfo == null) - { - throw new Exception("FieldInfo is null"); - } - - Init(fieldinfo, instance); - } - - public FieldRef(Type type, string fieldname, bool declaredonly, object instance) - { - BindingFlags flags = declaredonly ? AccessTools.allDeclared : AccessTools.all; - - FieldInfo fieldInfo = type.GetField(fieldname, flags); - - if (fieldInfo == null) - { - throw new Exception(fieldname + " is null"); - } - - Init(fieldInfo, instance); - } - - public FieldRef(Type type, string[] fieldnames, bool declaredonly, object instance) - { - BindingFlags flags = declaredonly ? AccessTools.allDeclared : AccessTools.all; - - FieldInfo fieldInfo = fieldnames.Select(x => type.GetField(x, flags)).FirstOrDefault(x => x != null); - - if (fieldInfo == null) - { - throw new Exception(fieldnames.First() + " is null"); - } - - Init(fieldInfo, instance); - } - - public static FieldRef Create(FieldInfo fieldinfo, object instance = null) - { - return new FieldRef(fieldinfo, instance); - } - - public static FieldRef Create(string fieldname, bool declaredonly = false, object instance = null) - { - return new FieldRef(typeof(T), fieldname, declaredonly, instance); - } - - public static FieldRef Create(string[] fieldnames, bool declaredonly = false, object instance = null) - { - return new FieldRef(typeof(T), fieldnames, declaredonly, instance); - } - - public static FieldRef Create(Type type, string fieldname, bool declaredonly = false, object instance = null) - { - return new FieldRef(type, fieldname, declaredonly, instance); - } - - public static FieldRef Create(Type type, string[] fieldnames, bool declaredonly = false, object instance = null) - { - return new FieldRef(type, fieldnames, declaredonly, instance); - } - - private void Init(FieldInfo fieldinfo, object instance = null) - { - FieldInfo = fieldinfo; - - TType = FieldInfo.DeclaringType; - - Instance = (T)instance; - - HarmonyFieldRef = AccessTools.FieldRefAccess(FieldInfo); - } - - public F GetValue(T instance) - { - if (HarmonyFieldRef == null) - { - throw new ArgumentNullException(nameof(HarmonyFieldRef)); - } - - if (instance != null && TType.IsAssignableFrom(instance.GetType())) - { - return HarmonyFieldRef(instance); - } - else if (Instance != null && instance == null) - { - return HarmonyFieldRef(Instance); - } - else - { - return default; - } - } - - public void SetValue(T instance, F value) - { - if (HarmonyFieldRef == null) - { - throw new ArgumentNullException(nameof(HarmonyFieldRef)); - } - - if (instance != null && TType.IsAssignableFrom(instance.GetType())) - { - HarmonyFieldRef(instance) = value; - } - else if (Instance != null && instance == null) - { - HarmonyFieldRef(Instance) = value; - } - } - } - - public static Type GetEftType(Func func) - { - return PatchConstants.EftTypes.Single(func); - } - - public static MethodInfo GetEftMethod(Type type, BindingFlags flags, Func func) - { - return type.GetMethods(flags).Single(func); - } - - public static MethodInfo GetEftMethod(Func func, BindingFlags flags, Func func2) - { - return GetEftMethod(GetEftType(func), flags, func2); - } - } -}