ScriptCore: Fixed component and entity reference serialization

This commit is contained in:
Simon Lübeß
2023-12-28 22:40:59 +01:00
parent 2e82f24fd7
commit 2fc45a50e0
2 changed files with 22 additions and 20 deletions
@@ -75,7 +75,7 @@ class SerializedObject
{ {
public uint8[16] RawData; public uint8[16] RawData;
public StringView StringView; public StringView StringView;
public (String Type, UUID ID) EngineObject; public (String FullTypeName, UUID ID) EngineObject;
static this() static this()
{ {
@@ -148,7 +148,7 @@ class SerializedObject
} }
data.StringView = valueView; data.StringView = valueView;
case .EntityReference | .ComponentReference: case .EntityReference, .ComponentReference:
String typeName = null; String typeName = null;
if (fullTypeName != null) if (fullTypeName != null)
@@ -161,7 +161,7 @@ class SerializedObject
Mono.mono_free(rawTypeName); Mono.mono_free(rawTypeName);
} }
data.EngineObject = (Type: typeName, ID: *(UUID*)Mono.mono_object_unbox(value)); data.EngineObject = (FullTypeName: typeName, ID: *(UUID*)Mono.mono_object_unbox(value));
default: default:
void* rawValue = Mono.mono_object_unbox(value); void* rawValue = Mono.mono_object_unbox(value);
@@ -189,11 +189,12 @@ class SerializedObject
{ {
case .String, .Enum: case .String, .Enum:
*(StringView*)target = field.Data.StringView; *(StringView*)target = field.Data.StringView;
case .EntityReference | .ComponentReference: case .EntityReference, .ComponentReference:
char8* typeNamePtr = field.Data.EngineObject.Type.Ptr; let engineObjectData = field.Data.EngineObject;
*(UUID*)target = field.Data.EngineObject.ID; *(char8**)target = engineObjectData.FullTypeName?.CStr();
*(char8**)(target + sizeof(UUID)) = typeNamePtr; *(int*)(target + sizeof(char8*)) = engineObjectData.FullTypeName?.Length ?? 0;
*(UUID*)(target + sizeof(char8*) + sizeof(int)) = engineObjectData.ID;
default: default:
// Most values can simply be copied, the conversion will be done in C# // Most values can simply be copied, the conversion will be done in C#
#unwarn #unwarn
+13 -12
View File
@@ -90,7 +90,7 @@ public static class EntitySerializer
private void PopScope() private void PopScope()
{ {
string scopeToRemove = _structScope.Pop(); string scopeToRemove = _structScope.Pop();
_structScopeName.Remove(_structScopeName.Length - scopeToRemove.Length - 1); _structScopeName = _structScopeName.Remove(_structScopeName.Length - scopeToRemove.Length - 1);
} }
private void AddField(string fieldName, SerializationType serializationType, object value, string fullTypeName = null) private void AddField(string fieldName, SerializationType serializationType, object value, string fullTypeName = null)
@@ -230,7 +230,7 @@ public static class EntitySerializer
{ {
AddField(fieldName, SerializationType.EntityReference, ((Entity)fieldValue)?.UUID ?? UUID.Zero, fieldValue?.GetType().FullName); AddField(fieldName, SerializationType.EntityReference, ((Entity)fieldValue)?.UUID ?? UUID.Zero, fieldValue?.GetType().FullName);
} }
else if (typeof(Component).IsAssignableFrom(fieldType)) else if (fieldType.IsSubclassOf(typeof(Component)))
{ {
AddField(fieldName, SerializationType.ComponentReference, ((Component)fieldValue)?.UUID ?? UUID.Zero, fieldValue?.GetType().FullName); AddField(fieldName, SerializationType.ComponentReference, ((Component)fieldValue)?.UUID ?? UUID.Zero, fieldValue?.GetType().FullName);
} }
@@ -349,7 +349,7 @@ public static class EntitySerializer
return context; return context;
} }
private void PushScope(string name) private void PushScope(string name)
{ {
_structScope.Push(name); _structScope.Push(name);
@@ -360,19 +360,20 @@ public static class EntitySerializer
private void PopScope() private void PopScope()
{ {
string scopeToRemove = _structScope.Pop(); string scopeToRemove = _structScope.Pop();
_structScopeName.Remove(_structScopeName.Length - scopeToRemove.Length - 1); _structScopeName = _structScopeName.Remove(_structScopeName.Length - scopeToRemove.Length - 1);
} }
[StructLayout(LayoutKind.Explicit)] [StructLayout(LayoutKind.Explicit)]
private struct DataHelper private unsafe struct DataHelper
{ {
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public struct EngineObjectReferenceHelper public struct EngineObjectReferenceHelper
{ {
public IntPtr FullTypeName; public byte* FullTypeName;
public long FullTypeNameLength;
public UUID Id; public UUID Id;
} }
[FieldOffset(0)] [FieldOffset(0)]
public EngineObjectReferenceHelper EngineObjectReference; public EngineObjectReferenceHelper EngineObjectReference;
} }
@@ -383,7 +384,7 @@ public static class EntitySerializer
// Decimal is the larges primitive we store so we use a decimal as stack allocated memory (because stackalloc doesn't seem to work :( // Decimal is the larges primitive we store so we use a decimal as stack allocated memory (because stackalloc doesn't seem to work :(
//decimal backingFieldOnStack = 0.0m; //decimal backingFieldOnStack = 0.0m;
byte* rawData = stackalloc byte[16]; byte* rawData = stackalloc byte[sizeof(DataHelper)];
//byte* rawData = (byte*)&backingFieldOnStack; //byte* rawData = (byte*)&backingFieldOnStack;
ref DataHelper dataHelper = ref Unsafe.AsRef<DataHelper>(rawData); ref DataHelper dataHelper = ref Unsafe.AsRef<DataHelper>(rawData);
@@ -605,21 +606,21 @@ public static class EntitySerializer
return changed ? targetInstance : null; return changed ? targetInstance : null;
} }
private object DeserializeClass(string fieldName, Type fieldType) private unsafe object DeserializeClass(string fieldName, Type fieldType)
{ {
bool isEntity = typeof(Entity).IsAssignableFrom(fieldType); bool isEntity = typeof(Entity).IsAssignableFrom(fieldType);
bool isComponent = fieldType.IsSubclassOf(typeof(Component)); bool isComponent = fieldType.IsSubclassOf(typeof(Component));
if (isEntity || isComponent) if (isEntity || isComponent)
{ {
var data = (DataHelper.EngineObjectReferenceHelper)GetFieldValue(fieldName, SerializationType.EntityReference); var data = (DataHelper.EngineObjectReferenceHelper)GetFieldValue(fieldName, isEntity ? SerializationType.EntityReference : SerializationType.ComponentReference);
UUID id = data.Id; UUID id = data.Id;
if (id == UUID.Zero) if (id == UUID.Zero)
return null; return null;
string fullTypeName = Marshal.PtrToStringUni(data.FullTypeName); string fullTypeName = Encoding.UTF8.GetString(data.FullTypeName, (int)data.FullTypeNameLength);
Type type = GetTypeFromName(fullTypeName); Type type = GetTypeFromName(fullTypeName);