using System;
using System.Collections.Generic;
using System.Reflection;
using Svelto.Common;
using Svelto.ECS.Serialization;
namespace Svelto.ECS
{
partial class EnginesRoot
{
///
/// The map of serializable entity hashes to the serializable entity builders (to know the entity structs
/// to serialize)
///
readonly SerializationDescriptorMap _serializationDescriptorMap;
sealed class SerializationDescriptorMap
{
static readonly Dictionary _descriptors;
static readonly Dictionary _defaultFactories;
static SerializationDescriptorMap()
{
_descriptors = new Dictionary();
_defaultFactories = new Dictionary();
}
///
/// 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()
{
_factories = new Dictionary();
CopyDefaultFactories();
}
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;
}
void CopyDefaultFactories()
{
foreach (var factory in _defaultFactories)
{
_factories[factory.Key] = factory.Value;
}
}
internal static void Init()
{
using (new StandardProfiler("Assemblies Scan"))
{
List assemblies = AssemblyUtility.GetCompatibleAssemblies();
Type defaultFactory = typeof(DefaultVersioningFactory<>);
foreach (Assembly assembly in assemblies)
{
foreach (Type type in AssemblyUtility.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, defaultFactory);
}
}
}
}
}
static 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);
_defaultFactories.Add(descriptorHash, instance as IDeserializationFactory);
}
readonly Dictionary _factories;
}
}
}