From e90a67a8d5053e9e02348adb49dae6f58002d8e7 Mon Sep 17 00:00:00 2001 From: kmyuhkyuk <2451614940@qq.com> Date: Tue, 11 Oct 2022 04:31:32 +0800 Subject: [PATCH] Update --- SkinHide/Properties/AssemblyInfo.cs | 4 +- SkinHide/SkinHide.csproj | 1 + SkinHide/SkinHidePlugin.cs | 29 ++- SkinHide/Utils/RefHelp.cs | 309 ++++++++++++++++++++++++++++ 4 files changed, 333 insertions(+), 10 deletions(-) create mode 100644 SkinHide/Utils/RefHelp.cs diff --git a/SkinHide/Properties/AssemblyInfo.cs b/SkinHide/Properties/AssemblyInfo.cs index 81251b7..5546fe6 100644 --- a/SkinHide/Properties/AssemblyInfo.cs +++ b/SkinHide/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ using System.Runtime.InteropServices; //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值 //通过使用 "*",如下所示: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.2.4.0")] -[assembly: AssemblyFileVersion("1.2.4.0")] +[assembly: AssemblyVersion("1.2.5.0")] +[assembly: AssemblyFileVersion("1.2.5.0")] diff --git a/SkinHide/SkinHide.csproj b/SkinHide/SkinHide.csproj index 17efc24..0796b49 100644 --- a/SkinHide/SkinHide.csproj +++ b/SkinHide/SkinHide.csproj @@ -82,6 +82,7 @@ + diff --git a/SkinHide/SkinHidePlugin.cs b/SkinHide/SkinHidePlugin.cs index a8c98e3..fa8c83a 100644 --- a/SkinHide/SkinHidePlugin.cs +++ b/SkinHide/SkinHidePlugin.cs @@ -1,26 +1,28 @@ using BepInEx; using BepInEx.Configuration; -using HarmonyLib; using System.Linq; using System.Collections.Generic; using UnityEngine; using EFT; using EFT.Visual; using SkinHide.Patches; +using SkinHide.Utils; namespace SkinHide { - [BepInPlugin("com.kmyuhkyuk.SkinHide", "kmyuhkyuk-SkinHide", "1.2.4")] + [BepInPlugin("com.kmyuhkyuk.SkinHide", "kmyuhkyuk-SkinHide", "1.2.5")] public class SkinHidePlugin : BaseUnityPlugin { - public static PlayerBody Player; + internal static PlayerBody Player; - public static PlayerBody PlayerModelView; + internal static PlayerBody PlayerModelView; - public static List Bot = new List(); + internal static List Bot = new List(); private SettingsData settingsdata = new SettingsData(); + private ReflectionData reflectiondata = new ReflectionData(); + public enum Part { All, @@ -47,6 +49,10 @@ namespace SkinHide new PlayerModelViewPatch().Enable(); new PlayerPatch().Enable(); + + reflectiondata.RefSlotViews = RefHelp.FieldRef.Create("SlotViews"); + reflectiondata.RefSlotList = RefHelp.FieldRef>.Create(reflectiondata.RefSlotViews.FieldType, "list_0"); + reflectiondata.RefDresses = RefHelp.FieldRef.Create(reflectiondata.RefSlotList.FieldType.GetGenericArguments()[0], "Dresses"); } void Update() @@ -88,11 +94,11 @@ namespace SkinHide void Hide(PlayerBody playerbody, Part part, bool hide) { - object slotviews = Traverse.Create(playerbody).Field("SlotViews").GetValue(); + object slotviews = reflectiondata.RefSlotViews.GetValue(playerbody); - IEnumerable slotlist = (IEnumerable)Traverse.Create(slotviews).Field("list_0").GetValue(); + IEnumerable slotlist = reflectiondata.RefSlotList.GetValue(slotviews); - Dress[] dresses = slotlist.Where(x => Traverse.Create(x).Field("Dresses").GetValue() != null).SelectMany(x => Traverse.Create(x).Field("Dresses").GetValue()).ToArray(); + Dress[] dresses = slotlist.Where(x => reflectiondata.RefDresses.GetValue(x) != null).SelectMany(x => reflectiondata.RefDresses.GetValue(x)).ToArray(); GameObject[] dress = dresses.Where(x => x.GetType() == typeof(Dress)).Select(x => x.gameObject).ToArray(); @@ -139,5 +145,12 @@ namespace SkinHide public ConfigEntry KBSPlayerSkinHide; public ConfigEntry KBSBotSkinHide; } + + public class ReflectionData + { + public RefHelp.FieldRef RefSlotViews; + public RefHelp.FieldRef> RefSlotList; + public RefHelp.FieldRef RefDresses; + } } } \ No newline at end of file diff --git a/SkinHide/Utils/RefHelp.cs b/SkinHide/Utils/RefHelp.cs new file mode 100644 index 0000000..26f011a --- /dev/null +++ b/SkinHide/Utils/RefHelp.cs @@ -0,0 +1,309 @@ +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 is null) + { + throw new ArgumentNullException(nameof(method)); + } + + var delegateType = typeof(DelegateType); + + var declaringType = method.DeclaringType; + + var DelegateParameters = delegateType.GetMethod("Invoke").GetParameters(); + var DelegateparameterTypes = DelegateParameters.Select(x => x.ParameterType).ToArray(); + + var dmd = new DynamicMethod("OpenInstanceDelegate_" + method.Name, method.ReturnType, DelegateparameterTypes); + + var ilGen = dmd.GetILGenerator(); + + if (!method.IsStatic) + { + var parameters = method.GetParameters(); + var numParameters = parameters.Length; + var parameterTypes = new Type[numParameters + 1]; + parameterTypes[0] = typeof(object); + for (var 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); + + for (var i = 1; i < parameterTypes.Length; i++) + { + ilGen.Emit(OpCodes.Ldarg, i); + ilGen.Emit(OpCodes.Castclass, parameterTypes[i]); + } + } + else + { + var parameterTypes = method.GetParameters().Select(x => x.ParameterType).ToArray(); + + for (var i = 0; i < parameterTypes.Length; i++) + { + ilGen.Emit(OpCodes.Ldarg, i); + ilGen.Emit(OpCodes.Castclass, parameterTypes[i]); + } + } + + + if (method.IsStatic || !virtualCall) + { + ilGen.Emit(OpCodes.Call, method); + } + else + { + ilGen.Emit(OpCodes.Callvirt, method); + } + + 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; + + public Type ReturnType; + + public PropertyRef(PropertyInfo propertyinfo, object instance = null) + { + Init(propertyinfo, instance); + } + + public PropertyRef(Type type, string propertyname, object instance = null) + { + Init(type.GetProperty(propertyname, AccessTools.all), instance); + } + + private void Init(PropertyInfo propertyinfo, object instance) + { + PropertyInfo = propertyinfo; + + TType = PropertyInfo.DeclaringType; + + Instance = (T)instance; + + GetMethodInfo = PropertyInfo.GetGetMethod(true); + + if (GetMethodInfo != null) + { + RefGetValue = ObjectMethodDelegate>(GetMethodInfo); + } + + SetMethodInfo = PropertyInfo.GetSetMethod(true); + + if (SetMethodInfo != null) + { + RefSetValue = ObjectMethodDelegate>(SetMethodInfo); + } + + if (GetMethodInfo != null && SetMethodInfo != null) + { + ReturnType = GetMethodInfo.ReturnType; + } + else if (GetMethodInfo != null || SetMethodInfo != null) + { + ReturnType = GetMethodInfo != null ? GetMethodInfo.ReturnType : SetMethodInfo.ReturnType; + } + } + + public static PropertyRef Create(PropertyInfo propertyinfo, object instance = null) + { + return new PropertyRef(propertyinfo, instance); + } + + public static PropertyRef Create(string propertyname, object instance = null) + { + return new PropertyRef(typeof(T), propertyname, instance); + } + + public static PropertyRef Create(Type type, string propertyname, object instance = null) + { + return new PropertyRef(type, propertyname, 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(F); + } + } + + 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 + { + private AccessTools.FieldRef HarmonyFieldRef; + + private FieldInfo FieldInfo; + + private Type TType; + + private T Instance; + + public Type InType; + + public Type FieldType; + + public FieldRef(FieldInfo fieldinfo, object instance = null) + { + Init(fieldinfo, instance); + } + + public FieldRef(Type type, string fieldname, object instance = null) + { + Init(type.GetField(fieldname, AccessTools.all), instance); + } + + public static FieldRef Create(FieldInfo fieldinfo, object instance = null) + { + return new FieldRef(fieldinfo, instance); + } + + public static FieldRef Create(string fieldname, object instance = null) + { + return new FieldRef(typeof(T), fieldname, instance); + } + + public static FieldRef Create(Type type, string fieldname, object instance = null) + { + return new FieldRef(type, fieldname, instance); + } + + private void Init(FieldInfo fieldinfo, object instance = null) + { + FieldInfo = fieldinfo; + + TType = FieldInfo.DeclaringType; + + InType = TType; + + FieldType = FieldInfo.FieldType; + + 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(F); + } + + } + + 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); + } + } +}