From 1045ad9d24c35cead16da449ec41ace7929c4fcb Mon Sep 17 00:00:00 2001 From: Kamron Batman <3953314+kamronbatman@users.noreply.github.com> Date: Tue, 10 Sep 2024 22:48:50 -0700 Subject: [PATCH] Adds generic serialization support to entity serialization --- .../Serialization/GenericEntityPersistence.cs | 76 ++++++++++++++----- 1 file changed, 59 insertions(+), 17 deletions(-) diff --git a/Projects/Server/Serialization/GenericEntityPersistence.cs b/Projects/Server/Serialization/GenericEntityPersistence.cs index 0a8331180..91f8ca955 100644 --- a/Projects/Server/Serialization/GenericEntityPersistence.cs +++ b/Projects/Server/Serialization/GenericEntityPersistence.cs @@ -31,14 +31,13 @@ public interface IGenericEntityPersistence public void DeserializeIndexes(string savePath, Dictionary typesDb); } -public class GenericEntityPersistence : Persistence, IGenericEntityPersistence where T : class, ISerializable +public class GenericEntityPersistence : GenericPersistence, IGenericEntityPersistence where T : class, ISerializable { private static readonly ILogger logger = LogFactory.GetLogger(typeof(GenericEntityPersistence)); // Support legacy split file serialization private static Dictionary>> _entities; - private readonly string _name; private readonly Serial _minSerial; private readonly Serial _maxSerial; private Serial _lastEntitySerial; @@ -56,9 +55,8 @@ public GenericEntityPersistence(string name, int priority, uint minSerial, uint { } - public GenericEntityPersistence(string name, int priority, Serial minSerial, Serial maxSerial) : base(priority) + public GenericEntityPersistence(string name, int priority, Serial minSerial, Serial maxSerial) : base(name, priority) { - _name = name; _minSerial = minSerial; _maxSerial = maxSerial; _lastEntitySerial = minSerial - 1; @@ -67,18 +65,40 @@ public GenericEntityPersistence(string name, int priority, Serial minSerial, Ser public override void WriteSnapshot(string savePath, HashSet typeSet) { - var dir = Path.Combine(savePath, _name); + var dir = Path.Combine(savePath, Name); PathUtility.EnsureDirectory(dir); var threads = World._threadWorkers; - using var binFs = new FileStream(Path.Combine(dir, $"{_name}.bin"), FileMode.Create, FileAccess.Write, FileShare.None); - using var idxFs = new FileStream(Path.Combine(dir, $"{_name}.idx"), FileMode.Create); + using var binFs = new FileStream(Path.Combine(dir, $"{Name}.bin"), FileMode.Create, FileAccess.Write, FileShare.None); + using var idxFs = new FileStream(Path.Combine(dir, $"{Name}.idx"), FileMode.Create); using var idx = new MemoryMapFileWriter(idxFs, 1024 * 1024, typeSet); // 1MB + var binPosition = 0L; + + // Support for non-entity generic serialization. + if (SerializedLength > 0) + { + try + { + binFs.Write(threads[SerializedThread].GetHeap(SerializedPosition, SerializedLength)); + } + catch (Exception error) + { + logger.Error( + error, + "Error writing entity: (Thread: {Thread} - {Start} {Length})", + SerializedThread, + SerializedPosition, + SerializedLength + ); + } + + binPosition += SerializedLength; + } + idx.Write(3); // Version idx.Write(EntitiesBySerial.Values.Count); - var binPosition = 0L; foreach (var e in EntitiesBySerial.Values) { @@ -98,7 +118,14 @@ public override void WriteSnapshot(string savePath, HashSet typeSet) } catch (Exception error) { - Console.WriteLine("Error writing entity: {0} (Thread: {1} - {2} {3})\n{4}", e, thread, heapStart, heapLength, error); + logger.Error( + error, + "Error writing entity: {Entity} (Thread: {Thread} - {Start} {Length})", + e, + thread, + heapStart, + heapLength + ); } binPosition += heapLength; @@ -111,6 +138,8 @@ public override void Serialize() { World.PushToCache(entity); } + + World.PushToCache(this); } private static ConstructorInfo GetConstructorFor(string typeName, Type t, Type[] constructorTypes) @@ -149,7 +178,7 @@ private static ConstructorInfo GetConstructorFor(string typeName, Type t, Type[] */ private unsafe Dictionary ReadTypes(string savePath) { - string typesPath = Path.Combine(savePath, _name, $"{_name}.tdb"); + string typesPath = Path.Combine(savePath, Name, $"{Name}.tdb"); if (!File.Exists(typesPath)) { return null; @@ -180,7 +209,7 @@ private unsafe Dictionary ReadTypes(string savePath) public virtual void DeserializeIndexes(string savePath, Dictionary typesDb) { - string indexPath = Path.Combine(savePath, _name, $"{_name}.idx"); + string indexPath = Path.Combine(savePath, Name, $"{Name}.idx"); _entities ??= []; @@ -199,7 +228,7 @@ private void TryDeserializeSplitFileIndexes(string savePath, Dictionary typesDb) { - string dataPath = Path.Combine(savePath, _name, $"{_name}.bin"); + string dataPath = Path.Combine(savePath, Name, $"{Name}.bin"); var fi = new FileInfo(dataPath); if (!fi.Exists) @@ -320,7 +349,7 @@ public override void Deserialize(string savePath, Dictionary type _entities = null; } - private static unsafe void InternalDeserialize(string filePath, int index, Dictionary typesDb) + private unsafe void InternalDeserialize(string filePath, int index, Dictionary typesDb) { using var mmf = MemoryMappedFile.CreateFromFile(filePath, FileMode.Open); using var accessor = mmf.CreateViewStream(); @@ -328,6 +357,9 @@ private static unsafe void InternalDeserialize(string filePath, int index, Dicti byte* ptr = null; accessor.SafeMemoryMappedViewHandle.AcquirePointer(ref ptr); UnmanagedDataReader dataReader = new UnmanagedDataReader(ptr, accessor.Length, typesDb); + + Deserialize(dataReader); + var deleteAllFailures = false; foreach (var entry in _entities[index]) @@ -398,15 +430,25 @@ private void TryDeserializeMultithread(string savePath, Dictionary