Mirror of Svelto.ECS because we're a fan of it
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.

198 lines
8.8KB

  1. using System;
  2. using Svelto.Common;
  3. using Svelto.ECS.Internal;
  4. using Svelto.ECS.Serialization;
  5. namespace Svelto.ECS
  6. {
  7. //todo: this should not be at framework level
  8. public enum SerializationType
  9. {
  10. Network,
  11. Storage,
  12. Length
  13. }
  14. public partial class EnginesRoot
  15. {
  16. readonly bool _isDeserializationOnly;
  17. sealed class EntitySerialization : IEntitySerialization
  18. {
  19. public void SerializeEntity(EGID egid, ISerializationData serializationData,
  20. SerializationType serializationType)
  21. {
  22. var entitiesDb = _enginesRoot._entitiesDB;
  23. //needs to retrieve the meta data associated with the entity
  24. ref var serializableEntityStruct = ref entitiesDb.QueryEntity<SerializableEntityStruct>(egid);
  25. uint descriptorHash = serializableEntityStruct.descriptorHash;
  26. SerializationDescriptorMap serializationDescriptorMap = _enginesRoot.serializationDescriptorMap;
  27. var entityDescriptor = serializationDescriptorMap.GetDescriptorFromHash(descriptorHash);
  28. var entityStructsToSerialise = entityDescriptor.entitiesToSerialize;
  29. var header =
  30. new SerializableEntityHeader(descriptorHash, egid, (byte) entityStructsToSerialise.Length);
  31. header.Copy(serializationData);
  32. for (int index = 0; index < entityStructsToSerialise.Length; index++)
  33. {
  34. var entityBuilder = entityStructsToSerialise[index];
  35. serializationData.BeginNextEntityStruct();
  36. SerializeEntityStruct(egid, entityBuilder, serializationData, serializationType);
  37. }
  38. }
  39. public EntityStructInitializer DeserializeNewEntity(EGID egid, ISerializationData serializationData,
  40. SerializationType serializationType)
  41. {
  42. //todo: SerializableEntityHeader may be needed to be customizable
  43. var serializableEntityHeader = new SerializableEntityHeader(serializationData);
  44. uint descriptorHash = serializableEntityHeader.descriptorHash;
  45. SerializationDescriptorMap serializationDescriptorMap = _enginesRoot.serializationDescriptorMap;
  46. var factory = serializationDescriptorMap.GetSerializationFactory(descriptorHash);
  47. var entityDescriptor = serializationDescriptorMap.GetDescriptorFromHash(descriptorHash);
  48. //default factory
  49. if (factory == null)
  50. {
  51. var initializer = _enginesRoot.BuildEntity(egid,
  52. _enginesRoot._isDeserializationOnly
  53. ? entityDescriptor.entitiesToSerialize
  54. : entityDescriptor.entitiesToBuild);
  55. DeserializeEntityStructs(serializationData, entityDescriptor, ref initializer, serializationType);
  56. return initializer;
  57. }
  58. //custom factory
  59. return factory.BuildDeserializedEntity(egid, serializationData, entityDescriptor, serializationType,
  60. this);
  61. }
  62. public void DeserializeEntity(ISerializationData serializationData, SerializationType serializationType)
  63. {
  64. var serializableEntityHeader = new SerializableEntityHeader(serializationData);
  65. EGID egid = serializableEntityHeader.egid;
  66. DeserializeEntityInternal(serializationData, egid, serializableEntityHeader, serializationType);
  67. }
  68. public void DeserializeEntity(EGID egid, ISerializationData serializationData,
  69. SerializationType serializationType)
  70. {
  71. var serializableEntityHeader = new SerializableEntityHeader(serializationData);
  72. DeserializeEntityInternal(serializationData, egid, serializableEntityHeader, serializationType);
  73. }
  74. public void DeserializeEntityStructs(ISerializationData serializationData,
  75. ISerializableEntityDescriptor entityDescriptor,
  76. ref EntityStructInitializer initializer, SerializationType serializationType)
  77. {
  78. foreach (var serializableEntityBuilder in entityDescriptor.entitiesToSerialize)
  79. {
  80. serializationData.BeginNextEntityStruct();
  81. serializableEntityBuilder.Deserialize(serializationData, initializer, serializationType);
  82. }
  83. }
  84. public void DeserializeEntityToSwap(EGID localEgid, EGID toEgid)
  85. {
  86. EntitiesDB entitiesDb = _enginesRoot._entitiesDB;
  87. ref var serializableEntityStruct = ref entitiesDb.QueryEntity<SerializableEntityStruct>(localEgid);
  88. SerializationDescriptorMap serializationDescriptorMap = _enginesRoot.serializationDescriptorMap;
  89. uint descriptorHash = serializableEntityStruct.descriptorHash;
  90. var entityDescriptor = serializationDescriptorMap.GetDescriptorFromHash(descriptorHash);
  91. var entitySubmitOperation = new EntitySubmitOperation(
  92. EntitySubmitOperationType.Swap,
  93. localEgid,
  94. toEgid,
  95. entityDescriptor.entitiesToBuild);
  96. _enginesRoot.CheckRemoveEntityID(localEgid);
  97. _enginesRoot.CheckAddEntityID(toEgid);
  98. _enginesRoot.QueueEntitySubmitOperation(entitySubmitOperation);
  99. }
  100. public void DeserializeEntityToDelete(EGID egid)
  101. {
  102. EntitiesDB entitiesDB = _enginesRoot._entitiesDB;
  103. ref var serializableEntityStruct = ref entitiesDB.QueryEntity<SerializableEntityStruct>(egid);
  104. uint descriptorHash = serializableEntityStruct.descriptorHash;
  105. SerializationDescriptorMap serializationDescriptorMap = _enginesRoot.serializationDescriptorMap;
  106. var entityDescriptor = serializationDescriptorMap.GetDescriptorFromHash(descriptorHash);
  107. _enginesRoot.CheckRemoveEntityID(egid);
  108. var entitySubmitOperation = new EntitySubmitOperation(
  109. EntitySubmitOperationType.Remove,
  110. egid,
  111. egid,
  112. entityDescriptor.entitiesToBuild);
  113. _enginesRoot.QueueEntitySubmitOperation(entitySubmitOperation);
  114. }
  115. public void RegisterSerializationFactory<T>(IDeserializationFactory deserializationFactory)
  116. where T : ISerializableEntityDescriptor, new()
  117. {
  118. SerializationDescriptorMap serializationDescriptorMap = _enginesRoot.serializationDescriptorMap;
  119. serializationDescriptorMap.RegisterSerializationFactory<T>(deserializationFactory);
  120. }
  121. internal EntitySerialization(EnginesRoot enginesRoot)
  122. {
  123. _enginesRoot = enginesRoot;
  124. }
  125. void SerializeEntityStruct(EGID entityGID, ISerializableEntityBuilder entityBuilder,
  126. ISerializationData serializationData, SerializationType serializationType)
  127. {
  128. uint groupId = entityGID.groupID;
  129. Type entityType = entityBuilder.GetEntityType();
  130. if (!_enginesRoot._entitiesDB.UnsafeQueryEntityDictionary(groupId, entityType,
  131. out var safeDictionary))
  132. {
  133. throw new Exception("Entity Serialization failed");
  134. }
  135. entityBuilder.Serialize(entityGID.entityID, safeDictionary, serializationData, serializationType);
  136. }
  137. void DeserializeEntityInternal(ISerializationData serializationData, EGID egid,
  138. SerializableEntityHeader serializableEntityHeader, SerializationType serializationType)
  139. {
  140. SerializationDescriptorMap descriptorMap = _enginesRoot.serializationDescriptorMap;
  141. var entityDescriptor = descriptorMap.GetDescriptorFromHash(serializableEntityHeader.descriptorHash);
  142. foreach (var serializableEntityBuilder in entityDescriptor.entitiesToSerialize)
  143. {
  144. _enginesRoot._entitiesDB.UnsafeQueryEntityDictionary(egid.groupID,
  145. serializableEntityBuilder.GetEntityType(), out var safeDictionary);
  146. serializationData.BeginNextEntityStruct();
  147. serializableEntityBuilder.Deserialize(egid.entityID, safeDictionary, serializationData,
  148. serializationType);
  149. }
  150. }
  151. readonly EnginesRoot _enginesRoot;
  152. }
  153. public IEntitySerialization GenerateEntitySerializer()
  154. {
  155. return new EntitySerialization(this);
  156. }
  157. }
  158. }