using System; using System.Text; using System.Reflection; using RobocraftX.Common; using RobocraftX.SaveAndLoad; using Svelto.DataStructures; using Svelto.ECS; using Svelto.ECS.Serialization; using GamecraftModdingAPI.Utility; using HarmonyLib; namespace GamecraftModdingAPI.Persistence { [HarmonyPatch] class SaveGameEnginePatch { private static readonly byte[] frameStart = Encoding.UTF8.GetBytes("\0\0\0GamecraftModdingAPI\0\0\0"); public static void Postfix(ref ISerializationData serializationData, EntitiesDB entitiesDB, IEntitySerialization entitySerializer) { Logging.MetaDebugLog("Running Postfix on SerializeGameToBuffer: serializing custom components..."); if (SerializerManager.GetSerializersCount() == 0) { Logging.MetaDebugLog("Skipping component serialization: no serializers registered!"); return; } serializationData.data.ExpandBy((uint)frameStart.Length); BinaryBufferWriter bbw = new BinaryBufferWriter(serializationData.data.ToArrayFast(out uint buffLen), serializationData.dataPos); uint originalPos = serializationData.dataPos; Logging.MetaDebugLog($"dataPos: {originalPos}"); // Add frame start so it's easier to find GamecraftModdingAPI-serialized components for (int i = 0; i < frameStart.Length; i++) { bbw.Write(frameStart[i]); } Logging.MetaDebugLog($"dataPos (after frame start): {bbw.Position}"); serializationData.data.ExpandBy(4u); bbw.Write((uint)SerializerManager.GetSerializersCount()); string[] serializerKeys = SerializerManager.GetSerializerNames(); for (uint c = 0; c < serializerKeys.Length; c++) { Logging.MetaDebugLog($"dataPos (loop start): {bbw.Position}"); // write component info serializationData.data.ExpandBy(4u + (uint)serializerKeys[c].Length); bbw.Write((uint)serializerKeys[c].Length); Logging.MetaDebugLog($"dataPos (now): {bbw.Position}"); byte[] nameBytes = Encoding.UTF8.GetBytes(serializerKeys[c]); for (int i = 0; i < nameBytes.Length; i++) { bbw.Write(nameBytes[i]); } Logging.MetaDebugLog($"dataPos (now): {bbw.Position}"); serializationData.data.ExpandBy(4u); serializationData.dataPos = bbw.Position + 4u; Logging.MetaDebugLog($"dataPos (now): {bbw.Position}"); Logging.MetaDebugLog($"dataPos (appears to be): {serializationData.dataPos}"); // serialize component IEntitySerializer serializer = SerializerManager.GetSerializer(serializerKeys[c]); if (!serializer.Serialize(ref serializationData, entitiesDB, entitySerializer)) { Logging.MetaDebugLog("Component serialization failed!"); } Logging.MetaDebugLog($"dataPos (now): {bbw.Position}"); bbw.Write((uint)serializationData.dataPos); Logging.MetaDebugLog($"dataPos (now): {bbw.Position}"); bbw = new BinaryBufferWriter(serializationData.data.ToArrayFast(out buffLen), serializationData.dataPos); Logging.MetaDebugLog($"dataPos (loop end): {bbw.Position}"); } serializationData.data.Trim(); Logging.MetaDebugLog($"dataPos (end): {bbw.Position}"); Logging.MetaDebugLog("Serialization complete"); } public static MethodBase TargetMethod() { return typeof(SaveGameEngine).GetMethod("SerializeGameToBuffer"); } } }