1051 lines
34 KiB
C#
1051 lines
34 KiB
C#
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
|
||
{
|
||
/// <summary>
|
||
/// 用来表示一个Entity
|
||
/// </summary>
|
||
public interface IEntity : IDisposable, IPool { }
|
||
|
||
/// <summary>
|
||
/// Entity的抽象类,任何Entity必须继承这个接口才可以使用
|
||
/// </summary>
|
||
public abstract partial class Entity : IEntity
|
||
{
|
||
#region Members
|
||
|
||
/// <summary>
|
||
/// 获取一个值,表示实体是否支持对象池。
|
||
/// </summary>
|
||
[BsonIgnore]
|
||
[JsonIgnore]
|
||
[ProtoIgnore]
|
||
[IgnoreDataMember]
|
||
private bool _isPool;
|
||
/// <summary>
|
||
/// 实体的Id
|
||
/// </summary>
|
||
[BsonId]
|
||
[BsonElement]
|
||
[BsonIgnoreIfDefault]
|
||
[BsonDefaultValue(0L)]
|
||
public long Id { get; protected set; }
|
||
/// <summary>
|
||
/// 实体的RunTimeId,其他系统可以通过这个Id发送Route消息,这个Id也可以理解为RouteId
|
||
/// </summary>
|
||
[BsonIgnore]
|
||
[IgnoreDataMember]
|
||
[ProtoIgnore]
|
||
public long RuntimeId { get; protected set; }
|
||
/// <summary>
|
||
/// 当前实体是否已经被销毁
|
||
/// </summary>
|
||
[BsonIgnore]
|
||
[JsonIgnore]
|
||
[IgnoreDataMember]
|
||
[ProtoIgnore]
|
||
public bool IsDisposed => RuntimeId == 0;
|
||
/// <summary>
|
||
/// 当前实体所归属的Scene
|
||
/// </summary>
|
||
[BsonIgnore]
|
||
[JsonIgnore]
|
||
[IgnoreDataMember]
|
||
[ProtoIgnore]
|
||
public Scene Scene { get; protected set; }
|
||
/// <summary>
|
||
/// 实体的父实体
|
||
/// </summary>
|
||
[BsonIgnore]
|
||
[JsonIgnore]
|
||
[IgnoreDataMember]
|
||
[ProtoIgnore]
|
||
public Entity Parent { get; protected set; }
|
||
/// <summary>
|
||
/// 实体的真实Type
|
||
/// </summary>
|
||
[BsonIgnore]
|
||
[JsonIgnore]
|
||
[IgnoreDataMember]
|
||
[ProtoIgnore]
|
||
public Type Type { get; protected set; }
|
||
#if FANTASY_NET
|
||
[BsonElement("t")] [BsonIgnoreIfNull] private EntityList<Entity> _treeDb;
|
||
[BsonElement("m")] [BsonIgnoreIfNull] private EntityList<Entity> _multiDb;
|
||
#endif
|
||
[BsonIgnore] [IgnoreDataMember] [ProtoIgnore] private EntitySortedDictionary<long, Entity> _tree;
|
||
[BsonIgnore] [IgnoreDataMember] [ProtoIgnore] private EntitySortedDictionary<long, Entity> _multi;
|
||
|
||
/// <summary>
|
||
/// 获得父Entity
|
||
/// </summary>
|
||
/// <typeparam name="T">父实体的泛型类型</typeparam>
|
||
/// <returns></returns>
|
||
public T GetParent<T>() where T : Entity, new()
|
||
{
|
||
return Parent as T;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取当前实体的RouteId。
|
||
/// </summary>
|
||
public long RouteId => RuntimeId;
|
||
|
||
#endregion
|
||
|
||
#region Create
|
||
|
||
/// <summary>
|
||
/// 创建一个实体
|
||
/// </summary>
|
||
/// <param name="scene">所属的Scene</param>
|
||
/// <param name="type">实体的Type</param>
|
||
/// <param name="isPool">是否从对象池创建,如果选择的是,销毁的时候同样会进入对象池</param>
|
||
/// <param name="isRunEvent">是否执行实体事件</param>
|
||
/// <returns></returns>
|
||
public static Entity Create(Scene scene, Type type, bool isPool, bool isRunEvent)
|
||
{
|
||
return Create(scene, type, scene.EntityIdFactory.Create, isPool, isRunEvent);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建一个实体
|
||
/// </summary>
|
||
/// <param name="scene">所属的Scene</param>
|
||
/// <param name="type">实体的Type</param>
|
||
/// <param name="id">指定实体的Id</param>
|
||
/// <param name="isPool">是否从对象池创建,如果选择的是,销毁的时候同样会进入对象池</param>
|
||
/// <param name="isRunEvent">是否执行实体事件</param>
|
||
/// <returns></returns>
|
||
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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建一个实体
|
||
/// </summary>
|
||
/// <param name="scene">所属的Scene</param>
|
||
/// <param name="isPool">是否从对象池创建,如果选择的是,销毁的时候同样会进入对象池</param>
|
||
/// <param name="isRunEvent">是否执行实体事件</param>
|
||
/// <typeparam name="T">要创建的实体泛型类型</typeparam>
|
||
/// <returns></returns>
|
||
public static T Create<T>(Scene scene, bool isPool, bool isRunEvent) where T : Entity, new()
|
||
{
|
||
return Create<T>(scene, scene.EntityIdFactory.Create, isPool, isRunEvent);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建一个实体
|
||
/// </summary>
|
||
/// <param name="scene">所属的Scene</param>
|
||
/// <param name="id">指定实体的Id</param>
|
||
/// <param name="isPool">是否从对象池创建,如果选择的是,销毁的时候同样会进入对象池</param>
|
||
/// <param name="isRunEvent">是否执行实体事件</param>
|
||
/// <typeparam name="T">要创建的实体泛型类型</typeparam>
|
||
/// <returns></returns>
|
||
public static T Create<T>(Scene scene, long id, bool isPool, bool isRunEvent) where T : Entity, new()
|
||
{
|
||
var entity = isPool ? scene.EntityPool.Rent<T>() : 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
|
||
|
||
/// <summary>
|
||
/// 添加一个组件到当前实体上
|
||
/// </summary>
|
||
/// <param name="isPool">是否从对象池里创建</param>
|
||
/// <typeparam name="T">要添加组件的泛型类型</typeparam>
|
||
/// <returns>返回添加到实体上组件的实例</returns>
|
||
public T AddComponent<T>(bool isPool = true) where T : Entity, new()
|
||
{
|
||
var id = SupportedMultiEntityChecker<T>.IsSupported ? Scene.EntityIdFactory.Create : Id;
|
||
var entity = Create<T>(Scene, id, isPool, false);
|
||
AddComponent(entity);
|
||
Scene.EntityComponent.Awake(entity);
|
||
Scene.EntityComponent.StartUpdate(entity);
|
||
return entity;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 添加一个组件到当前实体上
|
||
/// </summary>
|
||
/// <param name="id">要添加组件的Id</param>
|
||
/// <param name="isPool">是否从对象池里创建</param>
|
||
/// <typeparam name="T">要添加组件的泛型类型</typeparam>
|
||
/// <returns>返回添加到实体上组件的实例</returns>
|
||
public T AddComponent<T>(long id, bool isPool = true) where T : Entity, new()
|
||
{
|
||
var entity = Create<T>(Scene, id, isPool, false);
|
||
AddComponent(entity);
|
||
Scene.EntityComponent.Awake(entity);
|
||
Scene.EntityComponent.StartUpdate(entity);
|
||
return entity;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 添加一个组件到当前实体上
|
||
/// </summary>
|
||
/// <param name="component">要添加的实体实例</param>
|
||
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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 添加一个组件到当前实体上
|
||
/// </summary>
|
||
/// <param name="component">要添加的实体实例</param>
|
||
/// <typeparam name="T">要添加组件的泛型类型</typeparam>
|
||
public void AddComponent<T>(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<T>.IsSupported)
|
||
{
|
||
_multi ??= Scene.EntitySortedDictionaryPool.Rent();
|
||
_multi.Add(component.Id, component);
|
||
#if FANTASY_NET
|
||
if (SupportedDataBaseChecker<T>.IsSupported)
|
||
{
|
||
_multiDb ??= Scene.EntityListPool.Rent();
|
||
_multiDb.Add(component);
|
||
}
|
||
#endif
|
||
}
|
||
else
|
||
{
|
||
#if FANTASY_NET
|
||
if (SupportedSingleCollectionChecker<T>.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<T>.IsSupported)
|
||
{
|
||
_treeDb ??= Scene.EntityListPool.Rent();
|
||
_treeDb.Add(component);
|
||
}
|
||
#endif
|
||
}
|
||
|
||
component.Parent = this;
|
||
component.Scene = Scene;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 添加一个组件到当前实体上
|
||
/// </summary>
|
||
/// <param name="type">组件的类型</param>
|
||
/// <param name="isPool">是否在对象池创建</param>
|
||
/// <returns></returns>
|
||
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
|
||
|
||
/// <summary>
|
||
/// 当前实体上是否有指定类型的组件
|
||
/// </summary>
|
||
/// <typeparam name="T"></typeparam>
|
||
/// <returns></returns>
|
||
public bool HasComponent<T>() where T : Entity, new()
|
||
{
|
||
return HasComponent(typeof(T));
|
||
}
|
||
|
||
/// <summary>
|
||
/// 当前实体上是否有指定类型的组件
|
||
/// </summary>
|
||
/// <param name="type"></param>
|
||
/// <returns></returns>
|
||
public bool HasComponent(Type type)
|
||
{
|
||
if (_tree == null)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
return _tree.ContainsKey(Scene.EntityComponent.GetHashCode(type));
|
||
}
|
||
|
||
/// <summary>
|
||
/// 当前实体上是否有指定类型的组件
|
||
/// </summary>
|
||
/// <param name="id"></param>
|
||
/// <typeparam name="T"></typeparam>
|
||
/// <returns></returns>
|
||
public bool HasComponent<T>(long id) where T : Entity, ISupportedMultiEntity, new()
|
||
{
|
||
if (_multi == null)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
return _multi.ContainsKey(id);
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region GetComponent
|
||
|
||
/// <summary>
|
||
/// 当前实体上查找一个字实体
|
||
/// </summary>
|
||
/// <typeparam name="T">要查找实体泛型类型</typeparam>
|
||
/// <returns>查找的实体实例</returns>
|
||
public T GetComponent<T>() 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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 当前实体上查找一个字实体
|
||
/// </summary>
|
||
/// <param name="type">要查找实体类型</param>
|
||
/// <returns>查找的实体实例</returns>
|
||
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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 当前实体上查找一个字实体
|
||
/// </summary>
|
||
/// <param name="id">要查找实体的Id</param>
|
||
/// <typeparam name="T">要查找实体泛型类型</typeparam>
|
||
/// <returns>查找的实体实例</returns>
|
||
public T GetComponent<T>(long id) where T : Entity, ISupportedMultiEntity, new()
|
||
{
|
||
if (_multi == null)
|
||
{
|
||
return default;
|
||
}
|
||
|
||
return _multi.TryGetValue(id, out var entity) ? (T)entity : default;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 当前实体上查找一个字实体,如果没有就创建一个新的并添加到当前实体上
|
||
/// </summary>
|
||
/// <param name="isPool">是否从对象池创建</param>
|
||
/// <typeparam name="T">要查找或添加实体泛型类型</typeparam>
|
||
/// <returns>查找的实体实例</returns>
|
||
public T GetOrAddComponent<T>(bool isPool = true) where T : Entity, new()
|
||
{
|
||
return GetComponent<T>() ?? AddComponent<T>(isPool);
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region RemoveComponent
|
||
|
||
/// <summary>
|
||
/// 当前实体下删除一个实体
|
||
/// </summary>
|
||
/// <param name="isDispose">是否执行删除实体的Dispose方法</param>
|
||
/// <typeparam name="T">实体的泛型类型</typeparam>
|
||
/// <exception cref="NotSupportedException"></exception>
|
||
public void RemoveComponent<T>(bool isDispose = true) where T : Entity, new()
|
||
{
|
||
if (SupportedMultiEntityChecker<T>.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<T>.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();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 当前实体下删除一个实体
|
||
/// </summary>
|
||
/// <param name="id">要删除的实体Id</param>
|
||
/// <param name="isDispose">是否执行删除实体的Dispose方法</param>
|
||
/// <typeparam name="T">实体的泛型类型</typeparam>
|
||
public void RemoveComponent<T>(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<T>.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();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 当前实体下删除一个实体
|
||
/// </summary>
|
||
/// <param name="component">要删除的实体实例</param>
|
||
/// <param name="isDispose">是否执行删除实体的Dispose方法</param>
|
||
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();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 当前实体下删除一个实体
|
||
/// </summary>
|
||
/// <param name="component">要删除的实体实例</param>
|
||
/// <param name="isDispose">是否执行删除实体的Dispose方法</param>
|
||
/// <typeparam name="T">实体的泛型类型</typeparam>
|
||
public void RemoveComponent<T>(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<T>.IsSupported)
|
||
{
|
||
if (_multi != null)
|
||
{
|
||
if (!_multi.ContainsKey(component.Id))
|
||
{
|
||
return;
|
||
}
|
||
#if FANTASY_NET
|
||
if (SupportedDataBaseChecker<T>.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<T>.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
|
||
|
||
/// <summary>
|
||
/// 反序列化当前实体,因为在数据库加载过来的或通过协议传送过来的实体并没有跟当前Scene做关联。
|
||
/// 所以必须要执行一下这个反序列化的方法才可以使用。
|
||
/// </summary>
|
||
/// <param name="scene">Scene</param>
|
||
/// <param name="resetId">是否是重新生成实体的Id,如果是数据库加载过来的一般是不需要的</param>
|
||
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
|
||
/// <summary>
|
||
/// 查询当前实体下支持数据库分表存储实体
|
||
/// </summary>
|
||
[BsonIgnore]
|
||
[JsonIgnore]
|
||
[IgnoreDataMember]
|
||
[ProtoIgnore]
|
||
public IEnumerable<Entity> ForEachSingleCollection
|
||
{
|
||
get
|
||
{
|
||
foreach (var (_, treeEntity) in _tree)
|
||
{
|
||
if (treeEntity is not ISupportedSingleCollection)
|
||
{
|
||
continue;
|
||
}
|
||
|
||
yield return treeEntity;
|
||
}
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 查询当前实体下支持传送实体
|
||
/// </summary>
|
||
[BsonIgnore]
|
||
[JsonIgnore]
|
||
[IgnoreDataMember]
|
||
[ProtoIgnore]
|
||
public IEnumerable<Entity> 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
|
||
/// <summary>
|
||
/// 查询当前实体下的实现了ISupportedMultiEntity接口的实体
|
||
/// </summary>
|
||
[BsonIgnore]
|
||
[JsonIgnore]
|
||
[IgnoreDataMember]
|
||
[ProtoIgnore]
|
||
public IEnumerable<Entity> ForEachMultiEntity
|
||
{
|
||
get
|
||
{
|
||
if (_multi == null)
|
||
{
|
||
yield break;
|
||
}
|
||
|
||
foreach (var (_, supportedMultiEntity) in _multi)
|
||
{
|
||
yield return supportedMultiEntity;
|
||
}
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 查找当前实体下的所有实体,不包括实现ISupportedMultiEntity接口的实体
|
||
/// </summary>
|
||
[BsonIgnore]
|
||
[JsonIgnore]
|
||
[IgnoreDataMember]
|
||
[ProtoIgnore]
|
||
public IEnumerable<Entity> ForEachEntity
|
||
{
|
||
get
|
||
{
|
||
if (_tree == null)
|
||
{
|
||
yield break;
|
||
}
|
||
|
||
foreach (var (_, entity) in _tree)
|
||
{
|
||
yield return entity;
|
||
}
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
#region Dispose
|
||
|
||
/// <summary>
|
||
/// 销毁当前实体,销毁后会自动销毁当前实体下的所有实体。
|
||
/// </summary>
|
||
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
|
||
|
||
/// <summary>
|
||
/// 获取一个值,该值指示当前实例是否为对象池中的实例。
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
public bool IsPool()
|
||
{
|
||
return _isPool;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置一个值,该值指示当前实例是否为对象池中的实例。
|
||
/// </summary>
|
||
/// <param name="isPool"></param>
|
||
public void SetIsPool(bool isPool)
|
||
{
|
||
_isPool = isPool;
|
||
}
|
||
|
||
#endregion
|
||
}
|
||
} |