mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 13:01:52 +00:00
Serialization: Support sharing object references
This commit is contained in:
@@ -9,10 +9,18 @@ using internal GlitchyEngine.Scripting;
|
|||||||
|
|
||||||
class EntitySerializerWrapper : ScriptClass
|
class EntitySerializerWrapper : ScriptClass
|
||||||
{
|
{
|
||||||
function MonoObject* SerializeMethod(MonoObject* entity, void* contextPtr, MonoException** exception);
|
function void CreateSerializationContextMethod(void* serializerPtr, MonoException** exception);
|
||||||
function MonoObject* DeserializeMethod(MonoObject* entity, void* contextPtr, MonoException** exception);
|
function void ClearSerializationContextMethod(void* serializerPtr, MonoException** exception);
|
||||||
function MonoObject* SerializeStaticMethod(MonoReflectionType* type, void* contextPtr, MonoException** exception);
|
function void DestroySerializationContextMethod(void* serializerPtr, MonoException** exception);
|
||||||
function MonoObject* DeserializeStaticMethod(MonoReflectionType* type, void* contextPtr, MonoException** exception);
|
|
||||||
|
function void SerializeMethod(MonoObject* entity, void* serializedObjPtr, void* serializerPtr, MonoException** exception);
|
||||||
|
function void DeserializeMethod(MonoObject* entity, void* serializedObjPtr, void* serializerPtr, MonoException** exception);
|
||||||
|
function void SerializeStaticMethod(MonoReflectionType* type, void* serializedObjPtr, void* serializerPtr, MonoException** exception);
|
||||||
|
function void DeserializeStaticMethod(MonoReflectionType* type, void* serializedObjPtr, void* serializerPtr, MonoException** exception);
|
||||||
|
|
||||||
|
private CreateSerializationContextMethod _createSerializationContextMethod;
|
||||||
|
private ClearSerializationContextMethod _clearSerializationContextMethod;
|
||||||
|
private DestroySerializationContextMethod _destroySerializationContextMethod;
|
||||||
|
|
||||||
private SerializeMethod _serializeMethod;
|
private SerializeMethod _serializeMethod;
|
||||||
private DeserializeMethod _deserializeMethod;
|
private DeserializeMethod _deserializeMethod;
|
||||||
@@ -22,82 +30,138 @@ class EntitySerializerWrapper : ScriptClass
|
|||||||
[AllowAppend]
|
[AllowAppend]
|
||||||
public this(StringView classNamespace, StringView className, MonoImage* image) : base(classNamespace, className, image)
|
public this(StringView classNamespace, StringView className, MonoImage* image) : base(classNamespace, className, image)
|
||||||
{
|
{
|
||||||
_serializeMethod = (SerializeMethod)GetMethodThunk("Serialize", 2);
|
_serializeMethod = (SerializeMethod)GetMethodThunk("Serialize", 3);
|
||||||
|
|
||||||
if (_serializeMethod == null)
|
if (_serializeMethod == null)
|
||||||
{
|
{
|
||||||
Log.EngineLogger.Error("EntitySerializer has no \"Serialize\" method.");
|
Log.EngineLogger.Error("EntitySerializer has no \"Serialize\" method.");
|
||||||
}
|
}
|
||||||
|
|
||||||
_deserializeMethod = (DeserializeMethod)GetMethodThunk("Deserialize", 2);
|
_deserializeMethod = (DeserializeMethod)GetMethodThunk("Deserialize", 3);
|
||||||
|
|
||||||
if (_serializeMethod == null)
|
if (_serializeMethod == null)
|
||||||
{
|
{
|
||||||
Log.EngineLogger.Error("EntitySerializer has no \"Deserialize\" method.");
|
Log.EngineLogger.Error("EntitySerializer has no \"Deserialize\" method.");
|
||||||
}
|
}
|
||||||
|
|
||||||
_serializeStaticMethod = (SerializeStaticMethod)GetMethodThunk("SerializeStaticFields", 2);
|
_serializeStaticMethod = (SerializeStaticMethod)GetMethodThunk("SerializeStaticFields", 3);
|
||||||
|
|
||||||
if (_serializeStaticMethod == null)
|
if (_serializeStaticMethod == null)
|
||||||
{
|
{
|
||||||
Log.EngineLogger.Error("EntitySerializer has no \"SerializeStaticStatic\" method.");
|
Log.EngineLogger.Error("EntitySerializer has no \"SerializeStaticStatic\" method.");
|
||||||
}
|
}
|
||||||
|
|
||||||
_deserializeStaticMethod = (SerializeStaticMethod)GetMethodThunk("DeserializeStaticFields", 2);
|
_deserializeStaticMethod = (SerializeStaticMethod)GetMethodThunk("DeserializeStaticFields", 3);
|
||||||
|
|
||||||
if (_deserializeStaticMethod == null)
|
if (_deserializeStaticMethod == null)
|
||||||
{
|
{
|
||||||
Log.EngineLogger.Error("EntitySerializer has no \"DeserializeStaticStatic\" method.");
|
Log.EngineLogger.Error("EntitySerializer has no \"DeserializeStaticStatic\" method.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_createSerializationContextMethod = (CreateSerializationContextMethod)GetMethodThunk("CreateSerializationContext", 1);
|
||||||
|
|
||||||
|
if (_createSerializationContextMethod == null)
|
||||||
|
{
|
||||||
|
Log.EngineLogger.Error("EntitySerializer has no \"CreateSerializationContext\" method.");
|
||||||
|
}
|
||||||
|
|
||||||
|
_clearSerializationContextMethod = (ClearSerializationContextMethod)GetMethodThunk("ClearSerializationContext", 1);
|
||||||
|
|
||||||
|
if (_clearSerializationContextMethod == null)
|
||||||
|
{
|
||||||
|
Log.EngineLogger.Error("EntitySerializer has no \"ClearSerializationContext\" method.");
|
||||||
|
}
|
||||||
|
|
||||||
|
_destroySerializationContextMethod = (DestroySerializationContextMethod)GetMethodThunk("DestroySerializationContext", 1);
|
||||||
|
|
||||||
|
if (_destroySerializationContextMethod == null)
|
||||||
|
{
|
||||||
|
Log.EngineLogger.Error("EntitySerializer has no \"DestroySerializationContext\" method.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Serialize(ScriptInstance instance, SerializedObject context)
|
public void CreateSerializationContext(ScriptInstanceSerializer serializer)
|
||||||
{
|
{
|
||||||
void* thisPtr = Internal.UnsafeCastToPtr(context);
|
void* serializerPtr = Internal.UnsafeCastToPtr(serializer);
|
||||||
|
|
||||||
MonoException* exception = null;
|
MonoException* exception = null;
|
||||||
_serializeMethod(instance.[Friend]_instance, thisPtr, &exception);
|
_createSerializationContextMethod(serializerPtr, &exception);
|
||||||
|
|
||||||
if (exception != null)
|
|
||||||
ScriptEngine.[Friend]HandleMonoException(exception, instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SerializeStatic(ScriptClass @class, SerializedObject context)
|
|
||||||
{
|
|
||||||
void* thisPtr = Internal.UnsafeCastToPtr(context);
|
|
||||||
|
|
||||||
MonoException* exception = null;
|
|
||||||
|
|
||||||
MonoType* type = Mono.mono_class_get_type(@class.[Friend]_monoClass);
|
|
||||||
MonoReflectionType* reflectionType = Mono.mono_type_get_object(ScriptEngine.[Friend]s_AppDomain, type);
|
|
||||||
|
|
||||||
_serializeStaticMethod(reflectionType, thisPtr, &exception);
|
|
||||||
|
|
||||||
if (exception != null)
|
if (exception != null)
|
||||||
ScriptEngine.[Friend]HandleMonoException(exception, null);
|
ScriptEngine.[Friend]HandleMonoException(exception, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Deserialize(ScriptInstance instance, SerializedObject context)
|
public void ClearSerializationContext(ScriptInstanceSerializer serializer)
|
||||||
{
|
{
|
||||||
void* thisPtr = Internal.UnsafeCastToPtr(context);
|
void* serializerPtr = Internal.UnsafeCastToPtr(serializer);
|
||||||
|
|
||||||
MonoException* exception = null;
|
MonoException* exception = null;
|
||||||
_deserializeMethod(instance.[Friend]_instance, thisPtr, &exception);
|
_clearSerializationContextMethod(serializerPtr, &exception);
|
||||||
|
|
||||||
|
if (exception != null)
|
||||||
|
ScriptEngine.[Friend]HandleMonoException(exception, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DestroySerializationContext(ScriptInstanceSerializer serializer)
|
||||||
|
{
|
||||||
|
void* serializerPtr = Internal.UnsafeCastToPtr(serializer);
|
||||||
|
|
||||||
|
MonoException* exception = null;
|
||||||
|
_destroySerializationContextMethod(serializerPtr, &exception);
|
||||||
|
|
||||||
|
if (exception != null)
|
||||||
|
ScriptEngine.[Friend]HandleMonoException(exception, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Serialize(ScriptInstance instance, SerializedObject serializedObject)
|
||||||
|
{
|
||||||
|
void* serializedObjectPtr = Internal.UnsafeCastToPtr(serializedObject);
|
||||||
|
void* serializerPtr = Internal.UnsafeCastToPtr(serializedObject.Serializer);
|
||||||
|
|
||||||
|
MonoException* exception = null;
|
||||||
|
_serializeMethod(instance.[Friend]_instance, serializedObjectPtr, serializerPtr, &exception);
|
||||||
|
|
||||||
if (exception != null)
|
if (exception != null)
|
||||||
ScriptEngine.[Friend]HandleMonoException(exception, instance);
|
ScriptEngine.[Friend]HandleMonoException(exception, instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DeserializeStatic(ScriptClass @class, SerializedObject context)
|
public void SerializeStatic(ScriptClass @class, SerializedObject serializedObject)
|
||||||
{
|
{
|
||||||
void* thisPtr = Internal.UnsafeCastToPtr(context);
|
void* serializedObjectPtr = Internal.UnsafeCastToPtr(serializedObject);
|
||||||
|
void* serializerPtr = Internal.UnsafeCastToPtr(serializedObject.Serializer);
|
||||||
MonoException* exception = null;
|
|
||||||
|
|
||||||
MonoType* type = Mono.mono_class_get_type(@class.[Friend]_monoClass);
|
MonoType* type = Mono.mono_class_get_type(@class.[Friend]_monoClass);
|
||||||
MonoReflectionType* reflectionType = Mono.mono_type_get_object(ScriptEngine.[Friend]s_AppDomain, type);
|
MonoReflectionType* reflectionType = Mono.mono_type_get_object(ScriptEngine.[Friend]s_AppDomain, type);
|
||||||
|
|
||||||
_deserializeStaticMethod(reflectionType, thisPtr, &exception);
|
MonoException* exception = null;
|
||||||
|
_serializeStaticMethod(reflectionType, serializedObjectPtr, serializerPtr, &exception);
|
||||||
|
|
||||||
|
if (exception != null)
|
||||||
|
ScriptEngine.[Friend]HandleMonoException(exception, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Deserialize(ScriptInstance instance, SerializedObject serializedObject)
|
||||||
|
{
|
||||||
|
void* serializedObjectPtr = Internal.UnsafeCastToPtr(serializedObject);
|
||||||
|
void* serializerPtr = Internal.UnsafeCastToPtr(serializedObject.Serializer);
|
||||||
|
|
||||||
|
MonoException* exception = null;
|
||||||
|
_deserializeMethod(instance.[Friend]_instance, serializedObjectPtr, serializerPtr, &exception);
|
||||||
|
|
||||||
|
if (exception != null)
|
||||||
|
ScriptEngine.[Friend]HandleMonoException(exception, instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DeserializeStatic(ScriptClass @class, SerializedObject serializedObject)
|
||||||
|
{
|
||||||
|
void* serializedObjectPtr = Internal.UnsafeCastToPtr(serializedObject);
|
||||||
|
void* serializerPtr = Internal.UnsafeCastToPtr(serializedObject.Serializer);
|
||||||
|
|
||||||
|
MonoType* type = Mono.mono_class_get_type(@class.[Friend]_monoClass);
|
||||||
|
MonoReflectionType* reflectionType = Mono.mono_type_get_object(ScriptEngine.[Friend]s_AppDomain, type);
|
||||||
|
|
||||||
|
MonoException* exception = null;
|
||||||
|
_deserializeStaticMethod(reflectionType, serializedObjectPtr, serializerPtr, &exception);
|
||||||
|
|
||||||
if (exception != null)
|
if (exception != null)
|
||||||
ScriptEngine.[Friend]HandleMonoException(exception, null);
|
ScriptEngine.[Friend]HandleMonoException(exception, null);
|
||||||
|
|||||||
@@ -24,6 +24,12 @@ public class ScriptInstanceSerializer
|
|||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
ClearDictionaryAndDeleteValues!(_serializedData);
|
ClearDictionaryAndDeleteValues!(_serializedData);
|
||||||
|
ScriptEngine.Classes.EntitySerializer.DestroySerializationContext(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Init()
|
||||||
|
{
|
||||||
|
ScriptEngine.Classes.EntitySerializer.CreateSerializationContext(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Serializes all script instances that are currently managed by the ScriptEngine.
|
/// Serializes all script instances that are currently managed by the ScriptEngine.
|
||||||
@@ -31,6 +37,8 @@ public class ScriptInstanceSerializer
|
|||||||
{
|
{
|
||||||
Debug.Profiler.ProfileFunction!();
|
Debug.Profiler.ProfileFunction!();
|
||||||
|
|
||||||
|
Init();
|
||||||
|
|
||||||
for (let (id, scriptInstance) in ScriptEngine._entityScriptInstances)
|
for (let (id, scriptInstance) in ScriptEngine._entityScriptInstances)
|
||||||
{
|
{
|
||||||
SerializeScriptInstance(scriptInstance);
|
SerializeScriptInstance(scriptInstance);
|
||||||
@@ -61,6 +69,8 @@ public class ScriptInstanceSerializer
|
|||||||
{
|
{
|
||||||
Debug.Profiler.ProfileFunction!();
|
Debug.Profiler.ProfileFunction!();
|
||||||
|
|
||||||
|
Init();
|
||||||
|
|
||||||
for (let (id, script) in ScriptEngine._entityScriptInstances)
|
for (let (id, script) in ScriptEngine._entityScriptInstances)
|
||||||
{
|
{
|
||||||
DeserializeScriptInstance(id, script);
|
DeserializeScriptInstance(id, script);
|
||||||
|
|||||||
@@ -123,6 +123,7 @@ namespace GlitchyEngine.World
|
|||||||
});
|
});
|
||||||
|
|
||||||
_font = new Font(@"C:\Windows\Fonts\arial.ttf", 24);
|
_font = new Font(@"C:\Windows\Fonts\arial.ttf", 24);
|
||||||
|
//_font = new Font(@"C:\Windows\Fonts\Cascadia Code.ttf", 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ~this()
|
public ~this()
|
||||||
@@ -958,9 +959,8 @@ namespace GlitchyEngine.World
|
|||||||
*/
|
*/
|
||||||
public Entity CreateInstance(Entity entity)
|
public Entity CreateInstance(Entity entity)
|
||||||
{
|
{
|
||||||
//Dictionary<UUID, SerializedObject> serializedData = scope .();
|
|
||||||
ScriptInstanceSerializer scriptSerializer = scope .();
|
ScriptInstanceSerializer scriptSerializer = scope .();
|
||||||
//defer { ClearDictionaryAndDeleteValues!(serializedData); }
|
scriptSerializer.Init();
|
||||||
|
|
||||||
List<Entity> newEntities = scope .();
|
List<Entity> newEntities = scope .();
|
||||||
Dictionary<EcsEntity, EcsEntity> sourceToTargetEntity = scope .();
|
Dictionary<EcsEntity, EcsEntity> sourceToTargetEntity = scope .();
|
||||||
|
|||||||
@@ -603,6 +603,11 @@ public class DeserializationObject
|
|||||||
if (type == null)
|
if (type == null)
|
||||||
return NoValueDeserialized;
|
return NoValueDeserialized;
|
||||||
|
|
||||||
|
if (deserializedObject._instance != null)
|
||||||
|
{
|
||||||
|
return deserializedObject._instance;
|
||||||
|
}
|
||||||
|
|
||||||
deserializedObject._instance = ActivatorExtension.CreateInstanceSafe(type);
|
deserializedObject._instance = ActivatorExtension.CreateInstanceSafe(type);
|
||||||
|
|
||||||
if (deserializedObject._instance == null)
|
if (deserializedObject._instance == null)
|
||||||
|
|||||||
@@ -9,27 +9,54 @@ namespace GlitchyEngine.Serialization;
|
|||||||
|
|
||||||
internal static class EntitySerializer
|
internal static class EntitySerializer
|
||||||
{
|
{
|
||||||
internal static void Serialize(Entity entity, IntPtr internalContext)
|
private static Dictionary<IntPtr, Dictionary<object, SerializedObject>> SerializationObjects = new();
|
||||||
|
private static Dictionary<IntPtr, Dictionary<UUID, DeserializationObject>> DeserializationObjects = new();
|
||||||
|
|
||||||
|
internal static void CreateSerializationContext(IntPtr engineSerializer)
|
||||||
{
|
{
|
||||||
SerializedObject obj = new SerializedObject(internalContext, false, UUID.Zero, new Dictionary<object, SerializedObject>());
|
if (SerializationObjects.ContainsKey(engineSerializer))
|
||||||
|
{
|
||||||
|
ClearSerializationContext(engineSerializer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SerializationObjects.Add(engineSerializer, new Dictionary<object, SerializedObject>());
|
||||||
|
DeserializationObjects.Add(engineSerializer, new Dictionary<UUID, DeserializationObject>());
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void ClearSerializationContext(IntPtr engineSerializer)
|
||||||
|
{
|
||||||
|
SerializationObjects[engineSerializer].Clear();
|
||||||
|
DeserializationObjects[engineSerializer].Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void DestroySerializationContext(IntPtr engineSerializer)
|
||||||
|
{
|
||||||
|
SerializationObjects.Remove(engineSerializer);
|
||||||
|
DeserializationObjects.Remove(engineSerializer);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void Serialize(Entity entity, IntPtr engineObject, IntPtr engineSerializer)
|
||||||
|
{
|
||||||
|
SerializedObject obj = new SerializedObject(engineObject, false, UUID.Zero, SerializationObjects[engineSerializer]);
|
||||||
obj.Serialize(entity);
|
obj.Serialize(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void Deserialize(Entity entity, IntPtr internalContext)
|
internal static void Deserialize(Entity entity, IntPtr engineObject, IntPtr engineSerializer)
|
||||||
{
|
{
|
||||||
DeserializationObject obj = new DeserializationObject(internalContext, false, UUID.Zero, new Dictionary<UUID, DeserializationObject>());
|
DeserializationObject obj = new DeserializationObject(engineObject, false, UUID.Zero, DeserializationObjects[engineSerializer]);
|
||||||
obj.Deserialize(entity);
|
obj.Deserialize(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void SerializeStaticFields(Type type, IntPtr internalContext)
|
internal static void SerializeStaticFields(Type type, IntPtr engineObject, IntPtr engineSerializer)
|
||||||
{
|
{
|
||||||
SerializedObject obj = new SerializedObject(internalContext, true, UUID.Zero, new Dictionary<object, SerializedObject>());
|
SerializedObject obj = new SerializedObject(engineObject, true, UUID.Zero, SerializationObjects[engineSerializer]);
|
||||||
obj.Serialize(type);
|
obj.Serialize(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void DeserializeStaticFields(Type type, IntPtr internalContext)
|
internal static void DeserializeStaticFields(Type type, IntPtr engineObject, IntPtr engineSerializer)
|
||||||
{
|
{
|
||||||
DeserializationObject obj = new DeserializationObject(internalContext, true, UUID.Zero, new Dictionary<UUID, DeserializationObject>());
|
DeserializationObject obj = new DeserializationObject(engineObject, true, UUID.Zero, DeserializationObjects[engineSerializer]);
|
||||||
obj.Deserialize(type);
|
obj.Deserialize(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user