Update
This commit is contained in:
parent
8ce38e51db
commit
e90a67a8d5
@ -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")]
|
||||||
|
@ -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" />
|
||||||
|
@ -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
309
SkinHide/Utils/RefHelp.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user