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.

115 lines
4.7KB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Reflection;
  4. using System.Text;
  5. using Svelto.ECS.Serialization;
  6. namespace Svelto.ECS
  7. {
  8. static class GroupHashMap
  9. {
  10. /// <summary>
  11. /// c# Static constructors are guaranteed to be thread safe
  12. /// </summary>
  13. public static void Init()
  14. {
  15. List<Assembly> assemblies = AssemblyUtility.GetCompatibleAssemblies();
  16. foreach (Assembly assembly in assemblies)
  17. {
  18. try
  19. {
  20. var typeOfExclusiveGroup = typeof(ExclusiveGroup);
  21. var typeOfExclusiveGroupStruct = typeof(ExclusiveGroupStruct);
  22. foreach (Type type in AssemblyUtility.GetTypesSafe(assembly))
  23. {
  24. if (type != null && type.IsClass && type.IsSealed && type.IsAbstract) //this means only static classes
  25. {
  26. var fields = type.GetFields();
  27. foreach (var field in fields)
  28. {
  29. if (field.IsStatic)
  30. {
  31. if (typeOfExclusiveGroup.IsAssignableFrom(field.FieldType))
  32. {
  33. var group = (ExclusiveGroup)field.GetValue(null);
  34. var name = $"{type.FullName}.{field.Name}";
  35. #if DEBUG
  36. GroupNamesMap.idToName[(uint)@group] = $"{name} {(uint)group})";
  37. #endif
  38. RegisterGroup(group, name);
  39. }
  40. else
  41. {
  42. if (typeOfExclusiveGroupStruct.IsAssignableFrom(field.FieldType))
  43. {
  44. var group = (ExclusiveGroupStruct)field.GetValue(null);
  45. var name = $"{type.FullName}.{field.Name}";
  46. #if DEBUG
  47. GroupNamesMap.idToName[(uint)@group] = $"{name} {(uint)group})";
  48. #endif
  49. RegisterGroup(@group, name);
  50. }
  51. }
  52. }
  53. }
  54. }
  55. }
  56. }
  57. catch
  58. {
  59. Console.LogDebugWarning(
  60. "something went wrong while gathering group names on the assembly: ".FastConcat(assembly.FullName));
  61. }
  62. }
  63. }
  64. public static void RegisterGroup(ExclusiveGroupStruct exclusiveGroupStruct, string name)
  65. {
  66. //Group already registered by another field referencing the same group
  67. if (_hashByGroups.ContainsKey(exclusiveGroupStruct))
  68. return;
  69. var nameHash = DesignatedHash.Hash(Encoding.ASCII.GetBytes(name));
  70. if(_groupsByHash.ContainsKey(nameHash))
  71. throw new ECSException($"Group hash collision with {name} and {_groupsByHash[nameHash]}");
  72. Console.LogDebug($"Registering group {name} with ID {(uint)exclusiveGroupStruct} to {nameHash}");
  73. _groupsByHash.Add(nameHash, exclusiveGroupStruct);
  74. _hashByGroups.Add(exclusiveGroupStruct, nameHash);
  75. }
  76. public static uint GetHashFromGroup(ExclusiveGroupStruct groupStruct)
  77. {
  78. #if DEBUG
  79. if (_hashByGroups.ContainsKey(groupStruct) == false)
  80. throw new ECSException($"Attempted to get hash from unregistered group {groupStruct}");
  81. #endif
  82. return _hashByGroups[groupStruct];
  83. }
  84. public static ExclusiveGroupStruct GetGroupFromHash(uint groupHash)
  85. {
  86. #if DEBUG
  87. if (_groupsByHash.ContainsKey(groupHash) == false)
  88. throw new ECSException($"Attempted to get group from unregistered hash {groupHash}");
  89. #endif
  90. return _groupsByHash[groupHash];
  91. }
  92. static readonly Dictionary<uint, ExclusiveGroupStruct> _groupsByHash;
  93. static readonly Dictionary<ExclusiveGroupStruct, uint> _hashByGroups;
  94. static GroupHashMap()
  95. {
  96. _groupsByHash = new Dictionary<uint, ExclusiveGroupStruct>();
  97. _hashByGroups = new Dictionary<ExclusiveGroupStruct, uint>();
  98. }
  99. }
  100. }