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.

110 lines
4.4KB

  1. using System;
  2. using System.Reflection;
  3. using System.Text;
  4. using Svelto.DataStructures;
  5. using Svelto.Utilities;
  6. namespace Svelto.ECS.Serialization
  7. {
  8. public static class DesignatedHash
  9. {
  10. public static readonly Func<byte[], uint> Hash = Murmur3.MurmurHash3_x86_32;
  11. }
  12. public abstract class SerializableEntityDescriptor<TType> : ISerializableEntityDescriptor
  13. where TType : IEntityDescriptor, new()
  14. {
  15. static SerializableEntityDescriptor()
  16. {
  17. IComponentBuilder[] defaultEntities = EntityDescriptorTemplate<TType>.descriptor.componentsToBuild;
  18. var hashNameAttribute = Type.GetCustomAttribute<HashNameAttribute>();
  19. if (hashNameAttribute == null)
  20. {
  21. throw new Exception(
  22. "HashName attribute not found on the serializable type ".FastConcat(Type.FullName));
  23. }
  24. Hash = DesignatedHash.Hash(Encoding.ASCII.GetBytes(hashNameAttribute._name));
  25. var (index, dynamicIndex) = SetupSpecialEntityComponent(defaultEntities, out ComponentsToBuild);
  26. if (index == -1)
  27. {
  28. index = ComponentsToBuild.Length - 1;
  29. }
  30. // Stores the hash of this EntityDescriptor
  31. ComponentsToBuild[index] = new ComponentBuilder<SerializableEntityComponent>(new SerializableEntityComponent
  32. {
  33. descriptorHash = Hash
  34. });
  35. // If the current serializable is an ExtendibleDescriptor, I have to update it.
  36. if (dynamicIndex != -1)
  37. {
  38. ComponentsToBuild[dynamicIndex] = new ComponentBuilder<EntityInfoComponent>(new EntityInfoComponent
  39. {
  40. componentsToBuild = ComponentsToBuild
  41. });
  42. }
  43. /////
  44. var entitiesToSerialize = new FasterList<ISerializableComponentBuilder>();
  45. EntityComponentsToSerializeMap = new FasterDictionary<RefWrapperType, ISerializableComponentBuilder>();
  46. foreach (IComponentBuilder e in defaultEntities)
  47. {
  48. if (e is ISerializableComponentBuilder serializableEntityBuilder)
  49. {
  50. var entityType = serializableEntityBuilder.GetEntityComponentType();
  51. EntityComponentsToSerializeMap[new RefWrapperType(entityType)] = serializableEntityBuilder;
  52. entitiesToSerialize.Add(serializableEntityBuilder);
  53. }
  54. }
  55. EntitiesToSerialize = entitiesToSerialize.ToArray();
  56. }
  57. static (int indexSerial, int indexDynamic) SetupSpecialEntityComponent
  58. (IComponentBuilder[] defaultEntities, out IComponentBuilder[] componentsToBuild)
  59. {
  60. int length = defaultEntities.Length;
  61. int newLenght = length + 1;
  62. int indexSerial = -1;
  63. int indexDynamic = -1;
  64. for (var i = 0; i < length; ++i)
  65. {
  66. if (defaultEntities[i].GetEntityComponentType() == SerializableStructType)
  67. {
  68. indexSerial = i;
  69. --newLenght;
  70. }
  71. if (defaultEntities[i].GetEntityComponentType() == ComponentBuilderUtilities.ENTITY_INFO_COMPONENT)
  72. {
  73. indexDynamic = i;
  74. }
  75. }
  76. componentsToBuild = new IComponentBuilder[newLenght];
  77. Array.Copy(defaultEntities, 0, componentsToBuild, 0, length);
  78. return (indexSerial, indexDynamic);
  79. }
  80. public IComponentBuilder[] componentsToBuild => ComponentsToBuild;
  81. public uint hash => Hash;
  82. public Type realType => Type;
  83. public ISerializableComponentBuilder[] entitiesToSerialize => EntitiesToSerialize;
  84. static readonly IComponentBuilder[] ComponentsToBuild;
  85. static readonly FasterDictionary<RefWrapperType, ISerializableComponentBuilder> EntityComponentsToSerializeMap;
  86. static readonly ISerializableComponentBuilder[] EntitiesToSerialize;
  87. static readonly uint Hash;
  88. static readonly Type SerializableStructType = typeof(SerializableEntityComponent);
  89. static readonly Type Type = typeof(TType);
  90. }
  91. }