mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-06 05:01:53 +00:00
Try catch in C# Glue Functions called by engine, removed test ThrowException method
This commit is contained in:
@@ -113,7 +113,6 @@ static class CoreClrHelper
|
|||||||
|
|
||||||
GetFunctionPointerUnmanagedCallersOnly("GlitchyEngine.ScriptGlue, ScriptCore", "CreateScriptInstance", out _createScriptInstance);
|
GetFunctionPointerUnmanagedCallersOnly("GlitchyEngine.ScriptGlue, ScriptCore", "CreateScriptInstance", out _createScriptInstance);
|
||||||
|
|
||||||
GetFunctionPointerUnmanagedCallersOnly("GlitchyEngine.ScriptGlue, ScriptCore", "ThrowException", out _throwException);
|
|
||||||
GetFunctionPointerUnmanagedCallersOnly("GlitchyEngine.ScriptGlue, ScriptCore", "RegisterComponentType", out _registerComponentType);
|
GetFunctionPointerUnmanagedCallersOnly("GlitchyEngine.ScriptGlue, ScriptCore", "RegisterComponentType", out _registerComponentType);
|
||||||
|
|
||||||
InitEntityFunctions();
|
InitEntityFunctions();
|
||||||
|
|||||||
+188
-109
@@ -74,9 +74,14 @@ internal static unsafe partial class ScriptGlue
|
|||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
public static void SetEngineFunctions(EngineFunctions* engineFunctions)
|
public static void SetEngineFunctions(EngineFunctions* engineFunctions)
|
||||||
{
|
{
|
||||||
_engineFunctions = *engineFunctions;
|
try
|
||||||
|
{
|
||||||
Log.Info("Yeah");
|
_engineFunctions = *engineFunctions;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Exception(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -85,27 +90,27 @@ internal static unsafe partial class ScriptGlue
|
|||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
public static void LoadScriptAssembly(byte* assemblyData, long assemblyLength, byte* pdbData, long pdbLength)
|
public static void LoadScriptAssembly(byte* assemblyData, long assemblyLength, byte* pdbData, long pdbLength)
|
||||||
{
|
{
|
||||||
using UnmanagedMemoryStream assemblyStream = new(assemblyData, assemblyLength);
|
try
|
||||||
|
{
|
||||||
|
using UnmanagedMemoryStream assemblyStream = new(assemblyData, assemblyLength);
|
||||||
|
|
||||||
using UnmanagedMemoryStream? pdbStream = (pdbData != null) ? new UnmanagedMemoryStream(pdbData, pdbLength) : null;
|
using UnmanagedMemoryStream? pdbStream = (pdbData != null) ? new UnmanagedMemoryStream(pdbData, pdbLength) : null;
|
||||||
|
|
||||||
LoadAssembly(assemblyStream, pdbStream);
|
LoadAssembly(assemblyStream, pdbStream);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Exception(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void LoadAssembly(Stream assemblyStream, Stream? pdbStream)
|
private static void LoadAssembly(Stream assemblyStream, Stream? pdbStream)
|
||||||
{
|
{
|
||||||
try
|
_scriptAssemblyContext ??= new AssemblyLoadContext("ScriptContext", true);
|
||||||
{
|
|
||||||
_scriptAssemblyContext ??= new AssemblyLoadContext("ScriptContext", true);
|
|
||||||
|
|
||||||
_appAssembly = _scriptAssemblyContext.LoadFromStream(assemblyStream, pdbStream);
|
_appAssembly = _scriptAssemblyContext.LoadFromStream(assemblyStream, pdbStream);
|
||||||
|
|
||||||
Debug.Assert(_appAssembly != null);
|
Debug.Assert(_appAssembly != null);
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"Fehler: {e}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -114,8 +119,15 @@ internal static unsafe partial class ScriptGlue
|
|||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
public static void UnloadAssemblies()
|
public static void UnloadAssemblies()
|
||||||
{
|
{
|
||||||
_scriptAssemblyContext?.Unload();
|
try
|
||||||
_scriptAssemblyContext = null;
|
{
|
||||||
|
_scriptAssemblyContext?.Unload();
|
||||||
|
_scriptAssemblyContext = null;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Exception(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static NativeScriptClassInfo[]? _unsafeClasses;
|
private static NativeScriptClassInfo[]? _unsafeClasses;
|
||||||
@@ -148,61 +160,68 @@ internal static unsafe partial class ScriptGlue
|
|||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
public static void GetScriptClasses(NativeScriptClassInfo** outBuffer, long* length)
|
public static void GetScriptClasses(NativeScriptClassInfo** outBuffer, long* length)
|
||||||
{
|
{
|
||||||
using var contextualReflection = AssemblyLoadContext.EnterContextualReflection(_appAssembly);
|
try
|
||||||
|
|
||||||
Debug.Assert(_appAssembly != null);
|
|
||||||
|
|
||||||
Internal_FreeScriptClassNames();
|
|
||||||
|
|
||||||
var types = _appAssembly.GetTypes();
|
|
||||||
|
|
||||||
List<(string Name, Guid Guid, ScriptMethods AvailableMethods, bool runInEditMode)> scriptClasses = new();
|
|
||||||
|
|
||||||
foreach (var type in types)
|
|
||||||
{
|
{
|
||||||
if (type.IsSubclassOf(typeof(Entity)))
|
using var contextualReflection = AssemblyLoadContext.EnterContextualReflection(_appAssembly);
|
||||||
|
|
||||||
|
Debug.Assert(_appAssembly != null);
|
||||||
|
|
||||||
|
Internal_FreeScriptClassNames();
|
||||||
|
|
||||||
|
var types = _appAssembly.GetTypes();
|
||||||
|
|
||||||
|
List<(string Name, Guid Guid, ScriptMethods AvailableMethods, bool runInEditMode)> scriptClasses = new();
|
||||||
|
|
||||||
|
foreach (var type in types)
|
||||||
{
|
{
|
||||||
string? name = type.FullName;
|
if (type.IsSubclassOf(typeof(Entity)))
|
||||||
|
|
||||||
if (name == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
Guid guid = type.GUID;
|
|
||||||
|
|
||||||
ScriptMethods methods = ScriptMethods.None;
|
|
||||||
|
|
||||||
static ScriptMethods HasMethod(Type type, string methodName, ScriptMethods methodFlag)
|
|
||||||
{
|
{
|
||||||
MethodInfo? methodInfo = type.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly);
|
string? name = type.FullName;
|
||||||
|
|
||||||
return methodInfo != null ? methodFlag : ScriptMethods.None;
|
if (name == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Guid guid = type.GUID;
|
||||||
|
|
||||||
|
ScriptMethods methods = ScriptMethods.None;
|
||||||
|
|
||||||
|
static ScriptMethods HasMethod(Type type, string methodName, ScriptMethods methodFlag)
|
||||||
|
{
|
||||||
|
MethodInfo? methodInfo = type.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly);
|
||||||
|
|
||||||
|
return methodInfo != null ? methodFlag : ScriptMethods.None;
|
||||||
|
}
|
||||||
|
|
||||||
|
methods |= HasMethod(type, nameof(Entity.OnCreate), ScriptMethods.OnCreate);
|
||||||
|
methods |= HasMethod(type, nameof(Entity.OnUpdate), ScriptMethods.OnUpdate);
|
||||||
|
methods |= HasMethod(type, nameof(Entity.OnDestroy), ScriptMethods.OnDestroy);
|
||||||
|
|
||||||
|
bool runInEditMode = type.HasCustomAttribute<RunInEditModeAttribute>();
|
||||||
|
|
||||||
|
scriptClasses.Add((name, guid, methods, runInEditMode));
|
||||||
}
|
}
|
||||||
|
|
||||||
methods |= HasMethod(type, nameof(Entity.OnCreate), ScriptMethods.OnCreate);
|
|
||||||
methods |= HasMethod(type, nameof(Entity.OnUpdate), ScriptMethods.OnUpdate);
|
|
||||||
methods |= HasMethod(type, nameof(Entity.OnDestroy), ScriptMethods.OnDestroy);
|
|
||||||
|
|
||||||
bool runInEditMode = type.HasCustomAttribute<RunInEditModeAttribute>();
|
|
||||||
|
|
||||||
scriptClasses.Add((name, guid, methods, runInEditMode));
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
_unsafeClasses = new NativeScriptClassInfo[scriptClasses.Count];
|
_unsafeClasses = new NativeScriptClassInfo[scriptClasses.Count];
|
||||||
|
|
||||||
for (int i = 0; i < _unsafeClasses.Length; i++)
|
for (int i = 0; i < _unsafeClasses.Length; i++)
|
||||||
{
|
|
||||||
_unsafeClasses[i] = new NativeScriptClassInfo()
|
|
||||||
{
|
{
|
||||||
Guid = scriptClasses[i].Guid,
|
_unsafeClasses[i] = new NativeScriptClassInfo()
|
||||||
Name = Marshal.StringToCoTaskMemUTF8(scriptClasses[i].Name),
|
{
|
||||||
Methods = scriptClasses[i].AvailableMethods,
|
Guid = scriptClasses[i].Guid,
|
||||||
RunInEditMode = scriptClasses[i].runInEditMode
|
Name = Marshal.StringToCoTaskMemUTF8(scriptClasses[i].Name),
|
||||||
};
|
Methods = scriptClasses[i].AvailableMethods,
|
||||||
}
|
RunInEditMode = scriptClasses[i].runInEditMode
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
*outBuffer = (NativeScriptClassInfo*)Marshal.UnsafeAddrOfPinnedArrayElement(_unsafeClasses, 0);
|
*outBuffer = (NativeScriptClassInfo*)Marshal.UnsafeAddrOfPinnedArrayElement(_unsafeClasses, 0);
|
||||||
*length = _unsafeClasses.Length;
|
*length = _unsafeClasses.Length;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Exception(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -211,7 +230,14 @@ internal static unsafe partial class ScriptGlue
|
|||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
public static void FreeScriptClassNames()
|
public static void FreeScriptClassNames()
|
||||||
{
|
{
|
||||||
Internal_FreeScriptClassNames();
|
try
|
||||||
|
{
|
||||||
|
Internal_FreeScriptClassNames();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Exception(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void Internal_FreeScriptClassNames()
|
private static void Internal_FreeScriptClassNames()
|
||||||
@@ -237,8 +263,7 @@ internal static unsafe partial class ScriptGlue
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Console.WriteLine(e);
|
Log.Exception(e);
|
||||||
// TODO: Log exceptions to console
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -305,15 +330,22 @@ internal static unsafe partial class ScriptGlue
|
|||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
public static void CreateScriptInstance(UUID entityId, byte* scriptClassName)
|
public static void CreateScriptInstance(UUID entityId, byte* scriptClassName)
|
||||||
{
|
{
|
||||||
Type? scriptType = GetTypeFromNativeString(scriptClassName);
|
try
|
||||||
|
{
|
||||||
|
Type? scriptType = GetTypeFromNativeString(scriptClassName);
|
||||||
|
|
||||||
Debug.Assert(scriptType != null, "Script class Type not found.");
|
Debug.Assert(scriptType != null, "Script class Type not found.");
|
||||||
|
|
||||||
Entity? scriptInstance = ActivatorExtension.CreateEngineObject(scriptType, entityId) as Entity;
|
Entity? scriptInstance = ActivatorExtension.CreateEngineObject(scriptType, entityId) as Entity;
|
||||||
|
|
||||||
Debug.Assert(scriptInstance != null, "Failed to create script instance.");
|
Debug.Assert(scriptInstance != null, "Failed to create script instance.");
|
||||||
|
|
||||||
EntityScriptInstances.Add(entityId, (scriptInstance!, scriptType));
|
EntityScriptInstances.Add(entityId, (scriptInstance!, scriptType));
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Exception(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ComponentFunctionPointers
|
struct ComponentFunctionPointers
|
||||||
@@ -331,33 +363,34 @@ internal static unsafe partial class ScriptGlue
|
|||||||
delegate* unmanaged[Cdecl]<UUID, EngineResult> hasComponent,
|
delegate* unmanaged[Cdecl]<UUID, EngineResult> hasComponent,
|
||||||
delegate* unmanaged[Cdecl]<UUID, void> removeComponent)
|
delegate* unmanaged[Cdecl]<UUID, void> removeComponent)
|
||||||
{
|
{
|
||||||
string? beefComponentTypeName = Marshal.PtrToStringUTF8((IntPtr)fullComponentTypeName);
|
try
|
||||||
|
|
||||||
if (beefComponentTypeName == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
foreach(Type componentType in TypeExtension.FindDerivedTypes(typeof(Component)))
|
|
||||||
{
|
{
|
||||||
if (!componentType.TryGetCustomAttribute(out EngineClassAttribute mapping) ||
|
string? beefComponentTypeName = Marshal.PtrToStringUTF8((IntPtr)fullComponentTypeName);
|
||||||
mapping.EngineClassName != beefComponentTypeName) continue;
|
|
||||||
|
|
||||||
ComponentTypeFunctions[componentType] = new ComponentFunctionPointers
|
if (beefComponentTypeName == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach(Type componentType in TypeExtension.FindDerivedTypes(typeof(Component)))
|
||||||
{
|
{
|
||||||
AddComponent = addComponent,
|
if (!componentType.TryGetCustomAttribute(out EngineClassAttribute mapping) ||
|
||||||
HasComponent = hasComponent,
|
mapping.EngineClassName != beefComponentTypeName) continue;
|
||||||
RemoveComponent = removeComponent
|
|
||||||
};
|
|
||||||
|
|
||||||
return;
|
ComponentTypeFunctions[componentType] = new ComponentFunctionPointers
|
||||||
|
{
|
||||||
|
AddComponent = addComponent,
|
||||||
|
HasComponent = hasComponent,
|
||||||
|
RemoveComponent = removeComponent
|
||||||
|
};
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.Error($"Failed to register component type \"{beefComponentTypeName}\": No matching component class found.");
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Exception(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.Error($"Failed to register component type \"{beefComponentTypeName}\": No matching component class found.");
|
|
||||||
}
|
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
internal static void ThrowException(IntPtr message)
|
|
||||||
{
|
|
||||||
throw new Exception(Marshal.PtrToStringUTF8(message));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region EntitySerializer
|
#region EntitySerializer
|
||||||
@@ -365,49 +398,91 @@ internal static unsafe partial class ScriptGlue
|
|||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
public static void CreateSerializationContext(IntPtr engineSerializer)
|
public static void CreateSerializationContext(IntPtr engineSerializer)
|
||||||
{
|
{
|
||||||
EntitySerializer.CreateSerializationContext(engineSerializer);
|
try
|
||||||
|
{
|
||||||
|
EntitySerializer.CreateSerializationContext(engineSerializer);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Exception(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
public static void DestroySerializationContext(IntPtr engineSerializer)
|
public static void DestroySerializationContext(IntPtr engineSerializer)
|
||||||
{
|
{
|
||||||
EntitySerializer.DestroySerializationContext(engineSerializer);
|
try
|
||||||
|
{
|
||||||
|
EntitySerializer.DestroySerializationContext(engineSerializer);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Exception(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
public static void EntitySerializer_Serialize(UUID entityId, IntPtr engineObject, IntPtr engineSerializer)
|
public static void EntitySerializer_Serialize(UUID entityId, IntPtr engineObject, IntPtr engineSerializer)
|
||||||
{
|
{
|
||||||
if (!EntityScriptInstances.TryGetValue(entityId, out var match))
|
try
|
||||||
return;
|
{
|
||||||
|
if (!EntityScriptInstances.TryGetValue(entityId, out var match))
|
||||||
|
return;
|
||||||
|
|
||||||
EntitySerializer.Serialize(match.Entity, engineObject, engineSerializer);
|
EntitySerializer.Serialize(match.Entity, engineObject, engineSerializer);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Exception(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
public static void EntitySerializer_Deserialize(UUID entityId, IntPtr engineObject, IntPtr engineSerializer)
|
public static void EntitySerializer_Deserialize(UUID entityId, IntPtr engineObject, IntPtr engineSerializer)
|
||||||
{
|
{
|
||||||
if (!EntityScriptInstances.TryGetValue(entityId, out var match))
|
try
|
||||||
return;
|
{
|
||||||
|
if (!EntityScriptInstances.TryGetValue(entityId, out var match))
|
||||||
|
return;
|
||||||
|
|
||||||
EntitySerializer.Deserialize(match.Entity, engineObject, engineSerializer);
|
EntitySerializer.Deserialize(match.Entity, engineObject, engineSerializer);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Exception(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
public static void EntitySerializer_SerializeStaticFields(byte* fullTypeName, IntPtr engineObject, IntPtr engineSerializer)
|
public static void EntitySerializer_SerializeStaticFields(byte* fullTypeName, IntPtr engineObject, IntPtr engineSerializer)
|
||||||
{
|
{
|
||||||
Type? type = GetTypeFromNativeString(fullTypeName);
|
try
|
||||||
Debug.Assert(type != null);
|
{
|
||||||
|
Type? type = GetTypeFromNativeString(fullTypeName);
|
||||||
|
Debug.Assert(type != null);
|
||||||
|
|
||||||
EntitySerializer.SerializeStaticFields(type, engineObject, engineSerializer);
|
EntitySerializer.SerializeStaticFields(type, engineObject, engineSerializer);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Exception(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
public static void EntitySerializer_DeserializeStaticFields(byte* fullTypeName, IntPtr engineObject, IntPtr engineSerializer)
|
public static void EntitySerializer_DeserializeStaticFields(byte* fullTypeName, IntPtr engineObject, IntPtr engineSerializer)
|
||||||
{
|
{
|
||||||
Type? type = GetTypeFromNativeString(fullTypeName);
|
try
|
||||||
Debug.Assert(type != null);
|
{
|
||||||
|
Type? type = GetTypeFromNativeString(fullTypeName);
|
||||||
|
Debug.Assert(type != null);
|
||||||
|
|
||||||
EntitySerializer.DeserializeStaticFields(type, engineObject, engineSerializer);
|
EntitySerializer.DeserializeStaticFields(type, engineObject, engineSerializer);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Exception(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion EntitySerializer
|
#endregion EntitySerializer
|
||||||
@@ -454,8 +529,12 @@ internal static unsafe partial class ScriptGlue
|
|||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case SerializationType.String:
|
case SerializationType.String:
|
||||||
valueObjectConverted = (void*)Marshal.StringToCoTaskMemUTF8(fullTypeName);
|
case SerializationType.Enum:
|
||||||
deleteValueObject = true;
|
if (valueObject is String stringValue)
|
||||||
|
{
|
||||||
|
valueObjectConverted = (void*)Marshal.StringToCoTaskMemUTF8(stringValue);
|
||||||
|
deleteValueObject = true;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (valueObject is not null)
|
if (valueObject is not null)
|
||||||
|
|||||||
Reference in New Issue
Block a user