mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 13:01:52 +00:00
ScriptEngine: Serialize static fields
This commit is contained in:
@@ -28,6 +28,8 @@ public class DeserializationObject
|
||||
|
||||
private IntPtr _internalContext;
|
||||
|
||||
private bool _isStatic;
|
||||
|
||||
private UUID _id;
|
||||
|
||||
private Stack<string> _structScope = new();
|
||||
@@ -57,9 +59,12 @@ public class DeserializationObject
|
||||
}
|
||||
}
|
||||
|
||||
public DeserializationObject(IntPtr internalContext, UUID id, Dictionary<UUID, DeserializationObject> deserializedClasses)
|
||||
public bool IsStatic => _isStatic;
|
||||
|
||||
public DeserializationObject(IntPtr internalContext, bool isStatic, UUID id, Dictionary<UUID, DeserializationObject> deserializedClasses)
|
||||
{
|
||||
_internalContext = internalContext;
|
||||
_isStatic = isStatic;
|
||||
_id = id;
|
||||
DeserializedClasses = deserializedClasses;
|
||||
}
|
||||
@@ -114,7 +119,7 @@ public class DeserializationObject
|
||||
return null;
|
||||
}
|
||||
|
||||
context = new DeserializationObject(contextPtr, id, DeserializedClasses);
|
||||
context = new DeserializationObject(contextPtr, false, id, DeserializedClasses);
|
||||
|
||||
DeserializedClasses.Add(id, context);
|
||||
|
||||
@@ -250,6 +255,36 @@ public class DeserializationObject
|
||||
|
||||
DeserializeFields(entity);
|
||||
}
|
||||
|
||||
public void Deserialize(Type type)
|
||||
{
|
||||
_instance = null;
|
||||
|
||||
DeserializeStaticFields(type);
|
||||
}
|
||||
|
||||
public bool DeserializeStaticFields(Type type)
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
foreach (FieldInfo field in type.GetFields(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public))
|
||||
{
|
||||
if (!EntitySerializer.SerializeField(field, true))
|
||||
continue;
|
||||
|
||||
object currentValue = field.GetValue(null);
|
||||
|
||||
object? deserializeValue = DeserializeField(currentValue, field.FieldType, field.Name);
|
||||
|
||||
if (deserializeValue != NoValueDeserialized)
|
||||
{
|
||||
field.SetValue(null, deserializeValue);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
public bool DeserializeFields(object obj)
|
||||
{
|
||||
@@ -259,7 +294,7 @@ public class DeserializationObject
|
||||
|
||||
foreach (FieldInfo field in type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
|
||||
{
|
||||
if (!EntitySerializer.SerializeField(field))
|
||||
if (!EntitySerializer.SerializeField(field, false))
|
||||
continue;
|
||||
|
||||
object currentValue = field.GetValue(obj);
|
||||
|
||||
@@ -7,102 +7,40 @@ using GlitchyEngine.Extensions;
|
||||
|
||||
namespace GlitchyEngine.Serialization;
|
||||
|
||||
[Flags]
|
||||
public enum SerializationType : uint
|
||||
{
|
||||
None = 0,
|
||||
|
||||
Bool = 1u << 31,
|
||||
|
||||
TextTypes = 1 << 30,
|
||||
|
||||
Char = TextTypes | 1,
|
||||
String = TextTypes | 2,
|
||||
|
||||
Number = 1 << 29,
|
||||
Integer = Number | 1 << 28,
|
||||
|
||||
Int8 = Integer | 1,
|
||||
Int16 = Integer | 2,
|
||||
Int32 = Integer | 3,
|
||||
Int64 = Integer | 4,
|
||||
UInt8 = Integer | 5,
|
||||
UInt16 = Integer | 6,
|
||||
UInt32 = Integer | 7,
|
||||
UInt64 = Integer | 8,
|
||||
|
||||
FloatingPoint = Number | 1 << 27,
|
||||
|
||||
Float = FloatingPoint | 1,
|
||||
Double = FloatingPoint | 2,
|
||||
Decimal = FloatingPoint | 3,
|
||||
|
||||
Enum = 1 << 26,
|
||||
|
||||
EntityReference = 1 << 25,
|
||||
ComponentReference = 1 << 24,
|
||||
|
||||
ObjectReference = 1 << 23,
|
||||
}
|
||||
|
||||
public static class SerializationTypeExtension
|
||||
{
|
||||
public static bool CanConvertTo(this SerializationType currentType, SerializationType targetType)
|
||||
{
|
||||
if (currentType.HasFlag(SerializationType.Number) && targetType.HasFlag(SerializationType.Number))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static Type? GetTypeInstance(this SerializationType currentType)
|
||||
{
|
||||
return currentType switch
|
||||
{
|
||||
SerializationType.Bool => typeof(bool),
|
||||
SerializationType.Char => typeof(char),
|
||||
SerializationType.String => typeof(string),
|
||||
SerializationType.Int8 => typeof(sbyte),
|
||||
SerializationType.Int16 => typeof(short),
|
||||
SerializationType.Int32 => typeof(int),
|
||||
SerializationType.Int64 => typeof(long),
|
||||
SerializationType.UInt8 => typeof(byte),
|
||||
SerializationType.UInt16 => typeof(ushort),
|
||||
SerializationType.UInt32 => typeof(uint),
|
||||
SerializationType.UInt64 => typeof(ulong),
|
||||
SerializationType.Float => typeof(float),
|
||||
SerializationType.Double => typeof(double),
|
||||
SerializationType.Decimal => typeof(decimal),
|
||||
SerializationType.Enum => typeof(Enum),
|
||||
SerializationType.EntityReference => typeof(UUID),
|
||||
SerializationType.ComponentReference => typeof(UUID),
|
||||
SerializationType.ObjectReference => typeof(UUID),
|
||||
_ => null
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
internal static class EntitySerializer
|
||||
{
|
||||
internal static void Serialize(Entity entity, IntPtr internalContext)
|
||||
{
|
||||
SerializedObject obj = new SerializedObject(internalContext, UUID.Zero, new Dictionary<object, SerializedObject>());
|
||||
SerializedObject obj = new SerializedObject(internalContext, false, UUID.Zero, new Dictionary<object, SerializedObject>());
|
||||
obj.Serialize(entity);
|
||||
}
|
||||
|
||||
internal static void Deserialize(Entity entity, IntPtr internalContext)
|
||||
{
|
||||
DeserializationObject obj = new DeserializationObject(internalContext, UUID.Zero, new Dictionary<UUID, DeserializationObject>());
|
||||
DeserializationObject obj = new DeserializationObject(internalContext, false, UUID.Zero, new Dictionary<UUID, DeserializationObject>());
|
||||
obj.Deserialize(entity);
|
||||
}
|
||||
|
||||
internal static void SerializeStaticFields(Type type, IntPtr internalContext)
|
||||
{
|
||||
SerializedObject obj = new SerializedObject(internalContext, true, UUID.Zero, new Dictionary<object, SerializedObject>());
|
||||
obj.Serialize(type);
|
||||
}
|
||||
|
||||
internal static void DeserializeStaticFields(Type type, IntPtr internalContext)
|
||||
{
|
||||
DeserializationObject obj = new DeserializationObject(internalContext, true, UUID.Zero, new Dictionary<UUID, DeserializationObject>());
|
||||
obj.Deserialize(type);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether or not the field described by the given <see cref="fieldInfo"/> should be serialized or not.
|
||||
/// </summary>
|
||||
internal static bool SerializeField(FieldInfo fieldInfo)
|
||||
/// <param name="fieldInfo">The field info for which to check whether the field should be serialized or not.</param>
|
||||
/// <param name="staticSerialization">If <see langword="true"/> the only Static fields can be serialized; if <see langword="false"/> only instance fields can be serialized.</param>
|
||||
internal static bool SerializeField(FieldInfo fieldInfo, bool staticSerialization)
|
||||
{
|
||||
// TODO: We want to be able to serialize static fields in the future!
|
||||
if (fieldInfo.IsStatic)
|
||||
if (staticSerialization != fieldInfo.IsStatic)
|
||||
return false;
|
||||
|
||||
var serializeField = fieldInfo.HasCustomAttribute<SerializeFieldAttribute>();
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
using System;
|
||||
using GlitchyEngine.Core;
|
||||
|
||||
namespace GlitchyEngine.Serialization;
|
||||
|
||||
[Flags]
|
||||
public enum SerializationType : uint
|
||||
{
|
||||
None = 0,
|
||||
|
||||
Bool = 1u << 31,
|
||||
|
||||
TextTypes = 1 << 30,
|
||||
|
||||
Char = TextTypes | 1,
|
||||
String = TextTypes | 2,
|
||||
|
||||
Number = 1 << 29,
|
||||
Integer = Number | 1 << 28,
|
||||
|
||||
Int8 = Integer | 1,
|
||||
Int16 = Integer | 2,
|
||||
Int32 = Integer | 3,
|
||||
Int64 = Integer | 4,
|
||||
UInt8 = Integer | 5,
|
||||
UInt16 = Integer | 6,
|
||||
UInt32 = Integer | 7,
|
||||
UInt64 = Integer | 8,
|
||||
|
||||
FloatingPoint = Number | 1 << 27,
|
||||
|
||||
Float = FloatingPoint | 1,
|
||||
Double = FloatingPoint | 2,
|
||||
Decimal = FloatingPoint | 3,
|
||||
|
||||
Enum = 1 << 26,
|
||||
|
||||
EntityReference = 1 << 25,
|
||||
ComponentReference = 1 << 24,
|
||||
|
||||
ObjectReference = 1 << 23,
|
||||
}
|
||||
|
||||
public static class SerializationTypeExtension
|
||||
{
|
||||
public static bool CanConvertTo(this SerializationType currentType, SerializationType targetType)
|
||||
{
|
||||
if (currentType.HasFlag(SerializationType.Number) && targetType.HasFlag(SerializationType.Number))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static Type? GetTypeInstance(this SerializationType currentType) =>
|
||||
currentType switch
|
||||
{
|
||||
SerializationType.Bool => typeof(bool),
|
||||
SerializationType.Char => typeof(char),
|
||||
SerializationType.String => typeof(string),
|
||||
SerializationType.Int8 => typeof(sbyte),
|
||||
SerializationType.Int16 => typeof(short),
|
||||
SerializationType.Int32 => typeof(int),
|
||||
SerializationType.Int64 => typeof(long),
|
||||
SerializationType.UInt8 => typeof(byte),
|
||||
SerializationType.UInt16 => typeof(ushort),
|
||||
SerializationType.UInt32 => typeof(uint),
|
||||
SerializationType.UInt64 => typeof(ulong),
|
||||
SerializationType.Float => typeof(float),
|
||||
SerializationType.Double => typeof(double),
|
||||
SerializationType.Decimal => typeof(decimal),
|
||||
SerializationType.Enum => typeof(Enum),
|
||||
SerializationType.EntityReference => typeof(UUID),
|
||||
SerializationType.ComponentReference => typeof(UUID),
|
||||
SerializationType.ObjectReference => typeof(UUID),
|
||||
_ => null
|
||||
};
|
||||
}
|
||||
@@ -19,16 +19,21 @@ public class SerializedObject
|
||||
private Stack<string> _structScope = new();
|
||||
|
||||
private string _structScopeName = "";
|
||||
|
||||
private bool _isStatic;
|
||||
|
||||
private delegate void SerializeMethod(SerializedObject container, string fieldName, object? fieldValue, Type fieldType);
|
||||
|
||||
private static Dictionary<Type, SerializeMethod> _customSerializers = new();
|
||||
|
||||
public UUID Id => _id;
|
||||
|
||||
public bool IsStatic => _isStatic;
|
||||
|
||||
public SerializedObject(IntPtr internalContext, UUID id, Dictionary<object, SerializedObject> serializedClasses)
|
||||
public SerializedObject(IntPtr internalContext, bool isStatic, UUID id, Dictionary<object, SerializedObject> serializedClasses)
|
||||
{
|
||||
_internalContext = internalContext;
|
||||
_isStatic = isStatic;
|
||||
_id = id;
|
||||
_serializedClasses = serializedClasses;
|
||||
}
|
||||
@@ -40,9 +45,9 @@ public class SerializedObject
|
||||
if (_serializedClasses.TryGetValue(o, out context))
|
||||
return (context, false);
|
||||
|
||||
ScriptGlue.Serialization_CreateObject(_internalContext, o.GetType().ToString(), out IntPtr contextPtr, out UUID id);
|
||||
ScriptGlue.Serialization_CreateObject(_internalContext, false, o.GetType().ToString(), out IntPtr contextPtr, out UUID id);
|
||||
|
||||
context = new SerializedObject(contextPtr, id, _serializedClasses);
|
||||
context = new SerializedObject(contextPtr, false, id, _serializedClasses);
|
||||
|
||||
_serializedClasses.Add(o, context);
|
||||
|
||||
@@ -95,16 +100,21 @@ public class SerializedObject
|
||||
|
||||
public void Serialize(Entity entity)
|
||||
{
|
||||
SerializeFields(entity);
|
||||
SerializeInstanceFields(entity);
|
||||
}
|
||||
|
||||
public void Serialize(Type type)
|
||||
{
|
||||
SerializeStaticTypeFields(type);
|
||||
}
|
||||
|
||||
public void SerializeFields(object obj)
|
||||
public void SerializeInstanceFields(object obj)
|
||||
{
|
||||
Type type = obj.GetType();
|
||||
|
||||
foreach (FieldInfo field in type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
|
||||
{
|
||||
if (!EntitySerializer.SerializeField(field))
|
||||
if (!EntitySerializer.SerializeField(field, false))
|
||||
continue;
|
||||
|
||||
object? fieldValue = field.GetValue(obj);
|
||||
@@ -113,6 +123,20 @@ public class SerializedObject
|
||||
SerializeField(field.Name, fieldValue, fieldType);
|
||||
}
|
||||
}
|
||||
|
||||
public void SerializeStaticTypeFields(Type type)
|
||||
{
|
||||
foreach (FieldInfo field in type.GetFields(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public))
|
||||
{
|
||||
if (!EntitySerializer.SerializeField(field, true))
|
||||
continue;
|
||||
|
||||
object? fieldValue = field.GetValue(null);
|
||||
Type fieldType = fieldValue?.GetType() ?? field.FieldType;
|
||||
|
||||
SerializeField(field.Name, fieldValue, fieldType);
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryCustomSerializer(string fieldName, object? fieldValue, Type fieldType)
|
||||
{
|
||||
@@ -285,7 +309,7 @@ public class SerializedObject
|
||||
{
|
||||
PushScope(fieldName);
|
||||
|
||||
SerializeFields(fieldValue);
|
||||
SerializeInstanceFields(fieldValue);
|
||||
|
||||
PopScope();
|
||||
}
|
||||
@@ -312,7 +336,7 @@ public class SerializedObject
|
||||
|
||||
if (newContext)
|
||||
{
|
||||
context.SerializeFields(fieldValue);
|
||||
context.SerializeInstanceFields(fieldValue);
|
||||
}
|
||||
|
||||
AddField(fieldName, SerializationType.ObjectReference, context._id);
|
||||
|
||||
Reference in New Issue
Block a user