using System; using System.Reflection; using System.Text; using Svelto.DataStructures; using Svelto.Utilities; namespace Svelto.ECS.Serialization { public static class DesignatedHash { public static readonly Func Hash = Murmur3.MurmurHash3_x86_32; } public abstract class SerializableEntityDescriptor : ISerializableEntityDescriptor where TType : IEntityDescriptor, new() { static SerializableEntityDescriptor() { IEntityBuilder[] defaultEntities = EntityDescriptorTemplate.descriptor.entitiesToBuild; var hashNameAttribute = _type.GetCustomAttribute(); if (hashNameAttribute == null) { throw new Exception("HashName attribute not found on the serializable type ".FastConcat(_type.FullName)); } _hash = DesignatedHash.Hash(Encoding.ASCII.GetBytes(hashNameAttribute._name)); var (index, dynamicIndex) = SetupSpecialEntityStruct(defaultEntities, out _entitiesToBuild); if (index == -1) { index = _entitiesToBuild.Length - 1; } // Stores the hash of this EntityDescriptor _entitiesToBuild[index] = new EntityBuilder ( new SerializableEntityStruct { descriptorHash = _hash } ); // If the current serializable is an ExtendibleDescriptor, I have to update it. if (dynamicIndex != -1) { _entitiesToBuild[dynamicIndex] = new EntityBuilder ( new EntityStructInfoView { entitiesToBuild = _entitiesToBuild } ); } ///// var entitiesToSerialize = new FasterList(); _entitiesToSerializeMap = new FasterDictionary, ISerializableEntityBuilder>(); foreach (IEntityBuilder e in defaultEntities) { if (e is ISerializableEntityBuilder serializableEntityBuilder) { var entityType = serializableEntityBuilder.GetEntityType(); _entitiesToSerializeMap[new RefWrapper(entityType)] = serializableEntityBuilder; entitiesToSerialize.Add(serializableEntityBuilder); } } _entitiesToSerialize = entitiesToSerialize.ToArray(); } static (int indexSerial, int indexDynamic) SetupSpecialEntityStruct(IEntityBuilder[] defaultEntities, out IEntityBuilder[] entitiesToBuild) { int length = defaultEntities.Length; int newLenght = length + 1; int indexSerial = -1; int indexDynamic = -1; for (var i = 0; i < length; ++i) { if (defaultEntities[i].GetEntityType() == _serializableStructType) { indexSerial = i; --newLenght; } if (defaultEntities[i].GetEntityType() == EntityBuilderUtilities.ENTITY_STRUCT_INFO_VIEW) { indexDynamic = i; } } entitiesToBuild = new IEntityBuilder[newLenght]; Array.Copy(defaultEntities, 0, entitiesToBuild, 0, length); return (indexSerial, indexDynamic); } public void CopySerializedEntityStructs(in EntityStructInitializer sourceInitializer, in EntityStructInitializer destinationInitializer, SerializationType serializationType) { foreach (ISerializableEntityBuilder e in entitiesToSerialize) { e.CopySerializedEntityStructs(sourceInitializer, destinationInitializer, serializationType); } } public IEntityBuilder[] entitiesToBuild => _entitiesToBuild; public uint hash => _hash; public ISerializableEntityBuilder[] entitiesToSerialize => _entitiesToSerialize; static readonly IEntityBuilder[] _entitiesToBuild; static readonly FasterDictionary, ISerializableEntityBuilder> _entitiesToSerializeMap; static readonly ISerializableEntityBuilder[] _entitiesToSerialize; static readonly uint _hash; static readonly Type _serializableStructType = typeof(SerializableEntityStruct); static readonly Type _type = typeof(TType); } }