using System; using System.Collections.Generic; using System.Reflection; using Svelto.Common; using Svelto.ECS.Serialization; namespace Svelto.ECS { partial class EnginesRoot { sealed class SerializationDescriptorMap { /// /// Here we want to register all the EntityDescriptors that need to be serialized for network play. /// /// Remember! This needs to in sync across different clients and server as the values are serialized across /// the network also want this to not change so we can save to a DB /// internal SerializationDescriptorMap() { _descriptors = new Dictionary(); _factories = new Dictionary(); using (new StandardProfiler("Assemblies Scan")) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); Type d1 = typeof(DefaultVersioningFactory<>); foreach (Assembly assembly in assemblies) { foreach (Type type in GetTypesSafe(assembly)) { if (type != null && type.IsClass && type.IsAbstract == false && type.BaseType != null && type.BaseType.IsGenericType && type.BaseType.GetGenericTypeDefinition() == typeof(SerializableEntityDescriptor<>)) { var descriptor = Activator.CreateInstance(type) as ISerializableEntityDescriptor; RegisterEntityDescriptor(descriptor, type, d1); } } } } } static IEnumerable GetTypesSafe(Assembly assembly) { try { Type[] types = assembly.GetTypes(); return types; } catch (ReflectionTypeLoadException e) { return e.Types; } } void RegisterEntityDescriptor(ISerializableEntityDescriptor descriptor, Type type, Type d1) { if (descriptor == null) return; uint descriptorHash = descriptor.hash; #if DEBUG && !PROFILE_SVELTO if (_descriptors.ContainsKey(descriptorHash)) { throw new Exception($"Hash Collision of '{descriptor.GetType()}' against " + $"'{_descriptors[descriptorHash]} ::: {descriptorHash}'"); } #endif _descriptors[descriptorHash] = descriptor; Type[] typeArgs = {type}; var makeGenericType = d1.MakeGenericType(typeArgs); var instance = Activator.CreateInstance(makeGenericType); _factories.Add(descriptorHash, instance as IDeserializationFactory); } public ISerializableEntityDescriptor GetDescriptorFromHash(uint descriptorHash) { #if DEBUG && !PROFILE_SVELTO DBC.ECS.Check.Require(_descriptors.ContainsKey(descriptorHash), $"Could not find descriptor linked to hash, wrong deserialization size? '{ descriptorHash}'!"); #endif return _descriptors[descriptorHash]; } public IDeserializationFactory GetSerializationFactory(uint descriptorHash) { #if DEBUG && !PROFILE_SVELTO DBC.ECS.Check.Require(_descriptors.ContainsKey(descriptorHash), $"Could not find descriptor linked to descriptor hash, wrong deserialization size? '{ descriptorHash}'!"); DBC.ECS.Check.Require(_factories.ContainsKey(descriptorHash), $"Could not find factory linked to hash '{ _descriptors[descriptorHash]}'!"); #endif return _factories[descriptorHash]; } public void RegisterSerializationFactory(IDeserializationFactory deserializationFactory) where Descriptor : ISerializableEntityDescriptor, new() { _factories[SerializationEntityDescriptorTemplate.hash] = deserializationFactory; } readonly Dictionary _descriptors; readonly Dictionary _factories; } /// /// The map of serializable entity hashes to the serializable entity builders (to know the entity structs /// to serialize) /// SerializationDescriptorMap serializationDescriptorMap { get; } } }