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.

125 lines
5.3KB

  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
  25. && type.IsAbstract) //this means only static classes
  26. {
  27. var fields = type.GetFields();
  28. foreach (var field in fields)
  29. {
  30. if (field.IsStatic)
  31. {
  32. if (typeOfExclusiveGroup.IsAssignableFrom(field.FieldType))
  33. {
  34. var group = (ExclusiveGroup) field.GetValue(null);
  35. #if DEBUG
  36. GroupNamesMap.idToName[@group] =
  37. $"{$"{type.FullName}.{field.Name}"} {group.id})";
  38. #endif
  39. //The hashname is independent from the actual group ID. this is fundamental because it is want
  40. //guarantees the hash to be the same across different machines
  41. RegisterGroup(group, $"{type.FullName}.{field.Name}");
  42. }
  43. else
  44. if (typeOfExclusiveGroupStruct.IsAssignableFrom(field.FieldType))
  45. {
  46. var group = (ExclusiveGroupStruct) field.GetValue(null);
  47. #if DEBUG
  48. GroupNamesMap.idToName[@group] =
  49. $"{$"{type.FullName}.{field.Name}"} {group.id})";
  50. #endif
  51. //The hashname is independent from the actual group ID. this is fundamental because it is want
  52. //guarantees the hash to be the same across different machines
  53. RegisterGroup(@group, $"{type.FullName}.{field.Name}");
  54. }
  55. }
  56. }
  57. }
  58. }
  59. }
  60. catch
  61. {
  62. Console.LogDebugWarning(
  63. "something went wrong while gathering group names on the assembly: ".FastConcat(
  64. assembly.FullName));
  65. }
  66. }
  67. }
  68. /// <summary>
  69. /// The hashname is independent from the actual group ID. this is fundamental because it is want
  70. /// guarantees the hash to be the same across different machines
  71. /// </summary>
  72. /// <param name="exclusiveGroupStruct"></param>
  73. /// <param name="name"></param>
  74. /// <exception cref="ECSException"></exception>
  75. public static void RegisterGroup(ExclusiveGroupStruct exclusiveGroupStruct, string name)
  76. {
  77. //Group already registered by another field referencing the same group
  78. if (_hashByGroups.ContainsKey(exclusiveGroupStruct))
  79. return;
  80. var nameHash = DesignatedHash.Hash(Encoding.ASCII.GetBytes(name));
  81. if (_groupsByHash.ContainsKey(nameHash))
  82. throw new ECSException($"Group hash collision with {name} and {_groupsByHash[nameHash]}");
  83. Console.LogDebug($"Registering group {name} with ID {exclusiveGroupStruct.id} to {nameHash}");
  84. _groupsByHash.Add(nameHash, exclusiveGroupStruct);
  85. _hashByGroups.Add(exclusiveGroupStruct, nameHash);
  86. }
  87. public static uint GetHashFromGroup(ExclusiveGroupStruct groupStruct)
  88. {
  89. #if DEBUG
  90. if (_hashByGroups.ContainsKey(groupStruct) == false)
  91. throw new ECSException($"Attempted to get hash from unregistered group {groupStruct}");
  92. #endif
  93. return _hashByGroups[groupStruct];
  94. }
  95. public static ExclusiveGroupStruct GetGroupFromHash(uint groupHash)
  96. {
  97. #if DEBUG
  98. if (_groupsByHash.ContainsKey(groupHash) == false)
  99. throw new ECSException($"Attempted to get group from unregistered hash {groupHash}");
  100. #endif
  101. return _groupsByHash[groupHash];
  102. }
  103. static readonly Dictionary<uint, ExclusiveGroupStruct> _groupsByHash;
  104. static readonly Dictionary<ExclusiveGroupStruct, uint> _hashByGroups;
  105. static GroupHashMap()
  106. {
  107. _groupsByHash = new Dictionary<uint, ExclusiveGroupStruct>();
  108. _hashByGroups = new Dictionary<ExclusiveGroupStruct, uint>();
  109. }
  110. }
  111. }