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.

212 lines
11KB

  1. using System;
  2. using Svelto.DataStructures;
  3. using Svelto.ECS.Serialization;
  4. namespace Svelto.ECS
  5. {
  6. public partial class EnginesRoot
  7. {
  8. sealed class EntitySerialization : IEntitySerialization
  9. {
  10. public void SerializeEntity(EGID egid, ISerializationData serializationData, int serializationType)
  11. {
  12. var entitiesDb = _enginesRoot._entitiesDB;
  13. //needs to retrieve the meta data associated with the entity
  14. ref var serializableEntityComponent = ref entitiesDb.QueryEntity<SerializableEntityComponent>(egid);
  15. uint descriptorHash = serializableEntityComponent.descriptorHash;
  16. SerializationDescriptorMap serializationDescriptorMap = _enginesRoot._serializationDescriptorMap;
  17. var entityDescriptor = serializationDescriptorMap.GetDescriptorFromHash(descriptorHash);
  18. var entityComponentsToSerialise = entityDescriptor.componentsToSerialize;
  19. var header =
  20. new SerializableEntityHeader(descriptorHash, egid, (byte) entityComponentsToSerialise.Length);
  21. header.Copy(serializationData);
  22. for (int index = 0; index < entityComponentsToSerialise.Length; index++)
  23. {
  24. var entityBuilder = entityComponentsToSerialise[index];
  25. serializationData.BeginNextEntityComponent();
  26. SerializeEntityComponent(egid, entityBuilder, serializationData, serializationType);
  27. }
  28. }
  29. public EntityInitializer DeserializeNewEntity
  30. (EGID egid, ISerializationData serializationData, int serializationType)
  31. {
  32. //todo: SerializableEntityHeader may be needed to be customizable
  33. var serializableEntityHeader = new SerializableEntityHeader(serializationData);
  34. uint descriptorHash = serializableEntityHeader.descriptorHash;
  35. SerializationDescriptorMap serializationDescriptorMap = _enginesRoot._serializationDescriptorMap;
  36. var entityDescriptor = serializationDescriptorMap.GetDescriptorFromHash(descriptorHash);
  37. IDeserializationFactory factory = serializationDescriptorMap.GetSerializationFactory(descriptorHash);
  38. return factory.BuildDeserializedEntity(egid, serializationData, entityDescriptor, serializationType
  39. , this, this._enginesRoot.GenerateEntityFactory()
  40. , _enginesRoot._isDeserializationOnly);
  41. }
  42. public void DeserializeEntity(ISerializationData serializationData, int serializationType)
  43. {
  44. var serializableEntityHeader = new SerializableEntityHeader(serializationData);
  45. EGID egid = serializableEntityHeader.egid;
  46. DeserializeEntityInternal(serializationData, egid, serializableEntityHeader, serializationType);
  47. }
  48. public void DeserializeEntity(EGID egid, ISerializationData serializationData, int serializationType)
  49. {
  50. var serializableEntityHeader = new SerializableEntityHeader(serializationData);
  51. DeserializeEntityInternal(serializationData, egid, serializableEntityHeader, serializationType);
  52. }
  53. public void DeserializeEntityComponents
  54. (ISerializationData serializationData, ISerializableEntityDescriptor entityDescriptor
  55. , ref EntityInitializer initializer, int serializationType)
  56. {
  57. foreach (var serializableEntityBuilder in entityDescriptor.componentsToSerialize)
  58. {
  59. serializationData.BeginNextEntityComponent();
  60. serializableEntityBuilder.Deserialize(serializationData, initializer, serializationType);
  61. }
  62. }
  63. /// <summary>
  64. /// Note this has been left undocumented and forgot over the months. The initial version was obviously
  65. /// wrong, as it wasn't looking for T but only assuming that T was the first component in the entity.
  66. /// It's also weird or at least must be revalidated, the fact that serializationData works only as
  67. /// a tape, so we need to reset datapos in case we do not want to forward the head.
  68. /// </summary>
  69. /// <param name="serializationData"></param>
  70. /// <param name="entityDescriptor"></param>
  71. /// <param name="serializationType"></param>
  72. /// <typeparam name="T"></typeparam>
  73. /// <returns></returns>
  74. public T DeserializeEntityComponent<T>
  75. (ISerializationData serializationData, ISerializableEntityDescriptor entityDescriptor
  76. , int serializationType) where T : unmanaged, IEntityComponent
  77. {
  78. var readPos = serializationData.dataPos;
  79. T entityComponent = default;
  80. foreach (var serializableEntityBuilder in entityDescriptor.componentsToSerialize)
  81. {
  82. if (serializableEntityBuilder is SerializableComponentBuilder<T> entityBuilder)
  83. {
  84. entityBuilder.Deserialize(serializationData, ref entityComponent, serializationType);
  85. break;
  86. }
  87. else
  88. serializationData.dataPos += serializableEntityBuilder.Size(serializationType);
  89. }
  90. serializationData.dataPos = readPos;
  91. return entityComponent;
  92. }
  93. public void DeserializeEntityToSwap(EGID localEgid, EGID toEgid)
  94. {
  95. EntitiesDB entitiesDb = _enginesRoot._entitiesDB;
  96. ref var serializableEntityComponent =
  97. ref entitiesDb.QueryEntity<SerializableEntityComponent>(localEgid);
  98. SerializationDescriptorMap serializationDescriptorMap = _enginesRoot._serializationDescriptorMap;
  99. uint descriptorHash = serializableEntityComponent.descriptorHash;
  100. var entityDescriptor = serializationDescriptorMap.GetDescriptorFromHash(descriptorHash);
  101. var entitySubmitOperation =
  102. new EntitySubmitOperation(EntitySubmitOperationType.Swap, localEgid, toEgid
  103. , entityDescriptor.componentsToBuild);
  104. _enginesRoot.CheckRemoveEntityID(localEgid, entityDescriptor.realType);
  105. _enginesRoot.CheckAddEntityID(toEgid, entityDescriptor.realType);
  106. _enginesRoot.QueueEntitySubmitOperation(entitySubmitOperation);
  107. }
  108. public void DeserializeEntityToDelete(EGID egid)
  109. {
  110. EntitiesDB entitiesDB = _enginesRoot._entitiesDB;
  111. ref var serializableEntityComponent = ref entitiesDB.QueryEntity<SerializableEntityComponent>(egid);
  112. uint descriptorHash = serializableEntityComponent.descriptorHash;
  113. SerializationDescriptorMap serializationDescriptorMap = _enginesRoot._serializationDescriptorMap;
  114. var entityDescriptor = serializationDescriptorMap.GetDescriptorFromHash(descriptorHash);
  115. _enginesRoot.CheckRemoveEntityID(egid, entityDescriptor.realType);
  116. var entitySubmitOperation =
  117. new EntitySubmitOperation(EntitySubmitOperationType.Remove, egid, egid
  118. , entityDescriptor.componentsToBuild);
  119. _enginesRoot.QueueEntitySubmitOperation(entitySubmitOperation);
  120. }
  121. public uint GetHashFromGroup(ExclusiveGroupStruct groupStruct)
  122. {
  123. return GroupHashMap.GetHashFromGroup(groupStruct);
  124. }
  125. public ExclusiveGroupStruct GetGroupFromHash(uint groupHash)
  126. {
  127. return GroupHashMap.GetGroupFromHash(groupHash);
  128. }
  129. public void RegisterSerializationFactory<T>(IDeserializationFactory deserializationFactory)
  130. where T : ISerializableEntityDescriptor, new()
  131. {
  132. SerializationDescriptorMap serializationDescriptorMap = _enginesRoot._serializationDescriptorMap;
  133. serializationDescriptorMap.RegisterSerializationFactory<T>(deserializationFactory);
  134. }
  135. internal EntitySerialization(EnginesRoot enginesRoot) { _enginesRoot = enginesRoot; }
  136. void SerializeEntityComponent
  137. (EGID entityGID, ISerializableComponentBuilder componentBuilder, ISerializationData serializationData
  138. , int serializationType)
  139. {
  140. ExclusiveGroupStruct groupId = entityGID.groupID;
  141. Type entityType = componentBuilder.GetEntityComponentType();
  142. if (!_enginesRoot._entitiesDB.UnsafeQueryEntityDictionary(groupId, entityType, out var safeDictionary))
  143. {
  144. throw new Exception("Entity Serialization failed");
  145. }
  146. componentBuilder.Serialize(entityGID.entityID, safeDictionary, serializationData, serializationType);
  147. }
  148. void DeserializeEntityInternal
  149. (ISerializationData serializationData, EGID egid, SerializableEntityHeader serializableEntityHeader
  150. , int serializationType)
  151. {
  152. SerializationDescriptorMap descriptorMap = _enginesRoot._serializationDescriptorMap;
  153. var entityDescriptor = descriptorMap.GetDescriptorFromHash(serializableEntityHeader.descriptorHash);
  154. if (_enginesRoot._groupEntityComponentsDB.TryGetValue(egid.groupID, out var entitiesInGroupPerType)
  155. == false)
  156. throw new Exception("Entity Serialization failed");
  157. foreach (var serializableEntityBuilder in entityDescriptor.componentsToSerialize)
  158. {
  159. entitiesInGroupPerType.TryGetValue(
  160. new RefWrapperType(serializableEntityBuilder.GetEntityComponentType()), out var safeDictionary);
  161. serializationData.BeginNextEntityComponent();
  162. serializableEntityBuilder.Deserialize(egid.entityID, safeDictionary, serializationData
  163. , serializationType);
  164. }
  165. }
  166. readonly EnginesRoot _enginesRoot;
  167. }
  168. public IEntitySerialization GenerateEntitySerializer() { return new EntitySerialization(this); }
  169. readonly bool _isDeserializationOnly;
  170. }
  171. }