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.

EnginesRoot.GenericEntitySerialization.cs 8.8KB

Svelto.ECS 2.9 changes (random order of importance): New Serialization framework more thorough disposing of the EnginesRoot an EnginesRoot reference should never be held, unless it’s a weak reference. The code changed to stick to this rule IReactOnAddAndRemove callbacks are now guaranteed to be called after all the entity structs generated by the same entity have been added and before any is removed. both functions pass the EGID of the analysing entity by parameter now, so that the entity struct won’t need to implement INeedEGID for this sole purpose. The IReactOnSwap MovedFrom method has been removed, it is now redundant. Entities built or removed during the IReactOnAddAndRemove callbacks are now added and removed immediately and not on the next submission like used to happen. This avoid some awkward checks that were previously needed inside engines. EntityStreams can get (optionally) the EGID of the entity published, so that the EntityStruct won’t need an INeedEGID for this sole purpose. Groups are not trimmed anymore when they are emptied to avoid allocations. Removed a bunch of run-time allocations that weren’t supposed to happen in Release and/or when the Profile define is used in editor (for debugging reasons Svelto.ECS may need to use strings at run-time, but Svelto.ECS is allocation zero in Release and when the Profile keyword is used) A improved the DynamicEntityDescriptor and ExtendibleEntityDescriptor code and more notably, introduced the new method ExtendedWith<> to facilitate the writing of modular and reusable entity descriptors. Several minor code design improvements/optimisations
4 years ago
4 years ago
Svelto.ECS 2.9 changes (random order of importance): New Serialization framework more thorough disposing of the EnginesRoot an EnginesRoot reference should never be held, unless it’s a weak reference. The code changed to stick to this rule IReactOnAddAndRemove callbacks are now guaranteed to be called after all the entity structs generated by the same entity have been added and before any is removed. both functions pass the EGID of the analysing entity by parameter now, so that the entity struct won’t need to implement INeedEGID for this sole purpose. The IReactOnSwap MovedFrom method has been removed, it is now redundant. Entities built or removed during the IReactOnAddAndRemove callbacks are now added and removed immediately and not on the next submission like used to happen. This avoid some awkward checks that were previously needed inside engines. EntityStreams can get (optionally) the EGID of the entity published, so that the EntityStruct won’t need an INeedEGID for this sole purpose. Groups are not trimmed anymore when they are emptied to avoid allocations. Removed a bunch of run-time allocations that weren’t supposed to happen in Release and/or when the Profile define is used in editor (for debugging reasons Svelto.ECS may need to use strings at run-time, but Svelto.ECS is allocation zero in Release and when the Profile keyword is used) A improved the DynamicEntityDescriptor and ExtendibleEntityDescriptor code and more notably, introduced the new method ExtendedWith<> to facilitate the writing of modular and reusable entity descriptors. Several minor code design improvements/optimisations
4 years ago
4 years ago
Svelto.ECS 2.9 changes (random order of importance): New Serialization framework more thorough disposing of the EnginesRoot an EnginesRoot reference should never be held, unless it’s a weak reference. The code changed to stick to this rule IReactOnAddAndRemove callbacks are now guaranteed to be called after all the entity structs generated by the same entity have been added and before any is removed. both functions pass the EGID of the analysing entity by parameter now, so that the entity struct won’t need to implement INeedEGID for this sole purpose. The IReactOnSwap MovedFrom method has been removed, it is now redundant. Entities built or removed during the IReactOnAddAndRemove callbacks are now added and removed immediately and not on the next submission like used to happen. This avoid some awkward checks that were previously needed inside engines. EntityStreams can get (optionally) the EGID of the entity published, so that the EntityStruct won’t need an INeedEGID for this sole purpose. Groups are not trimmed anymore when they are emptied to avoid allocations. Removed a bunch of run-time allocations that weren’t supposed to happen in Release and/or when the Profile define is used in editor (for debugging reasons Svelto.ECS may need to use strings at run-time, but Svelto.ECS is allocation zero in Release and when the Profile keyword is used) A improved the DynamicEntityDescriptor and ExtendibleEntityDescriptor code and more notably, introduced the new method ExtendedWith<> to facilitate the writing of modular and reusable entity descriptors. Several minor code design improvements/optimisations
4 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  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. }