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.

106 lines
3.9KB

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