PorygonSharp/PorygonSharp/UserData/UserDataHandler.cs

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);
}
}