65 lines
2.7 KiB
C#
65 lines
2.7 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Reflection;
|
|
using System.Runtime.InteropServices;
|
|
using PorygonSharp.Utilities;
|
|
|
|
namespace PorygonSharp.UserData
|
|
{
|
|
public static class UserDataHandler
|
|
{
|
|
private static readonly Dictionary<Type, uint> UserDataLookup = new Dictionary<Type, uint>();
|
|
|
|
private delegate IntPtr GetterDelegate(IntPtr ptr);
|
|
private delegate void SetterDelegate(IntPtr ptr, IntPtr val);
|
|
|
|
public static void RegisterType(string name, Type type)
|
|
{
|
|
var hash = name.ScriptHash();
|
|
RegisterUserDataType(hash);
|
|
UserDataLookup.Add(type, hash);
|
|
|
|
var fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
|
|
foreach (var field in fields)
|
|
{
|
|
var getter = new GetterDelegate(ptr =>
|
|
{
|
|
var obj = GCHandle.FromIntPtr(ptr).Target;
|
|
var value = field.GetValue(obj);
|
|
return new EvalValue(value).GetPointer();
|
|
});
|
|
var setter = new SetterDelegate((ptr, val) =>
|
|
{
|
|
var obj = GCHandle.FromIntPtr(ptr).Target;
|
|
var evalValue = Convert.ChangeType(new EvalValue(val).GetObjectValue(), field.FieldType);
|
|
field.SetValue(obj, evalValue);
|
|
});
|
|
var scriptType = ScriptType.ScriptType.GetScriptType(field.FieldType);
|
|
var userDataField = CreateUserDataField(scriptType, Marshal.GetFunctionPointerForDelegate(getter),
|
|
Marshal.GetFunctionPointerForDelegate(setter));
|
|
|
|
|
|
var fieldName = field.Name.ScriptHash();
|
|
RegisterUserDataField(hash, fieldName, userDataField);
|
|
}
|
|
}
|
|
|
|
public static uint GetTypeId(Type t)
|
|
{
|
|
return UserDataLookup[t];
|
|
}
|
|
|
|
[DllImport("libPorygonLang", EntryPoint = "RegisterUserDataType", CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern void RegisterUserDataType(uint hashId);
|
|
|
|
[DllImport("libPorygonLang", EntryPoint = "RegisterUserDataField", CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern void RegisterUserDataField(uint hashId, uint fieldId, IntPtr field);
|
|
|
|
[DllImport("libPorygonLang", EntryPoint = "CreateUserDataField", CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern IntPtr CreateUserDataField(IntPtr type, IntPtr getter, IntPtr setter);
|
|
|
|
[DllImport("libPorygonLang", EntryPoint = "GetUserDataFieldCount", CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern int GetUserDataFieldCount(uint hashId);
|
|
|
|
}
|
|
} |