Pārlūkot izejas kodu

简化MemoryPack对于SortedDictionary<long, Entity>的序列化格式,key不需要序列化

tanghai 1 gadu atpakaļ
vecāks
revīzija
24937e2426

+ 23 - 0
Unity/Assets/Scripts/Core/Entity/ChildrenCollection.cs

@@ -0,0 +1,23 @@
+using System.Collections.Generic;
+
+namespace ET
+{
+    public class ChildrenCollection : SortedDictionary<long, Entity>
+    {
+        public ChildrenCollection()
+        {
+        }
+
+        public ChildrenCollection(IComparer<long> comparer) : base(comparer)
+        {
+        }
+
+        public ChildrenCollection(IDictionary<long, Entity> dictionary) : base(dictionary)
+        {
+        }
+
+        public ChildrenCollection(IDictionary<long, Entity> dictionary, IComparer<long> comparer) : base(dictionary, comparer)
+        {
+        }
+    }
+}

+ 1 - 1
Unity/Assets/Scripts/Core/Serialize/MemoryPackSortedDictionaryFormatter.cs.meta → Unity/Assets/Scripts/Core/Entity/ChildrenCollection.cs.meta

@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 204521cc3ab453749a3c4f6faf154fe2
+guid: 9a2d3f5dcc1743d41ae71e07fac014ef
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2

+ 23 - 0
Unity/Assets/Scripts/Core/Entity/ComponentsCollection.cs

@@ -0,0 +1,23 @@
+using System.Collections.Generic;
+
+namespace ET
+{
+    public class ComponentsCollection : SortedDictionary<long, Entity>
+    {
+        public ComponentsCollection()
+        {
+        }
+
+        public ComponentsCollection(IComparer<long> comparer) : base(comparer)
+        {
+        }
+
+        public ComponentsCollection(IDictionary<long, Entity> dictionary) : base(dictionary)
+        {
+        }
+
+        public ComponentsCollection(IDictionary<long, Entity> dictionary, IComparer<long> comparer) : base(dictionary, comparer)
+        {
+        }
+    }
+}

+ 11 - 0
Unity/Assets/Scripts/Core/Entity/ComponentsCollection.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 260517e72a2f58648822f015b6967bfb
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 27 - 27
Unity/Assets/Scripts/Core/Entity/Entity.cs

@@ -20,6 +20,11 @@ namespace ET
     [MemoryPackable(GenerateType.NoGenerate)]
     public abstract partial class Entity: DisposeObject, IPool
     {
+        public static long GetLongHashCodeByType(Type type)
+        {
+            return EntitySystemSingleton.Instance.GetLongHashCode(type);
+        }
+        
 #if ENABLE_VIEW && UNITY_EDITOR
         [BsonIgnore]
         [UnityEngine.HideInInspector]
@@ -336,7 +341,7 @@ namespace ET
                         foreach ((long _, Entity component) in this.components)
                         {
                             component.IsComponent = true;
-                            this.Components.Add(this.GetLongHashCode(component.GetType()), component);
+                            this.Components.Add(GetLongHashCodeByType(component.GetType()), component);
                             component.parent = this;
                         }
                     }
@@ -378,18 +383,18 @@ namespace ET
         }
 
         [MemoryPackInclude]
-        [BsonElement]
+        [BsonIgnore]
         [BsonIgnoreIfNull]
         [BsonDictionaryOptions(DictionaryRepresentation.ArrayOfArrays)]
-        protected SortedDictionary<long, Entity> children;
+        protected ChildrenCollection children;
 
         [MemoryPackIgnore]
         [BsonIgnore]
-        public SortedDictionary<long, Entity> Children
+        public ChildrenCollection Children
         {
             get
             {
-                return this.children ??= ObjectPool.Instance.Fetch<SortedDictionary<long, Entity>>();
+                return this.children ??= ObjectPool.Instance.Fetch<ChildrenCollection>();
             }
         }
 
@@ -415,18 +420,18 @@ namespace ET
         }
 
         [MemoryPackInclude]
-        [BsonElement]
+        [BsonIgnore]
         [BsonIgnoreIfNull]
         [BsonDictionaryOptions(DictionaryRepresentation.ArrayOfArrays)]
-        protected SortedDictionary<long, Entity> components;
+        protected ComponentsCollection components;
 
         [MemoryPackIgnore]
         [BsonIgnore]
-        public SortedDictionary<long, Entity> Components
+        public ComponentsCollection Components
         {
             get
             {
-                return this.components ??= ObjectPool.Instance.Fetch<SortedDictionary<long, Entity>>();
+                return this.components ??= ObjectPool.Instance.Fetch<ComponentsCollection>();
             }
         }
 
