This commit is contained in:
kmyuhkyuk 2022-10-11 04:31:32 +08:00
parent 8ce38e51db
commit e90a67a8d5
4 changed files with 333 additions and 10 deletions

View File

@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值 //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
//通过使用 "*",如下所示: //通过使用 "*",如下所示:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.2.4.0")] [assembly: AssemblyVersion("1.2.5.0")]
[assembly: AssemblyFileVersion("1.2.4.0")] [assembly: AssemblyFileVersion("1.2.5.0")]

View File

@ -82,6 +82,7 @@
<Compile Include="Patches\PlayerModelViewPatch.cs" /> <Compile Include="Patches\PlayerModelViewPatch.cs" />
<Compile Include="SkinHidePlugin.cs" /> <Compile Include="SkinHidePlugin.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Utils\RefHelp.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="kmyuhkyuk.pfx" /> <None Include="kmyuhkyuk.pfx" />

View File

@ -1,26 +1,28 @@
using BepInEx; using BepInEx;
using BepInEx.Configuration; using BepInEx.Configuration;
using HarmonyLib;
using System.Linq; using System.Linq;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
using EFT; using EFT;
using EFT.Visual; using EFT.Visual;
using SkinHide.Patches; using SkinHide.Patches;
using SkinHide.Utils;
namespace SkinHide 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 class SkinHidePlugin : BaseUnityPlugin
{ {
public static PlayerBody Player; internal static PlayerBody Player;
public static PlayerBody PlayerModelView; internal static PlayerBody PlayerModelView;
public static List <PlayerBody> Bot = new List<PlayerBody>(); internal static List<PlayerBody> Bot = new List<PlayerBody>();
private SettingsData settingsdata = new SettingsData(); private SettingsData settingsdata = new SettingsData();
private ReflectionData reflectiondata = new ReflectionData();
public enum Part public enum Part
{ {
All, All,
@ -47,6 +49,10 @@ namespace SkinHide
new PlayerModelViewPatch().Enable(); new PlayerModelViewPatch().Enable();
new PlayerPatch().Enable(); new PlayerPatch().Enable();
reflectiondata.RefSlotViews = RefHelp.FieldRef<PlayerBody, object>.Create("SlotViews");
reflectiondata.RefSlotList = RefHelp.FieldRef<object, IEnumerable<object>>.Create(reflectiondata.RefSlotViews.FieldType, "list_0");
reflectiondata.RefDresses = RefHelp.FieldRef<object, Dress[]>.Create(reflectiondata.RefSlotList.FieldType.GetGenericArguments()[0], "Dresses");
} }
void Update() void Update()
@ -88,11 +94,11 @@ namespace SkinHide
void Hide(PlayerBody playerbody, Part part, bool hide) void Hide(PlayerBody playerbody, Part part, bool hide)
{ {
object slotviews = Traverse.Create(playerbody).Field("SlotViews").GetValue<object>(); object slotviews = reflectiondata.RefSlotViews.GetValue(playerbody);
IEnumerable<object> slotlist = (IEnumerable<object>)Traverse.Create(slotviews).Field("list_0").GetValue<object>(); IEnumerable<object> slotlist = reflectiondata.RefSlotList.GetValue(slotviews);
Dress[] dresses = slotlist.Where(x => Traverse.Create(x).Field("Dresses").GetValue<Dress[]>() != null).SelectMany(x => Traverse.Create(x).Field("Dresses").GetValue<Dress[]>()).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(); GameObject[] dress = dresses.Where(x => x.GetType() == typeof(Dress)).Select(x => x.gameObject).ToArray();
@ -139,5 +145,12 @@ namespace SkinHide
public ConfigEntry<KeyboardShortcut> KBSPlayerSkinHide; public ConfigEntry<KeyboardShortcut> KBSPlayerSkinHide;
public ConfigEntry<KeyboardShortcut> KBSBotSkinHide; public ConfigEntry<KeyboardShortcut> KBSBotSkinHide;
} }
public class ReflectionData
{
public RefHelp.FieldRef<PlayerBody, object> RefSlotViews;
public RefHelp.FieldRef<object, IEnumerable<object>> RefSlotList;
public RefHelp.FieldRef<object, Dress[]> RefDresses;
}
} }
} }

309
SkinHide/Utils/RefHelp.cs Normal file
View File

@ -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<DelegateType>(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<T, F> where T : class
{
private Func<T, F> RefGetValue;
private Action<T, F> 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<Func<T, F>>(GetMethodInfo);
}
SetMethodInfo = PropertyInfo.GetSetMethod(true);
if (SetMethodInfo != null)
{
RefSetValue = ObjectMethodDelegate<Action<T, F>>(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<T, F> Create(PropertyInfo propertyinfo, object instance = null)
{
return new PropertyRef<T, F>(propertyinfo, instance);
}
public static PropertyRef<T, F> Create(string propertyname, object instance = null)
{
return new PropertyRef<T, F>(typeof(T), propertyname, instance);
}
public static PropertyRef<T, F> Create(Type type, string propertyname, object instance = null)
{
return new PropertyRef<T, F>(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<T, F>
{
private AccessTools.FieldRef<T, F> 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<T, F> Create(FieldInfo fieldinfo, object instance = null)
{
return new FieldRef<T, F>(fieldinfo, instance);
}
public static FieldRef<T, F> Create(string fieldname, object instance = null)
{
return new FieldRef<T, F>(typeof(T), fieldname, instance);
}
public static FieldRef<T, F> Create(Type type, string fieldname, object instance = null)
{
return new FieldRef<T, F>(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<T, F>(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<Type, bool> func)
{
return PatchConstants.EftTypes.Single(func);
}
public static MethodInfo GetEftMethod(Type type, BindingFlags flags, Func<MethodInfo, bool> func)
{
return type.GetMethods(flags).Single(func);
}
public static MethodInfo GetEftMethod(Func<Type, bool> func, BindingFlags flags, Func<MethodInfo, bool> func2)
{
return GetEftMethod(GetEftType(func), flags, func2);
}
}
}