using System; using System.Collections.Generic; using System.Reflection; using System.Text; using Svelto.ECS.Serialization; namespace Svelto.ECS { static class GroupHashMap { /// /// c# Static constructors are guaranteed to be thread safe /// public static void Init() { List assemblies = AssemblyUtility.GetCompatibleAssemblies(); foreach (Assembly assembly in assemblies) { try { var typeOfExclusiveGroup = typeof(ExclusiveGroup); var typeOfExclusiveGroupStruct = typeof(ExclusiveGroupStruct); foreach (Type type in AssemblyUtility.GetTypesSafe(assembly)) { if (type != null && type.IsClass && type.IsSealed && type.IsAbstract) //this means only static classes { var fields = type.GetFields(); foreach (var field in fields) { if (field.IsStatic) { if (typeOfExclusiveGroup.IsAssignableFrom(field.FieldType)) { var group = (ExclusiveGroup) field.GetValue(null); #if DEBUG GroupNamesMap.idToName[@group] = $"{$"{type.FullName}.{field.Name}"} {group.id})"; #endif //The hashname is independent from the actual group ID. this is fundamental because it is want //guarantees the hash to be the same across different machines RegisterGroup(group, $"{type.FullName}.{field.Name}"); } else if (typeOfExclusiveGroupStruct.IsAssignableFrom(field.FieldType)) { var group = (ExclusiveGroupStruct) field.GetValue(null); #if DEBUG GroupNamesMap.idToName[@group] = $"{$"{type.FullName}.{field.Name}"} {group.id})"; #endif //The hashname is independent from the actual group ID. this is fundamental because it is want //guarantees the hash to be the same across different machines RegisterGroup(@group, $"{type.FullName}.{field.Name}"); } } } } } } catch { Console.LogDebugWarning( "something went wrong while gathering group names on the assembly: ".FastConcat( assembly.FullName)); } } } /// /// The hashname is independent from the actual group ID. this is fundamental because it is want /// guarantees the hash to be the same across different machines /// /// /// /// public static void RegisterGroup(ExclusiveGroupStruct exclusiveGroupStruct, string name) { //Group already registered by another field referencing the same group if (_hashByGroups.ContainsKey(exclusiveGroupStruct)) return; var nameHash = DesignatedHash.Hash(Encoding.ASCII.GetBytes(name)); if (_groupsByHash.ContainsKey(nameHash)) throw new ECSException($"Group hash collision with {name} and {_groupsByHash[nameHash]}"); Console.LogDebug($"Registering group {name} with ID {exclusiveGroupStruct.id} to {nameHash}"); _groupsByHash.Add(nameHash, exclusiveGroupStruct); _hashByGroups.Add(exclusiveGroupStruct, nameHash); } public static uint GetHashFromGroup(ExclusiveGroupStruct groupStruct) { #if DEBUG if (_hashByGroups.ContainsKey(groupStruct) == false) throw new ECSException($"Attempted to get hash from unregistered group {groupStruct}"); #endif return _hashByGroups[groupStruct]; } public static ExclusiveGroupStruct GetGroupFromHash(uint groupHash) { #if DEBUG if (_groupsByHash.ContainsKey(groupHash) == false) throw new ECSException($"Attempted to get group from unregistered hash {groupHash}"); #endif return _groupsByHash[groupHash]; } static readonly Dictionary _groupsByHash; static readonly Dictionary _hashByGroups; static GroupHashMap() { _groupsByHash = new Dictionary(); _hashByGroups = new Dictionary(); } } }