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.

119 lines
4.9KB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Reflection;
  4. using Svelto.Common;
  5. using Svelto.ECS.Serialization;
  6. namespace Svelto.ECS
  7. {
  8. partial class EnginesRoot
  9. {
  10. sealed class SerializationDescriptorMap
  11. {
  12. /// <summary>
  13. /// Here we want to register all the EntityDescriptors that need to be serialized for network play.
  14. ///
  15. /// Remember! This needs to in sync across different clients and server as the values are serialized across
  16. /// the network also want this to not change so we can save to a DB
  17. /// </summary>
  18. internal SerializationDescriptorMap()
  19. {
  20. _descriptors = new Dictionary<uint, ISerializableEntityDescriptor>();
  21. _factories = new Dictionary<uint, IDeserializationFactory>();
  22. using (new StandardProfiler("Assemblies Scan"))
  23. {
  24. Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
  25. Type d1 = typeof(DefaultVersioningFactory<>);
  26. foreach (Assembly assembly in assemblies)
  27. {
  28. foreach (Type type in GetTypesSafe(assembly))
  29. {
  30. if (type != null && type.IsClass && type.IsAbstract == false && type.BaseType != null
  31. && type.BaseType.IsGenericType && type.BaseType.GetGenericTypeDefinition()
  32. == typeof(SerializableEntityDescriptor<>))
  33. {
  34. var descriptor = Activator.CreateInstance(type) as ISerializableEntityDescriptor;
  35. RegisterEntityDescriptor(descriptor, type, d1);
  36. }
  37. }
  38. }
  39. }
  40. }
  41. static IEnumerable<Type> GetTypesSafe(Assembly assembly)
  42. {
  43. try
  44. {
  45. Type[] types = assembly.GetTypes();
  46. return types;
  47. }
  48. catch (ReflectionTypeLoadException e)
  49. {
  50. return e.Types;
  51. }
  52. }
  53. void RegisterEntityDescriptor(ISerializableEntityDescriptor descriptor, Type type, Type d1)
  54. {
  55. if (descriptor == null)
  56. return;
  57. uint descriptorHash = descriptor.hash;
  58. #if DEBUG && !PROFILE_SVELTO
  59. if (_descriptors.ContainsKey(descriptorHash))
  60. {
  61. throw new Exception($"Hash Collision of '{descriptor.GetType()}' against " +
  62. $"'{_descriptors[descriptorHash]} ::: {descriptorHash}'");
  63. }
  64. #endif
  65. _descriptors[descriptorHash] = descriptor;
  66. Type[] typeArgs = {type};
  67. var makeGenericType = d1.MakeGenericType(typeArgs);
  68. var instance = Activator.CreateInstance(makeGenericType);
  69. _factories.Add(descriptorHash, instance as IDeserializationFactory);
  70. }
  71. public ISerializableEntityDescriptor GetDescriptorFromHash(uint descriptorHash)
  72. {
  73. #if DEBUG && !PROFILE_SVELTO
  74. DBC.ECS.Check.Require(_descriptors.ContainsKey(descriptorHash),
  75. $"Could not find descriptor linked to hash, wrong deserialization size? '{ descriptorHash}'!");
  76. #endif
  77. return _descriptors[descriptorHash];
  78. }
  79. public IDeserializationFactory GetSerializationFactory(uint descriptorHash)
  80. {
  81. #if DEBUG && !PROFILE_SVELTO
  82. DBC.ECS.Check.Require(_descriptors.ContainsKey(descriptorHash),
  83. $"Could not find descriptor linked to descriptor hash, wrong deserialization size? '{ descriptorHash}'!");
  84. DBC.ECS.Check.Require(_factories.ContainsKey(descriptorHash),
  85. $"Could not find factory linked to hash '{ _descriptors[descriptorHash]}'!");
  86. #endif
  87. return _factories[descriptorHash];
  88. }
  89. public void RegisterSerializationFactory<Descriptor>(IDeserializationFactory deserializationFactory)
  90. where Descriptor : ISerializableEntityDescriptor, new()
  91. {
  92. _factories[SerializationEntityDescriptorTemplate<Descriptor>.hash] = deserializationFactory;
  93. }
  94. readonly Dictionary<uint, ISerializableEntityDescriptor> _descriptors;
  95. readonly Dictionary<uint, IDeserializationFactory> _factories;
  96. }
  97. /// <summary>
  98. /// The map of serializable entity hashes to the serializable entity builders (to know the entity structs
  99. /// to serialize)
  100. /// </summary>
  101. SerializationDescriptorMap serializationDescriptorMap { get; }
  102. }
  103. }