@@ -526,7 +531,7 @@ namespace ET
 
         private void AddToComponents(Entity component)
         {
-            this.Components.Add(this.GetLongHashCode(component.GetType()), component);
+            this.Components.Add(GetLongHashCodeByType(component.GetType()), component);
         }
 
         private void RemoveFromComponents(Entity component)
@@ -536,7 +541,7 @@ namespace ET
                 return;
             }
 
-            this.components.Remove(this.GetLongHashCode(component.GetType()));
+            this.components.Remove(GetLongHashCodeByType(component.GetType()));
 
             if (this.components.Count == 0)
             {
@@ -586,7 +591,7 @@ namespace ET
             Type type = typeof (K);
             
             Entity c;
-            if (!this.components.TryGetValue(this.GetLongHashCode(type), out c))
+            if (!this.components.TryGetValue(GetLongHashCodeByType(type), out c))
             {
                 return;
             }
@@ -608,7 +613,7 @@ namespace ET
             }
 
             Entity c;
-            if (!this.components.TryGetValue(this.GetLongHashCode(component.GetType()), out c))
+            if (!this.components.TryGetValue(GetLongHashCodeByType(component.GetType()), out c))
             {
                 return;
             }
@@ -630,7 +635,7 @@ namespace ET
             }
 
             Entity c;
-            if (!this.components.TryGetValue(this.GetLongHashCode(type), out c))
+            if (!this.components.TryGetValue(GetLongHashCodeByType(type), out c))
             {
                 return;
             }
@@ -653,7 +658,7 @@ namespace ET
             }
             
             Entity component;
-            if (!this.components.TryGetValue(this.GetLongHashCode(typeof (K)), out component))
+            if (!this.components.TryGetValue(GetLongHashCodeByType(typeof (K)), out component))
             {
                 return default;
             }
@@ -676,7 +681,7 @@ namespace ET
             }
             
             Entity component;
-            if (!this.components.TryGetValue(this.GetLongHashCode(type), out component))
+            if (!this.components.TryGetValue(GetLongHashCodeByType(type), out component))
             {
                 return null;
             }
