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.

90 lines
3.7KB

  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 TechbloxModdingAPI.Utility;
  10. namespace TechbloxModdingAPI.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\0TechbloxModdingAPI\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. if (SaveAndLoadCompositionRootPatch.currentEnginesRoot == null) return;
  21. SerializerManager.RegisterSerializers(SaveAndLoadCompositionRootPatch.currentEnginesRoot);
  22. uint originalPos = ____serializationData.dataPos;
  23. Logging.MetaDebugLog($"dataPos: {originalPos}");
  24. BinaryBufferReader bbr = new BinaryBufferReader(____bytesStream.ToArrayFast(out uint count), ____serializationData.dataPos);
  25. byte[] frameBuffer = new byte[frameStart.Length];
  26. Logging.MetaDebugLog($"serial data count: {____serializationData.data.count} capacity: {____serializationData.data.capacity}");
  27. int i = 0;
  28. // match frame start
  29. while (frameBuffer != frameStart && bbr.Position < count-frameStart.Length)
  30. {
  31. i = 0;
  32. frameBuffer[0] = bbr.ReadByte();
  33. while (frameBuffer[i] == frameStart[i] && bbr.Position < count - frameStart.Length + i)
  34. {
  35. i++;
  36. if (i == frameStart.Length) break;
  37. frameBuffer[i] = bbr.ReadByte();
  38. }
  39. if (i == frameStart.Length) break;
  40. }
  41. // abort if at end of file
  42. if (bbr.Position >= count - frameStart.Length)
  43. {
  44. Logging.MetaLog("Skipping deserialization (no frame found)");
  45. return;
  46. }
  47. //____serializationData.dataPos = bbr.Position;
  48. Logging.MetaDebugLog($"dataPos (after frame): {bbr.Position}");
  49. uint customComponentsCount = bbr.ReadUint();
  50. for (uint c = 0; c < customComponentsCount; c++)
  51. {
  52. // determine component from info
  53. uint nameLength = bbr.ReadUint();
  54. byte[] nameBytes = new byte[nameLength];
  55. bbr.ReadBytes(nameBytes, nameLength);
  56. string name = Encoding.UTF8.GetString(nameBytes);
  57. Logging.MetaDebugLog($"Component name: {name} (len: {nameLength})");
  58. uint componentEnd = bbr.ReadUint();
  59. ____serializationData.dataPos = bbr.Position;
  60. if (SerializerManager.ExistsSerializer(name))
  61. {
  62. // deserialize component
  63. IEntitySerializer serial = SerializerManager.GetSerializer(name);
  64. if (!serial.Deserialize(ref ____serializationData, ____entitySerializer))
  65. {
  66. Logging.MetaDebugLog("Component deserialization failed!");
  67. }
  68. }
  69. else
  70. {
  71. Logging.MetaDebugLog("Skipping component deserialization: not found!");
  72. }
  73. bbr = new BinaryBufferReader(____bytesStream.ToArrayFast(out count), componentEnd);
  74. }
  75. ____serializationData.dataPos = originalPos; // change back to original end point (just in case)
  76. Logging.MetaDebugLog("Deserialization complete");
  77. }
  78. public static MethodBase TargetMethod()
  79. {
  80. return AccessTools.Method("RobocraftX.SaveAndLoad.DeserializeFromDiskEntitiesEngine:LoadingFinished");//AccessTools.TypeByName("RobocraftX.SaveAndLoad.DeserializeFromDiskEntities")
  81. }
  82. }
  83. }