A stable modding interface between Techblox and mods https://mod.exmods.org/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

88 lines
3.5KB

  1. using System;
  2. using System.Text;
  3. using System.Reflection;
  4. using RobocraftX.Common;
  5. using Svelto.DataStructures;
  6. using Svelto.ECS;
  7. using Svelto.ECS.Serialization;
  8. using HarmonyLib;
  9. using GamecraftModdingAPI.Utility;
  10. namespace GamecraftModdingAPI.Persistence
  11. {
  12. [HarmonyPatch]
  13. class DeserializeFromDiskEntitiesEnginePatch
  14. {
  15. internal static EntitiesDB entitiesDB = null;
  16. private static readonly byte[] frameStart = Encoding.UTF8.GetBytes("\0\0\0GamecraftModdingAPI\0\0\0");
  17. public static void Prefix(ref ISerializationData ____serializationData, ref FasterList<byte> ____bytesStream, ref IEntitySerialization ____entitySerializer, bool ____spawnBlocksOnly)
  18. {
  19. if (____spawnBlocksOnly) return; // only run after second deserialization call (when all vanilla stuff is already deserialized)
  20. uint originalPos = ____serializationData.dataPos;
  21. Logging.MetaDebugLog($"dataPos: {originalPos}");
  22. BinaryBufferReader bbr = new BinaryBufferReader(____bytesStream.ToArrayFast(out uint count), ____serializationData.dataPos);
  23. byte[] frameBuffer = new byte[frameStart.Length];
  24. Logging.MetaDebugLog($"serial data count: {____serializationData.data.count} capacity: {____serializationData.data.capacity}");
  25. int i = 0;
  26. // match frame start
  27. while (frameBuffer != frameStart && bbr.Position < count-frameStart.Length)
  28. {
  29. i = 0;
  30. frameBuffer[0] = bbr.ReadByte();
  31. while (frameBuffer[i] == frameStart[i] && bbr.Position < count - frameStart.Length + i)
  32. {
  33. i++;
  34. if (i == frameStart.Length) break;
  35. frameBuffer[i] = bbr.ReadByte();
  36. }
  37. if (i == frameStart.Length) break;
  38. }
  39. // abort if at end of file
  40. if (bbr.Position >= count - frameStart.Length)
  41. {
  42. Logging.MetaLog("Skipping deserialization (no frame found)");
  43. return;
  44. }
  45. //____serializationData.dataPos = bbr.Position;
  46. Logging.MetaDebugLog($"dataPos (after frame): {bbr.Position}");
  47. uint customComponentsCount = bbr.ReadUint();
  48. for (uint c = 0; c < customComponentsCount; c++)
  49. {
  50. // determine component from info
  51. uint nameLength = bbr.ReadUint();
  52. byte[] nameBytes = new byte[nameLength];
  53. bbr.ReadBytes(nameBytes, nameLength);
  54. string name = Encoding.UTF8.GetString(nameBytes);
  55. Logging.MetaDebugLog($"Component name: {name} (len: {nameLength})");
  56. uint componentEnd = bbr.ReadUint();
  57. ____serializationData.dataPos = bbr.Position;
  58. if (SerializerManager.ExistsSerializer(name))
  59. {
  60. // deserialize component
  61. IEntitySerializer serial = SerializerManager.GetSerializer(name);
  62. if (!serial.Deserialize(ref ____serializationData, ____entitySerializer))
  63. {
  64. Logging.MetaDebugLog("Component deserialization failed!");
  65. }
  66. }
  67. else
  68. {
  69. Logging.MetaDebugLog("Skipping component deserialization: not found!");
  70. }
  71. bbr = new BinaryBufferReader(____bytesStream.ToArrayFast(out count), componentEnd);
  72. }
  73. ____serializationData.dataPos = originalPos; // change back to original end point (just in case)
  74. Logging.MetaDebugLog("Deserialization complete");
  75. }
  76. public static MethodBase TargetMethod()
  77. {
  78. return AccessTools.Method("RobocraftX.SaveAndLoad.DeserializeFromDiskEntitiesEngine:LoadingFinished");//AccessTools.TypeByName("RobocraftX.SaveAndLoad.DeserializeFromDiskEntities")
  79. }
  80. }
  81. }