diff --git a/Projects/Server/Serialization/GenericPersistence.cs b/Projects/Server/Serialization/GenericPersistence.cs index fdc4ec321..b5f399541 100644 --- a/Projects/Server/Serialization/GenericPersistence.cs +++ b/Projects/Server/Serialization/GenericPersistence.cs @@ -20,35 +20,64 @@ namespace Server { public static class GenericPersistence { - public static void Serialize(Action serializer) => serializer(new BufferWriter(true)); - - public static void WriteSnapshot(string path, Action serializer) + public static void Register( + string name, + Action serializer, + Action deserializer + ) { - AssemblyHandler.EnsureDirectory(Path.GetDirectoryName(path)); + BufferWriter saveBuffer = null; - using var fs = new FileStream(path, FileMode.Open, FileAccess.Write, FileShare.None); - serializer(new BinaryFileWriter(fs, true)); - } - - public static void Deserialize(string path, Action deserializer, bool ensure = true) - { - AssemblyHandler.EnsureDirectory(Path.GetDirectoryName(path)); - - if (!File.Exists(path)) + void Serialize() { - if (ensure) - { - new FileInfo(path).Create().Close(); - } + saveBuffer ??= new BufferWriter(true); + saveBuffer.Seek(0, SeekOrigin.Begin); - return; + serializer(saveBuffer); } - using FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read); - // TODO: Support files larger than 2GB - var buffer = GC.AllocateUninitializedArray((int)fs.Length); + void WriterSnapshot(string savePath) + { + var path = Path.Combine(savePath, name); - deserializer(new BufferReader(buffer)); + AssemblyHandler.EnsureDirectory(path); + + string binPath = Path.Combine(path, $"{name}.bin"); + using var bin = new BinaryFileWriter(binPath, true); + + saveBuffer!.Resize((int)saveBuffer.Position); + bin.Write(saveBuffer.Buffer); + } + + void Deserialize(string savePath) + { + var path = Path.Combine(savePath, name); + + AssemblyHandler.EnsureDirectory(path); + + string binPath = Path.Combine(path, $"{name}.bin"); + + if (!File.Exists(binPath)) + { + return; + } + + try + { + using FileStream bin = new FileStream(binPath, FileMode.Open, FileAccess.Read, FileShare.Read); + var br = new BufferReader(GC.AllocateUninitializedArray((int)bin.Length)); + deserializer(br); + } + catch (Exception e) + { + Utility.PushColor(ConsoleColor.Red); + Persistence.WriteConsoleLine($"***** Bad deserialize of {name} *****"); + Persistence.WriteConsoleLine(e.ToString()); + Utility.PopColor(); + } + } + + Persistence.Register(Serialize, WriterSnapshot, Deserialize); } } } diff --git a/Projects/Server/World/EntityPersistence.cs b/Projects/Server/World/EntityPersistence.cs index 8899b6661..48fe307b2 100644 --- a/Projects/Server/World/EntityPersistence.cs +++ b/Projects/Server/World/EntityPersistence.cs @@ -276,10 +276,12 @@ namespace Server private static void SerializeTo(this ISerializable entity, IGenericWriter writer) { var saveBuffer = entity.SaveBuffer; - writer.Write(saveBuffer.Buffer.AsSpan(0, (int)saveBuffer.Position)); - // Resize to exact buffer size - entity.SaveBuffer.Resize((int)entity.SaveBuffer.Position); + // Resize to the exact size + saveBuffer.Resize((int)saveBuffer.Position); + + // Write that amount + writer.Write(saveBuffer.Buffer); } } }