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.2.4.0")]
[assembly: AssemblyFileVersion("1.2.4.0")]
[assembly: AssemblyVersion("1.2.5.0")]
[assembly: AssemblyFileVersion("1.2.5.0")]

View File

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

View File

@ -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 <PlayerBody> Bot = new List<PlayerBody>();
internal static List<PlayerBody> Bot = new List<PlayerBody>();
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<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()
@ -88,11 +94,11 @@ namespace SkinHide
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();
@ -139,5 +145,12 @@ namespace SkinHide
public ConfigEntry<KeyboardShortcut> KBSPlayerSkinHide;
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);
}
}
}