Files
RAGECOOP-V/Client/Scripts/Util/NativeCaller.cs

140 lines
4.0 KiB
C#
Raw Normal View History

2022-10-23 19:02:39 +08:00
using System;
using System.Runtime.InteropServices;
2022-10-23 19:02:39 +08:00
using GTA.Math;
using GTA.Native;
namespace RageCoop.Client
{
2022-09-06 21:46:35 +08:00
[StructLayout(LayoutKind.Explicit, Size = 80)]
public struct HeadBlendData
{
2022-10-23 19:02:39 +08:00
[FieldOffset(0)] public int ShapeFirst;
2022-10-23 19:02:39 +08:00
[FieldOffset(8)] public int ShapeSecond;
2022-10-23 19:02:39 +08:00
[FieldOffset(16)] public int ShapeThird;
2022-10-23 19:02:39 +08:00
[FieldOffset(24)] public int SkinFirst;
2022-10-23 19:02:39 +08:00
[FieldOffset(32)] public int SkinSecond;
2022-10-23 19:02:39 +08:00
[FieldOffset(40)] public int SkinThird;
2022-10-23 19:02:39 +08:00
[FieldOffset(48)] public float ShapeMix;
2022-10-23 19:02:39 +08:00
[FieldOffset(56)] public float SkinMix;
2022-10-23 19:02:39 +08:00
[FieldOffset(64)] public float ThirdMix;
2022-09-06 21:46:35 +08:00
}
2022-09-06 21:46:35 +08:00
[StructLayout(LayoutKind.Explicit, Size = 24)]
public struct NativeVector3
{
2022-10-23 19:02:39 +08:00
[FieldOffset(0)] public float X;
2022-10-23 19:02:39 +08:00
[FieldOffset(8)] public float Y;
2022-10-23 19:02:39 +08:00
[FieldOffset(16)] public float Z;
2022-09-06 21:46:35 +08:00
public static implicit operator Vector3(NativeVector3 vec)
{
2022-10-23 19:02:39 +08:00
return new Vector3 { X = vec.X, Y = vec.Y, Z = vec.Z };
}
2022-10-23 19:02:39 +08:00
2022-09-06 21:46:35 +08:00
public static implicit operator NativeVector3(Vector3 vec)
{
2022-10-23 19:02:39 +08:00
return new NativeVector3 { X = vec.X, Y = vec.Y, Z = vec.Z };
2022-09-06 21:46:35 +08:00
}
}
2022-10-23 19:02:39 +08:00
2022-09-06 21:46:35 +08:00
public static class NativeCaller
{
// These are borrowed from ScriptHookVDotNet's
[DllImport("ScriptHookV.dll", ExactSpelling = true, EntryPoint = "?nativeInit@@YAX_K@Z")]
private static extern void NativeInit(ulong hash);
[DllImport("ScriptHookV.dll", ExactSpelling = true, EntryPoint = "?nativePush64@@YAX_K@Z")]
private static extern void NativePush64(ulong val);
[DllImport("ScriptHookV.dll", ExactSpelling = true, EntryPoint = "?nativeCall@@YAPEA_KXZ")]
private static extern unsafe ulong* NativeCall();
// These are from ScriptHookV's nativeCaller.h
private static unsafe void NativePush<T>(T val) where T : unmanaged
{
ulong val64 = 0;
*(T*)(&val64) = val;
NativePush64(val64);
}
public static unsafe R Invoke<R>(ulong hash) where R : unmanaged
{
NativeInit(hash);
2022-10-23 19:02:39 +08:00
return *(R*)NativeCall();
2022-09-06 21:46:35 +08:00
}
2022-10-23 19:02:39 +08:00
2022-09-06 21:46:35 +08:00
public static unsafe R Invoke<R>(Hash hash, params object[] args)
where R : unmanaged
{
NativeInit((ulong)hash);
var arguments = ConvertPrimitiveArguments(args);
foreach (var arg in arguments)
NativePush(arg);
2022-10-23 19:02:39 +08:00
return *(R*)NativeCall();
2022-09-06 21:46:35 +08:00
}
/// <summary>
2022-10-23 19:02:39 +08:00
/// Helper function that converts an array of primitive values to a native stack.
2022-09-06 21:46:35 +08:00
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
private static unsafe ulong[] ConvertPrimitiveArguments(object[] args)
{
var result = new ulong[args.Length];
2022-10-23 19:02:39 +08:00
for (var i = 0; i < args.Length; ++i)
2022-09-06 21:46:35 +08:00
{
if (args[i] is bool valueBool)
{
result[i] = valueBool ? 1ul : 0ul;
continue;
}
2022-10-23 19:02:39 +08:00
2022-09-06 21:46:35 +08:00
if (args[i] is byte valueByte)
{
result[i] = valueByte;
continue;
}
2022-10-23 19:02:39 +08:00
2022-09-06 21:46:35 +08:00
if (args[i] is int valueInt32)
{
result[i] = (ulong)valueInt32;
continue;
}
2022-10-23 19:02:39 +08:00
2022-09-06 21:46:35 +08:00
if (args[i] is ulong valueUInt64)
{
result[i] = valueUInt64;
continue;
}
2022-10-23 19:02:39 +08:00
2022-09-06 21:46:35 +08:00
if (args[i] is float valueFloat)
{
result[i] = *(ulong*)&valueFloat;
continue;
}
2022-10-23 19:02:39 +08:00
2022-09-06 21:46:35 +08:00
if (args[i] is IntPtr valueIntPtr)
{
result[i] = (ulong)valueIntPtr.ToInt64();
continue;
}
throw new ArgumentException("Unknown primitive type in native argument list", nameof(args));
}
return result;
}
}
2022-10-23 19:02:39 +08:00
}