TechbloxModdingAPI/GamecraftModdingAPI/Persistence/DeserializeFromDiskEntitiesEnginePatch.cs
2020-05-15 17:42:04 -04:00

88 lines
3.5 KiB
C#

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<byte> ____bytesStream, ref IEntitySerialization ____entitySerializer, bool ____spawnBlocksOnly)
{
if (____spawnBlocksOnly) return; // only run after second deserialization call (when all vanilla stuff is already deserialized)
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")
}
}
}