using System; using System.Text; using System.Reflection; using RobocraftX.Common; using Svelto.DataStructures; using Svelto.ECS; using Svelto.ECS.Serialization; using HarmonyLib; using GamecraftModdingAPI.Utility; namespace GamecraftModdingAPI.Persistence { [HarmonyPatch] class DeserializeFromDiskEntitiesEnginePatch { internal static EntitiesDB entitiesDB = null; private static readonly byte[] frameStart = Encoding.UTF8.GetBytes("\0\0\0GamecraftModdingAPI\0\0\0"); public static void Prefix(ref ISerializationData ____serializationData, ref FasterList ____bytesStream, ref IEntitySerialization ____entitySerializer, bool ____spawnBlocksOnly) { if (____spawnBlocksOnly) return; // only run after second deserialization call (when all vanilla stuff is already deserialized) if (SaveAndLoadCompositionRootPatch.currentEnginesRoot == null) return; SerializerManager.RegisterSerializers(SaveAndLoadCompositionRootPatch.currentEnginesRoot); uint originalPos = ____serializationData.dataPos; Logging.MetaDebugLog($"dataPos: {originalPos}"); BinaryBufferReader bbr = new BinaryBufferReader(____bytesStream.ToArrayFast(out uint count), ____serializationData.dataPos); byte[] frameBuffer = new byte[frameStart.Length]; Logging.MetaDebugLog($"serial data count: {____serializationData.data.count} capacity: {____serializationData.data.capacity}"); int i = 0; // match frame start while (frameBuffer != frameStart && bbr.Position < count-frameStart.Length) { i = 0; frameBuffer[0] = bbr.ReadByte(); while (frameBuffer[i] == frameStart[i] && bbr.Position < count - frameStart.Length + i) { i++; if (i == frameStart.Length) break; frameBuffer[i] = bbr.ReadByte(); } if (i == frameStart.Length) break; } // abort if at end of file if (bbr.Position >= count - frameStart.Length) { Logging.MetaLog("Skipping deserialization (no frame found)"); return; } //____serializationData.dataPos = bbr.Position; Logging.MetaDebugLog($"dataPos (after frame): {bbr.Position}"); uint customComponentsCount = bbr.ReadUint(); for (uint c = 0; c < customComponentsCount; c++) { // determine component from info uint nameLength = bbr.ReadUint(); byte[] nameBytes = new byte[nameLength]; bbr.ReadBytes(nameBytes, nameLength); string name = Encoding.UTF8.GetString(nameBytes); Logging.MetaDebugLog($"Component name: {name} (len: {nameLength})"); uint componentEnd = bbr.ReadUint(); ____serializationData.dataPos = bbr.Position; if (SerializerManager.ExistsSerializer(name)) { // deserialize component IEntitySerializer serial = SerializerManager.GetSerializer(name); if (!serial.Deserialize(ref ____serializationData, ____entitySerializer)) { Logging.MetaDebugLog("Component deserialization failed!"); } } else { Logging.MetaDebugLog("Skipping component deserialization: not found!"); } bbr = new BinaryBufferReader(____bytesStream.ToArrayFast(out count), componentEnd); } ____serializationData.dataPos = originalPos; // change back to original end point (just in case) Logging.MetaDebugLog("Deserialization complete"); } public static MethodBase TargetMethod() { return AccessTools.Method("RobocraftX.SaveAndLoad.DeserializeFromDiskEntitiesEngine:LoadingFinished");//AccessTools.TypeByName("RobocraftX.SaveAndLoad.DeserializeFromDiskEntities") } } }