using System; using System.Collections.Generic; using System.Runtime.Serialization; using Fantasy.Entitas.Interface; using Fantasy.Pool; using MongoDB.Bson.Serialization.Attributes; using Newtonsoft.Json; using ProtoBuf; // ReSharper disable ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract // ReSharper disable MergeIntoPattern // ReSharper disable SuspiciousTypeConversion.Global // ReSharper disable NullCoalescingConditionIsAlwaysNotNullAccordingToAPIContract // ReSharper disable CheckNamespace #pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type. #pragma warning disable CS8603 // Possible null reference return. #pragma warning disable CS8602 // Dereference of a possibly null reference. #pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type. #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. namespace Fantasy.Entitas { /// /// 用来表示一个Entity /// public interface IEntity : IDisposable, IPool { } /// /// Entity的抽象类,任何Entity必须继承这个接口才可以使用 /// public abstract partial class Entity : IEntity { #region Members /// /// 获取一个值,表示实体是否支持对象池。 /// [BsonIgnore] [JsonIgnore] [ProtoIgnore] [IgnoreDataMember] private bool _isPool; /// /// 实体的Id /// [BsonId] [BsonElement] [BsonIgnoreIfDefault] [BsonDefaultValue(0L)] public long Id { get; protected set; } /// /// 实体的RunTimeId,其他系统可以通过这个Id发送Route消息,这个Id也可以理解为RouteId /// [BsonIgnore] [IgnoreDataMember] [ProtoIgnore] public long RuntimeId { get; protected set; } /// /// 当前实体是否已经被销毁 /// [BsonIgnore] [JsonIgnore] [IgnoreDataMember] [ProtoIgnore] public bool IsDisposed => RuntimeId == 0; /// /// 当前实体所归属的Scene /// [BsonIgnore] [JsonIgnore] [IgnoreDataMember] [ProtoIgnore] public Scene Scene { get; protected set; } /// /// 实体的父实体 /// [BsonIgnore] [JsonIgnore] [IgnoreDataMember] [ProtoIgnore] public Entity Parent { get; protected set; } /// /// 实体的真实Type /// [BsonIgnore] [JsonIgnore] [IgnoreDataMember] [ProtoIgnore] public Type Type { get; protected set; } #if FANTASY_NET [BsonElement("t")] [BsonIgnoreIfNull] private EntityList _treeDb; [BsonElement("m")] [BsonIgnoreIfNull] private EntityList _multiDb; #endif [BsonIgnore] [IgnoreDataMember] [ProtoIgnore] private EntitySortedDictionary _tree; [BsonIgnore] [IgnoreDataMember] [ProtoIgnore] private EntitySortedDictionary _multi; /// /// 获得父Entity /// /// 父实体的泛型类型 /// public T GetParent() where T : Entity, new() { return Parent as T; } /// /// 获取当前实体的RouteId。 /// public long RouteId => RuntimeId; #endregion #region Create /// /// 创建一个实体 /// /// 所属的Scene /// 实体的Type /// 是否从对象池创建,如果选择的是,销毁的时候同样会进入对象池 /// 是否执行实体事件 /// public static Entity Create(Scene scene, Type type, bool isPool, bool isRunEvent) { return Create(scene, type, scene.EntityIdFactory.Create, isPool, isRunEvent); } /// /// 创建一个实体 /// /// 所属的Scene /// 实体的Type /// 指定实体的Id /// 是否从对象池创建,如果选择的是,销毁的时候同样会进入对象池 /// 是否执行实体事件 /// public static Entity Create(Scene scene, Type type, long id, bool isPool, bool isRunEvent) { if (!typeof(Entity).IsAssignableFrom(type)) { throw new NotSupportedException($"{type.FullName} Type:{type.FullName} must inherit from Entity"); } Entity entity = null; if (isPool) { entity = (Entity)scene.EntityPool.Rent(type); } else { if (!scene.TypeInstance.TryGetValue(type, out var createInstance)) { createInstance = CreateInstance.CreateIPool(type); scene.TypeInstance[type] = createInstance; } entity = (Entity)createInstance(); } entity.Scene = scene; entity.Type = type; entity.SetIsPool(isPool); entity.Id = id; entity.RuntimeId = scene.RuntimeIdFactory.Create; scene.AddEntity(entity); if (isRunEvent) { scene.EntityComponent.Awake(entity); scene.EntityComponent.StartUpdate(entity); } return entity; } /// /// 创建一个实体 /// /// 所属的Scene /// 是否从对象池创建,如果选择的是,销毁的时候同样会进入对象池 /// 是否执行实体事件 /// 要创建的实体泛型类型 /// public static T Create(Scene scene, bool isPool, bool isRunEvent) where T : Entity, new() { return Create(scene, scene.EntityIdFactory.Create, isPool, isRunEvent); } /// /// 创建一个实体 /// /// 所属的Scene /// 指定实体的Id /// 是否从对象池创建,如果选择的是,销毁的时候同样会进入对象池 /// 是否执行实体事件 /// 要创建的实体泛型类型 /// public static T Create(Scene scene, long id, bool isPool, bool isRunEvent) where T : Entity, new() { var entity = isPool ? scene.EntityPool.Rent() : new T(); entity.Scene = scene; entity.Type = typeof(T); entity.SetIsPool(isPool); entity.Id = id; entity.RuntimeId = scene.RuntimeIdFactory.Create; scene.AddEntity(entity); if (isRunEvent) { scene.EntityComponent.Awake(entity); scene.EntityComponent.StartUpdate(entity); } return entity; } #endregion #region AddComponent /// /// 添加一个组件到当前实体上 /// /// 是否从对象池里创建 /// 要添加组件的泛型类型 /// 返回添加到实体上组件的实例 public T AddComponent(bool isPool = true) where T : Entity, new() { var id = SupportedMultiEntityChecker.IsSupported ? Scene.EntityIdFactory.Create : Id; var entity = Create(Scene, id, isPool, false); AddComponent(entity); Scene.EntityComponent.Awake(entity); Scene.EntityComponent.StartUpdate(entity); return entity; } /// /// 添加一个组件到当前实体上 /// /// 要添加组件的Id /// 是否从对象池里创建 /// 要添加组件的泛型类型 /// 返回添加到实体上组件的实例 public T AddComponent(long id, bool isPool = true) where T : Entity, new() { var entity = Create(Scene, id, isPool, false); AddComponent(entity); Scene.EntityComponent.Awake(entity); Scene.EntityComponent.StartUpdate(entity); return entity; } /// /// 添加一个组件到当前实体上 /// /// 要添加的实体实例 public void AddComponent(Entity component) { if (this == component) { Log.Error("Cannot add oneself to one's own components"); return; } if (component.IsDisposed) { Log.Error($"component is Disposed {component.Type.FullName}"); return; } var type = component.Type; component.Parent?.RemoveComponent(component, false); if (component is ISupportedMultiEntity) { _multi ??= Scene.EntitySortedDictionaryPool.Rent(); _multi.Add(component.Id, component); #if FANTASY_NET if (component is ISupportedDataBase) { _multiDb ??= Scene.EntityListPool.Rent(); _multiDb.Add(component); } #endif } else { #if FANTASY_NET if (component is ISupportedSingleCollection && component.Id != Id) { Log.Error($"component type :{type.FullName} for implementing ISupportedSingleCollection, it is required that the Id must be the same as the parent"); } #endif var typeHashCode = Scene.EntityComponent.GetHashCode(type);; if (_tree == null) { _tree = Scene.EntitySortedDictionaryPool.Rent(); } else if (_tree.ContainsKey(typeHashCode)) { Log.Error($"type:{type.FullName} If you want to add multiple components of the same type, please implement IMultiEntity"); return; } _tree.Add(typeHashCode, component); #if FANTASY_NET if (component is ISupportedDataBase) { _treeDb ??= Scene.EntityListPool.Rent(); _treeDb.Add(component); } #endif } component.Parent = this; component.Scene = Scene; } /// /// 添加一个组件到当前实体上 /// /// 要添加的实体实例 /// 要添加组件的泛型类型 public void AddComponent(T component) where T : Entity { var type = typeof(T); if (type == typeof(Entity)) { Log.Error("Cannot add a generic Entity type as a component. Specify a more specific type."); return; } if (this == component) { Log.Error("Cannot add oneself to one's own components"); return; } if (component.IsDisposed) { Log.Error($"component is Disposed {type.FullName}"); return; } component.Parent?.RemoveComponent(component, false); if (SupportedMultiEntityChecker.IsSupported) { _multi ??= Scene.EntitySortedDictionaryPool.Rent(); _multi.Add(component.Id, component); #if FANTASY_NET if (SupportedDataBaseChecker.IsSupported) { _multiDb ??= Scene.EntityListPool.Rent(); _multiDb.Add(component); } #endif } else { #if FANTASY_NET if (SupportedSingleCollectionChecker.IsSupported && component.Id != Id) { Log.Error($"component type :{type.FullName} for implementing ISupportedSingleCollection, it is required that the Id must be the same as the parent"); } #endif var typeHashCode = Scene.EntityComponent.GetHashCode(type); if (_tree == null) { _tree = Scene.EntitySortedDictionaryPool.Rent(); } else if (_tree.ContainsKey(typeHashCode)) { Log.Error($"type:{type.FullName} If you want to add multiple components of the same type, please implement IMultiEntity"); return; } _tree.Add(typeHashCode, component); #if FANTASY_NET if (SupportedDataBaseChecker.IsSupported) { _treeDb ??= Scene.EntityListPool.Rent(); _treeDb.Add(component); } #endif } component.Parent = this; component.Scene = Scene; } /// /// 添加一个组件到当前实体上 /// /// 组件的类型 /// 是否在对象池创建 /// public Entity AddComponent(Type type, bool isPool = true) { var id = typeof(ISupportedMultiEntity).IsAssignableFrom(type) ? Scene.EntityIdFactory.Create : Id; var entity = Entity.Create(Scene, type, id, isPool, false); AddComponent(entity); Scene.EntityComponent.Awake(entity); Scene.EntityComponent.StartUpdate(entity); return entity; } #endregion #region HasComponent /// /// 当前实体上是否有指定类型的组件 /// /// /// public bool HasComponent() where T : Entity, new() { return HasComponent(typeof(T)); } /// /// 当前实体上是否有指定类型的组件 /// /// /// public bool HasComponent(Type type) { if (_tree == null) { return false; } return _tree.ContainsKey(Scene.EntityComponent.GetHashCode(type)); } /// /// 当前实体上是否有指定类型的组件 /// /// /// /// public bool HasComponent(long id) where T : Entity, ISupportedMultiEntity, new() { if (_multi == null) { return false; } return _multi.ContainsKey(id); } #endregion #region GetComponent /// /// 当前实体上查找一个字实体 /// /// 要查找实体泛型类型 /// 查找的实体实例 public T GetComponent() where T : Entity, new() { if (_tree == null) { return null; } var typeHashCode = Scene.EntityComponent.GetHashCode(typeof(T)); return _tree.TryGetValue(typeHashCode, out var component) ? (T)component : null; } /// /// 当前实体上查找一个字实体 /// /// 要查找实体类型 /// 查找的实体实例 public Entity GetComponent(Type type) { if (_tree == null) { return null; } var typeHashCode = Scene.EntityComponent.GetHashCode(type); return _tree.TryGetValue(typeHashCode, out var component) ? component : null; } /// /// 当前实体上查找一个字实体 /// /// 要查找实体的Id /// 要查找实体泛型类型 /// 查找的实体实例 public T GetComponent(long id) where T : Entity, ISupportedMultiEntity, new() { if (_multi == null) { return default; } return _multi.TryGetValue(id, out var entity) ? (T)entity : default; } /// /// 当前实体上查找一个字实体,如果没有就创建一个新的并添加到当前实体上 /// /// 是否从对象池创建 /// 要查找或添加实体泛型类型 /// 查找的实体实例 public T GetOrAddComponent(bool isPool = true) where T : Entity, new() { return GetComponent() ?? AddComponent(isPool); } #endregion #region RemoveComponent /// /// 当前实体下删除一个实体 /// /// 是否执行删除实体的Dispose方法 /// 实体的泛型类型 /// public void RemoveComponent(bool isDispose = true) where T : Entity, new() { if (SupportedMultiEntityChecker.IsSupported) { throw new NotSupportedException($"{typeof(T).FullName} message:Cannot delete components that implement the ISupportedMultiEntity interface"); } if (_tree == null) { return; } var type = typeof(T); var typeHashCode = Scene.EntityComponent.GetHashCode(type); if (!_tree.TryGetValue(typeHashCode, out var component)) { return; } #if FANTASY_NET if (_treeDb != null && SupportedDataBaseChecker.IsSupported) { _treeDb.Remove(component); if (_treeDb.Count == 0) { Scene.EntityListPool.Return(_treeDb); _treeDb = null; } } #endif _tree.Remove(typeHashCode); if (_tree.Count == 0) { Scene.EntitySortedDictionaryPool.Return(_tree); _tree = null; } if (isDispose) { component.Dispose(); } } /// /// 当前实体下删除一个实体 /// /// 要删除的实体Id /// 是否执行删除实体的Dispose方法 /// 实体的泛型类型 public void RemoveComponent(long id, bool isDispose = true) where T : Entity, ISupportedMultiEntity, new() { if (_multi == null) { return; } if (!_multi.TryGetValue(id, out var component)) { return; } #if FANTASY_NET if (SupportedDataBaseChecker.IsSupported) { _multiDb.Remove(component); if (_multiDb.Count == 0) { Scene.EntityListPool.Return(_multiDb); _multiDb = null; } } #endif _multi.Remove(component.Id); if (_multi.Count == 0) { Scene.EntitySortedDictionaryPool.Return(_multi); _multi = null; } if (isDispose) { component.Dispose(); } } /// /// 当前实体下删除一个实体 /// /// 要删除的实体实例 /// 是否执行删除实体的Dispose方法 public void RemoveComponent(Entity component, bool isDispose = true) { if (this == component) { return; } if (component is ISupportedMultiEntity) { if (_multi != null) { if (!_multi.ContainsKey(component.Id)) { return; } #if FANTASY_NET if (component is ISupportedDataBase) { _multiDb.Remove(component); if (_multiDb.Count == 0) { Scene.EntityListPool.Return(_multiDb); _multiDb = null; } } #endif _multi.Remove(component.Id); if (_multi.Count == 0) { Scene.EntitySortedDictionaryPool.Return(_multi); _multi = null; } } } else if (_tree != null) { var typeHashCode = Scene.EntityComponent.GetHashCode(component.Type); if (!_tree.ContainsKey(typeHashCode)) { return; } #if FANTASY_NET if (_treeDb != null && component is ISupportedDataBase) { _treeDb.Remove(component); if (_treeDb.Count == 0) { Scene.EntityListPool.Return(_treeDb); _treeDb = null; } } #endif _tree.Remove(typeHashCode); if (_tree.Count == 0) { Scene.EntitySortedDictionaryPool.Return(_tree); _tree = null; } } if (isDispose) { component.Dispose(); } } /// /// 当前实体下删除一个实体 /// /// 要删除的实体实例 /// 是否执行删除实体的Dispose方法 /// 实体的泛型类型 public void RemoveComponent(T component, bool isDispose = true) where T : Entity { if (this == component) { return; } if (typeof(T) == typeof(Entity)) { Log.Error("Cannot remove a generic Entity type as a component. Specify a more specific type."); return; } if (SupportedMultiEntityChecker.IsSupported) { if (_multi != null) { if (!_multi.ContainsKey(component.Id)) { return; } #if FANTASY_NET if (SupportedDataBaseChecker.IsSupported) { _multiDb.Remove(component); if (_multiDb.Count == 0) { Scene.EntityListPool.Return(_multiDb); _multiDb = null; } } #endif _multi.Remove(component.Id); if (_multi.Count == 0) { Scene.EntitySortedDictionaryPool.Return(_multi); _multi = null; } } } else if (_tree != null) { var typeHashCode = Scene.EntityComponent.GetHashCode(typeof(T)); if (!_tree.ContainsKey(typeHashCode)) { return; } #if FANTASY_NET if (_treeDb != null && SupportedDataBaseChecker.IsSupported) { _treeDb.Remove(component); if (_treeDb.Count == 0) { Scene.EntityListPool.Return(_treeDb); _treeDb = null; } } #endif _tree.Remove(typeHashCode); if (_tree.Count == 0) { Scene.EntitySortedDictionaryPool.Return(_tree); _tree = null; } } if (isDispose) { component.Dispose(); } } #endregion #region Deserialize /// /// 反序列化当前实体,因为在数据库加载过来的或通过协议传送过来的实体并没有跟当前Scene做关联。 /// 所以必须要执行一下这个反序列化的方法才可以使用。 /// /// Scene /// 是否是重新生成实体的Id,如果是数据库加载过来的一般是不需要的 public void Deserialize(Scene scene, bool resetId = false) { if (RuntimeId != 0) { return; } try { Scene = scene; Type ??= GetType(); RuntimeId = Scene.RuntimeIdFactory.Create; if (resetId) { Id = RuntimeId; } #if FANTASY_NET if (_treeDb != null && _treeDb.Count > 0) { _tree = Scene.EntitySortedDictionaryPool.Rent(); foreach (var entity in _treeDb) { entity.Parent = this; entity.Type = entity.GetType(); var typeHashCode = Scene.EntityComponent.GetHashCode(entity.Type); _tree.Add(typeHashCode, entity); entity.Deserialize(scene, resetId); } } if (_multiDb != null && _multiDb.Count > 0) { _multi = Scene.EntitySortedDictionaryPool.Rent(); foreach (var entity in _multiDb) { entity.Parent = this; entity.Deserialize(scene, resetId); _multi.Add(entity.Id, entity); } } #endif scene.AddEntity(this); scene.EntityComponent.Deserialize(this); } catch (Exception e) { if (RuntimeId != 0) { scene.RemoveEntity(RuntimeId); } Log.Error(e); } } #endregion #region ForEach #if FANTASY_NET /// /// 查询当前实体下支持数据库分表存储实体 /// [BsonIgnore] [JsonIgnore] [IgnoreDataMember] [ProtoIgnore] public IEnumerable ForEachSingleCollection { get { foreach (var (_, treeEntity) in _tree) { if (treeEntity is not ISupportedSingleCollection) { continue; } yield return treeEntity; } } } /// /// 查询当前实体下支持传送实体 /// [BsonIgnore] [JsonIgnore] [IgnoreDataMember] [ProtoIgnore] public IEnumerable ForEachTransfer { get { if (_tree != null) { foreach (var (_, treeEntity) in _tree) { if (treeEntity is ISupportedTransfer) { yield return treeEntity; } } } if (_multiDb != null) { foreach (var treeEntity in _multiDb) { if (treeEntity is not ISupportedTransfer) { continue; } yield return treeEntity; } } } } #endif /// /// 查询当前实体下的实现了ISupportedMultiEntity接口的实体 /// [BsonIgnore] [JsonIgnore] [IgnoreDataMember] [ProtoIgnore] public IEnumerable ForEachMultiEntity { get { if (_multi == null) { yield break; } foreach (var (_, supportedMultiEntity) in _multi) { yield return supportedMultiEntity; } } } /// /// 查找当前实体下的所有实体,不包括实现ISupportedMultiEntity接口的实体 /// [BsonIgnore] [JsonIgnore] [IgnoreDataMember] [ProtoIgnore] public IEnumerable ForEachEntity { get { if (_tree == null) { yield break; } foreach (var (_, entity) in _tree) { yield return entity; } } } #endregion #region Dispose /// /// 销毁当前实体,销毁后会自动销毁当前实体下的所有实体。 /// public virtual void Dispose() { if (IsDisposed) { return; } var scene = Scene; var runTimeId = RuntimeId; RuntimeId = 0; if (_tree != null) { foreach (var (_, entity) in _tree) { entity.Dispose(); } _tree.Clear(); scene.EntitySortedDictionaryPool.Return(_tree); _tree = null; } if (_multi != null) { foreach (var (_, entity) in _multi) { entity.Dispose(); } _multi.Clear(); scene.EntitySortedDictionaryPool.Return(_multi); _multi = null; } #if FANTASY_NET if (_treeDb != null) { foreach (var entity in _treeDb) { entity.Dispose(); } _treeDb.Clear(); scene.EntityListPool.Return(_treeDb); _treeDb = null; } if (_multiDb != null) { foreach (var entity in _multiDb) { entity.Dispose(); } _multiDb.Clear(); scene.EntityListPool.Return(_multiDb); _multiDb = null; } #endif scene.EntityComponent.Destroy(this); if (Parent != null && Parent != this && !Parent.IsDisposed) { Parent.RemoveComponent(this, false); Parent = null; } Id = 0; Scene = null; Parent = null; scene.RemoveEntity(runTimeId); if (IsPool()) { scene.EntityPool.Return(Type, this); } Type = null; } #endregion #region Pool /// /// 获取一个值,该值指示当前实例是否为对象池中的实例。 /// /// public bool IsPool() { return _isPool; } /// /// 设置一个值,该值指示当前实例是否为对象池中的实例。 /// /// public void SetIsPool(bool isPool) { _isPool = isPool; } #endregion } }