@@ -706,7 +711,7 @@ namespace ET
         public Entity AddComponent(Entity component)
         {
             Type type = component.GetType();
-            if (this.components != null && this.components.ContainsKey(this.GetLongHashCode(type)))
+            if (this.components != null && this.components.ContainsKey(GetLongHashCodeByType(type)))
             {
                 throw new Exception($"entity already has component: {type.FullName}");
             }
@@ -718,7 +723,7 @@ namespace ET
 
         public Entity AddComponent(Type type, bool isFromPool = false)
         {
-            if (this.components != null && this.components.ContainsKey(this.GetLongHashCode(type)))
+            if (this.components != null && this.components.ContainsKey(GetLongHashCodeByType(type)))
             {
                 throw new Exception($"entity already has component: {type.FullName}");
             }
@@ -735,7 +740,7 @@ namespace ET
         public K AddComponentWithId<K>(long id, bool isFromPool = false) where K : Entity, IAwake, new()
         {
             Type type = typeof (K);
-            if (this.components != null && this.components.ContainsKey(this.GetLongHashCode(type)))
+            if (this.components != null && this.components.ContainsKey(GetLongHashCodeByType(type)))
             {
                 throw new Exception($"entity already has component: {type.FullName}");
             }
@@ -752,7 +757,7 @@ namespace ET
         public K AddComponentWithId<K, P1>(long id, P1 p1, bool isFromPool = false) where K : Entity, IAwake<P1>, new()
         {
             Type type = typeof (K);
-            if (this.components != null && this.components.ContainsKey(this.GetLongHashCode(type)))
+            if (this.components != null && this.components.ContainsKey(GetLongHashCodeByType(type)))
             {
                 throw new Exception($"entity already has component: {type.FullName}");
             }
@@ -769,7 +774,7 @@ namespace ET
         public K AddComponentWithId<K, P1, P2>(long id, P1 p1, P2 p2, bool isFromPool = false) where K : Entity, IAwake<P1, P2>, new()
         {
             Type type = typeof (K);
-            if (this.components != null && this.components.ContainsKey(this.GetLongHashCode(type)))
+            if (this.components != null && this.components.ContainsKey(GetLongHashCodeByType(type)))
             {
                 throw new Exception($"entity already has component: {type.FullName}");
             }
@@ -786,7 +791,7 @@ namespace ET
         public K AddComponentWithId<K, P1, P2, P3>(long id, P1 p1, P2 p2, P3 p3, bool isFromPool = false) where K : Entity, IAwake<P1, P2, P3>, new()
         {
             Type type = typeof (K);
-            if (this.components != null && this.components.ContainsKey(this.GetLongHashCode(type)))
+            if (this.components != null && this.components.ContainsKey(GetLongHashCodeByType(type)))
             {
                 throw new Exception($"entity already has component: {type.FullName}");
             }
@@ -913,11 +918,6 @@ namespace ET
             return component;
         }
 
-        protected virtual long GetLongHashCode(Type type)
-        {
-            return type.TypeHandle.Value.ToInt64();
-        }
-
         public override void BeginInit()
         {
             if (this is not ISerializeToEntity)

+ 25 - 0
Unity/Assets/Scripts/Core/Entity/EntitySystemSingleton.cs

@@ -6,6 +6,8 @@ namespace ET
     [Code]
     public class EntitySystemSingleton: Singleton<EntitySystemSingleton>, ISingletonAwake
     {
+        private readonly DoubleMap<Type, long> entityTypeLongHashCode = new();
+        
         public TypeSystems TypeSystems { get; private set; }
         
         public void Awake()
@@ -27,6 +29,29 @@ namespace ET
                     }
                 }
             }
+            
+            foreach (var kv in CodeTypes.Instance.GetTypes())
+            {
+                Type type = kv.Value;
+                if (typeof(Entity).IsAssignableFrom(type))
+                {
+                    long hash = type.FullName.GetLongHashCode();
+                    try
+                    {
+                        this.entityTypeLongHashCode.Add(type, type.FullName.GetLongHashCode());
+                    }
+                    catch (Exception e)
+                    {
+                        Type sameHashType = this.entityTypeLongHashCode.GetKeyByValue(hash);
+                        throw new Exception($"long hash add fail: {type.FullName} {sameHashType.FullName}", e);
+                    }
+                }
+            }
+        }
+        
+        public long GetLongHashCode(Type type)
+        {
+            return this.entityTypeLongHashCode.GetValueByKey(type);
         }
         
         public void Serialize(Entity component)

+ 79 - 0
Unity/Assets/Scripts/Core/Serialize/MemoryPackChildrenCollectionFormatter.cs

@@ -0,0 +1,79 @@
+using MemoryPack.Internal;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+using MemoryPack;
+using MemoryPack.Formatters;
+
+#nullable enable
+namespace ET
+{
+    /// <summary>
+    /// 替换默认的SortedDictionaryFormatter
+    /// </summary>
+    [Preserve]
+    public sealed class MemoryPackChildrenCollectionFormatter : MemoryPackFormatter<ChildrenCollection>
+    {
+        [Preserve]
+#if UNITY
+        public override void Serialize(ref MemoryPackWriter writer, ref ChildrenCollection? value)
+#else
+        public override void Serialize<TBufferWriter>(ref MemoryPackWriter<TBufferWriter> writer, scoped ref ChildrenCollection? value)
+#endif
+        {
+            if (value == null)
+            {
+                writer.WriteNullCollectionHeader();
+                return;
+            }
+            
+            // writer.WriteCollectionHeader(value.Count);
+            var formatter = writer.GetFormatter<Entity>();
+            ref byte spanReference = ref writer.GetSpanReference(4);
+            writer.Advance(4);
+            int count = 0;
+            foreach (var kv in value)
+            {
+                if (kv.Value is not ISerializeToEntity)
+                {
+                    continue;
+                }
+
+                Entity entity = kv.Value;
+                ++count;
+                formatter.Serialize(ref writer, ref entity!);
+            }
+            Unsafe.WriteUnaligned(ref spanReference, count);
+        }
+
+        [Preserve]
+#if UNITY
+        public override void Deserialize(ref MemoryPackReader reader, ref ChildrenCollection? value)
+#else
+        public override void Deserialize(ref MemoryPackReader reader, scoped ref ChildrenCollection? value)
+#endif
+        {
+            if (!reader.TryReadCollectionHeader(out int length))
+            {
+                value = null;
+                return;
+            }
+
+            if (value == null)
+            {
+                value = new ChildrenCollection();
+            }
+            else
+            {
+                value.Clear();
+            }
+
+            var formatter = reader.GetFormatter<Entity>();
+            for (int i = 0; i < length; i++)
+            {
+                Entity entity = null!;
+                formatter.Deserialize(ref reader, ref entity!);
+                value.Add(entity.Id, entity);
+            }
+        }
+    }
+}

+ 11 - 0
Unity/Assets/Scripts/Core/Serialize/MemoryPackChildrenCollectionFormatter.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: ac56eff40b8db2042a38c4b93477d8d9
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 81 - 0
Unity/Assets/Scripts/Core/Serialize/MemoryPackComponentsCollectionFormatter.cs

@@ -0,0 +1,81 @@
+using MemoryPack.Internal;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+using MemoryPack;
+using MemoryPack.Formatters;
+
+#nullable enable
+namespace ET
+{
+    /// <summary>
+    /// 替换默认的SortedDictionaryFormatter
+    /// </summary>
+    [Preserve]
+    public sealed class MemoryPackComponentsCollectionFormatter : MemoryPackFormatter<ComponentsCollection>
+    {
+        [Preserve]
+#if UNITY
+        public override void Serialize(ref MemoryPackWriter writer, ref ComponentsCollection? value)
+#else
+        public override void Serialize<TBufferWriter>(ref MemoryPackWriter<TBufferWriter> writer, scoped ref ComponentsCollection? value)
+#endif
+        {
+            if (value == null)
+            {
+                writer.WriteNullCollectionHeader();
+                return;
+            }
+            
+            // writer.WriteCollectionHeader(value.Count);
+            var formatter = writer.GetFormatter<Entity>();
+            ref byte spanReference = ref writer.GetSpanReference(4);
+            writer.Advance(4);
+            int count = 0;
+            foreach (var kv in value)
+            {
+                if (kv.Value is not ISerializeToEntity)
+                {
+                    continue;
+                }
+
+                Entity entity = kv.Value;
+                ++count;
+                formatter.Serialize(ref writer, ref entity!);
+            }
+            Unsafe.WriteUnaligned(ref spanReference, count);
+        }
+
+        [Preserve]
+#if UNITY
+        public override void Deserialize(ref MemoryPackReader reader, ref ComponentsCollection? value)
+#else
+        public override void Deserialize(ref MemoryPackReader reader, scoped ref ComponentsCollection? value)
+#endif
+        {
+            if (!reader.TryReadCollectionHeader(out int length))
+            {
+                value = null;
+                return;
+            }
+
+            if (value == null)
+            {
+                // 这里甚至可以用对象池
+                value = new ComponentsCollection();
+            }
+            else
+            {
+                value.Clear();
+            }
+
+            var formatter = reader.GetFormatter<Entity>();
+            for (int i = 0; i < length; i++)
+            {
+                Entity entity = null!;
+                formatter.Deserialize(ref reader, ref entity!);
+                long key = Entity.GetLongHashCodeByType(entity.GetType());
+                value.Add(key, entity);
+            }
+        }
+    }
+}

+ 11 - 0
Unity/Assets/Scripts/Core/Serialize/MemoryPackComponentsCollectionFormatter.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 5b8dad68588411b47a5c5ae82a91a20f
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 0 - 97
Unity/Assets/Scripts/Core/Serialize/MemoryPackSortedDictionaryFormatter.cs

@@ -1,97 +0,0 @@
-using MemoryPack.Internal;
-using System.Collections.Generic;
-using System.Runtime.CompilerServices;
-using MemoryPack;
-using MemoryPack.Formatters;
-
-#nullable enable
-namespace ET
-{
-    /// <summary>
-    /// 替换默认的SortedDictionaryFormatter
-    /// </summary>
-    /// <typeparam name="TKey"></typeparam>
-    /// <typeparam name="TValue"></typeparam>
-    [Preserve]
-    public sealed class MemoryPackSortedDictionaryFormatter<TKey, TValue> : MemoryPackFormatter<SortedDictionary<TKey, TValue?>>
-            where TKey : notnull
-    {
-        readonly IComparer<TKey>? comparer;
-
-        public MemoryPackSortedDictionaryFormatter()
-                : this(null)
-        {
-
-        }
-
-        public MemoryPackSortedDictionaryFormatter(IComparer<TKey>? comparer)
-        {
-            this.comparer = comparer;
-        }
-
-
-        [Preserve]
-#if UNITY
-        public override void Serialize(ref MemoryPackWriter writer, ref SortedDictionary<TKey, TValue?>? value)
-#else
-        public override void Serialize<TBufferWriter>(ref MemoryPackWriter<TBufferWriter> writer, scoped ref SortedDictionary<TKey, TValue?>? value)
-#endif
-        {
-            if (value == null)
-            {
-                writer.WriteNullCollectionHeader();
-                return;
-            }
-
-            var keyFormatter = writer.GetFormatter<TKey>();
-            var valueFormatter = writer.GetFormatter<TValue>();
-
-            // writer.WriteCollectionHeader(value.Count);
-            ref byte spanReference = ref writer.GetSpanReference(4);
-            writer.Advance(4);
-            int count = 0;
-            foreach (var item in value)
-            {
-                if (item.Value is not ISerializeToEntity)
-                {
-                    continue;
-                }
-                ++count;
-                KeyValuePairFormatter.Serialize(keyFormatter, valueFormatter, ref writer, item!);
-            }
-            Unsafe.WriteUnaligned(ref spanReference, count);
-        }
-
-        [Preserve]
-#if UNITY
-        public override void Deserialize(ref MemoryPackReader reader, ref SortedDictionary<TKey, TValue?>? value)
-#else
-        
-        public override void Deserialize(ref MemoryPackReader reader, scoped ref SortedDictionary<TKey, TValue?>? value)
-#endif
-        {
-            if (!reader.TryReadCollectionHeader(out var length))
-            {
-                value = null;
-                return;
-            }
-
-            if (value == null)
-            {
-                value = new SortedDictionary<TKey, TValue?>(comparer);
-            }
-            else
-            {
-                value.Clear();
-            }
-
-            var keyFormatter = reader.GetFormatter<TKey>();
-            var valueFormatter = reader.GetFormatter<TValue>();
-            for (int i = 0; i < length; i++)
-            {
-                KeyValuePairFormatter.Deserialize(keyFormatter, valueFormatter, ref reader, out var k, out var v);
-                value.Add(k!, v);
-            }
-        }
-    }
-}

+ 2 - 1
Unity/Assets/Scripts/Model/Share/Entry.cs

@@ -58,7 +58,8 @@ namespace ET
             // 注册Mongo type
             MongoRegister.Init();
             
-            MemoryPackFormatterProvider.Register(new MemoryPackSortedDictionaryFormatter<long, Entity>());
+            MemoryPackFormatterProvider.Register(new MemoryPackChildrenCollectionFormatter());
+            MemoryPackFormatterProvider.Register(new MemoryPackComponentsCollectionFormatter());
             
             // 注册Entity序列化器
             EntitySerializeRegister.Init();

+ 0 - 5
Unity/Assets/Scripts/Model/Share/LockStep/LSEntity.cs

@@ -49,11 +49,6 @@ namespace ET
             return this.AddChildWithId<T, A, B, C>(this.GetId(), a, b, c, isFromPool);
         }
 
-        protected override long GetLongHashCode(Type type)
-        {
-            return LSEntitySystemSingleton.Instance.GetLongHashCode(type);
-        }
-
         protected override void RegisterSystem()
         {
             LSWorld lsWorld = (LSWorld)this.IScene;

+ 1 - 24
Unity/Assets/Scripts/Model/Share/LockStep/LSEntitySystemSingleton.cs

@@ -16,8 +16,6 @@ namespace ET
     {
         private TypeSystems TypeSystems { get; set; }
         
-        private readonly DoubleMap<Type, long> lsEntityTypeLongHashCode = new();
-        
         public void Awake()
         {
             this.TypeSystems = new(LSQueneUpdateIndex.Max);
@@ -39,28 +37,7 @@ namespace ET
                 }
             }
             
-            foreach (var kv in CodeTypes.Instance.GetTypes())
-            {
-                Type type = kv.Value;
-                if (typeof(LSEntity).IsAssignableFrom(type))
-                {
-                    long hash = type.FullName.GetLongHashCode();
-                    try
-                    {
-                        this.lsEntityTypeLongHashCode.Add(type, type.FullName.GetLongHashCode());
-                    }
-                    catch (Exception e)
-                    {
-                        Type sameHashType = this.lsEntityTypeLongHashCode.GetKeyByValue(hash);
-                        throw new Exception($"long hash add fail: {type.FullName} {sameHashType.FullName}", e);
-                    }
-                }
-            }
-        }
-        
-        public long GetLongHashCode(Type type)
-        {
-            return this.lsEntityTypeLongHashCode.GetValueByKey(type);
+
         }
         
         public TypeSystems.OneTypeSystems GetOneTypeSystems(Type type)

+ 0 - 5
Unity/Assets/Scripts/Model/Share/LockStep/LSWorld.cs

@@ -114,10 +114,5 @@ namespace ET
         {
             return this.AddChildWithId<T, A, B, C>(this.GetId(), a, b, c, isFromPool);
         }
-        
-        protected override long GetLongHashCode(Type type)
-        {
-            return LSEntitySystemSingleton.Instance.GetLongHashCode(type);
-        }
     }
 }