diff --git a/Assets/GameMain/Scripts/Runtime/BuiltinComponent/AsyncTask/EntityAsyncExtension.cs b/Assets/GameMain/Scripts/Runtime/BuiltinComponent/AsyncTask/EntityAsyncExtension.cs index ea447e4..9f1a182 100644 --- a/Assets/GameMain/Scripts/Runtime/BuiltinComponent/AsyncTask/EntityAsyncExtension.cs +++ b/Assets/GameMain/Scripts/Runtime/BuiltinComponent/AsyncTask/EntityAsyncExtension.cs @@ -1,5 +1,12 @@ using System; +using System.Collections.Generic; +using System.Threading; using Cysharp.Threading.Tasks; +using SepCore.CustomUtility; +using SepCore.DataTable; +using SepCore.Definition; +using SepCore.Entity; +using SepCore.Entity.Weapon; using UnityGameFramework.Runtime; using HideEntityCompleteEventArgs = UnityGameFramework.Runtime.HideEntityCompleteEventArgs; using ShowEntityFailureEventArgs = UnityGameFramework.Runtime.ShowEntityFailureEventArgs; @@ -12,6 +19,11 @@ namespace SepCore.AsyncTask /// public static class EntityAsyncExtension { + private const string EntityNamespace = "SepCore.Entity."; + + private static readonly Dictionary _typeDict = new(); + private static readonly Dictionary _assetNameDict = new(); + /// /// 异步显示实体 /// @@ -22,6 +34,7 @@ namespace SepCore.AsyncTask /// 实体组名称 /// 用户自定义数据 /// 超时时间(秒),0表示不超时 + /// 取消令牌 /// 显示的实体 public static UniTask ShowEntityAsync(this EntityComponent entityComponent, int entityId, @@ -29,17 +42,46 @@ namespace SepCore.AsyncTask string entityAssetName, string entityGroupName, object userData = null, - float timeout = 30f) + float timeout = 30f, + CancellationToken cancellationToken = default) + { + return ShowEntityAsync(entityComponent, entityId, entityLogicType, entityAssetName, entityGroupName, 0, + userData, timeout, cancellationToken); + } + + /// + /// 异步显示实体 + /// + /// 实体组件 + /// 实体编号 + /// 实体逻辑类型 + /// 实体资源名称 + /// 实体组名称 + /// 加载优先级 + /// 用户自定义数据 + /// 超时时间(秒),0表示不超时 + /// 取消令牌 + /// 显示的实体 + public static UniTask ShowEntityAsync(this EntityComponent entityComponent, + int entityId, + Type entityLogicType, + string entityAssetName, + string entityGroupName, + int priority, + object userData = null, + float timeout = 30f, + CancellationToken cancellationToken = default) { UniTask waitTask = AsyncTaskHelper.WaitSuccessOrFailureAsync( ShowEntitySuccessEventArgs.EventId, ShowEntityFailureEventArgs.EventId, successArgs => successArgs.Entity.Id == entityId && ReferenceEquals(successArgs.UserData, userData), failureArgs => failureArgs.EntityId == entityId && ReferenceEquals(failureArgs.UserData, userData), - timeout + timeout, + cancellationToken ).ContinueWith(successArgs => successArgs.Entity); - entityComponent.ShowEntity(entityId, entityLogicType, entityAssetName, entityGroupName, userData); + entityComponent.ShowEntity(entityId, entityLogicType, entityAssetName, entityGroupName, priority, userData); return waitTask; } @@ -53,26 +95,157 @@ namespace SepCore.AsyncTask /// 实体组名称 /// 用户自定义数据 /// 超时时间(秒),0表示不超时 + /// 取消令牌 /// 显示的实体 public static UniTask ShowEntityAsync(this EntityComponent entityComponent, int entityId, string entityAssetName, string entityGroupName, object userData = null, - float timeout = 30f) where T : EntityLogic + float timeout = 30f, + CancellationToken cancellationToken = default) where T : EntityLogic + { + return ShowEntityAsync(entityComponent, entityId, entityAssetName, entityGroupName, 0, userData, timeout, + cancellationToken); + } + + /// + /// 异步显示实体(泛型版本) + /// + /// 实体逻辑类型 + /// 实体组件 + /// 实体编号 + /// 实体资源名称 + /// 实体组名称 + /// 加载优先级 + /// 用户自定义数据 + /// 超时时间(秒),0表示不超时 + /// 取消令牌 + /// 显示的实体 + public static UniTask ShowEntityAsync(this EntityComponent entityComponent, + int entityId, + string entityAssetName, + string entityGroupName, + int priority, + object userData = null, + float timeout = 30f, + CancellationToken cancellationToken = default) where T : EntityLogic { UniTask waitTask = AsyncTaskHelper.WaitSuccessOrFailureAsync( ShowEntitySuccessEventArgs.EventId, ShowEntityFailureEventArgs.EventId, successArgs => successArgs.Entity.Id == entityId && ReferenceEquals(successArgs.UserData, userData), failureArgs => failureArgs.EntityId == entityId && ReferenceEquals(failureArgs.UserData, userData), - timeout + timeout, + cancellationToken ).ContinueWith(successArgs => (T)successArgs.Entity.Logic); - entityComponent.ShowEntity(entityId, entityAssetName, entityGroupName, userData); + entityComponent.ShowEntity(entityId, entityAssetName, entityGroupName, priority, userData); return waitTask; } + /// + /// 异步显示玩家实体。 + /// + public static UniTask ShowPlayerAsync(this EntityComponent entityComponent, + PlayerData data, + float timeout = 30f, + CancellationToken cancellationToken = default) + { + return ShowEntityByDataAsync(entityComponent, typeof(Player), "Player", + Constant.AssetPriority.PlayerAsset, data, timeout, cancellationToken); + } + + /// + /// 异步显示敌人实体。 + /// + public static UniTask ShowEnemyAsync(this EntityComponent entityComponent, + EnemyData data, + float timeout = 30f, + CancellationToken cancellationToken = default) + { + if (data == null) + { + Log.Warning("Enemy data is invalid."); + return UniTask.FromResult(null); + } + + Type enemyType = TryGetType(data.EnemyType.ToString()); + string assetName = TryGetAssetName(data.EntityTypeId); + if (enemyType == null || string.IsNullOrEmpty(assetName)) + { + return UniTask.FromResult(null); + } + + return entityComponent + .ShowEntityAsync(data.Id, enemyType, AssetUtility.GetEntityAsset(assetName), "Enemy", + Constant.AssetPriority.BulletAsset, data, timeout, cancellationToken) + .ContinueWith(entity => entity?.Logic as EnemyBase); + } + + /// + /// 异步显示武器实体。 + /// + public static UniTask ShowWeaponAsync(this EntityComponent entityComponent, + WeaponData data, + float timeout = 30f, + CancellationToken cancellationToken = default) + { + if (data == null) + { + Log.Warning("Weapon data is invalid."); + return UniTask.FromResult(null); + } + + Type weaponType = TryGetType("Weapon." + data.WeaponType); + string assetName = TryGetAssetName(data.EntityTypeId); + if (weaponType == null || string.IsNullOrEmpty(assetName)) + { + return UniTask.FromResult(null); + } + + return entityComponent + .ShowEntityAsync(data.Id, weaponType, AssetUtility.GetEntityAsset(assetName), "Weapon", + Constant.AssetPriority.BulletAsset, data, timeout, cancellationToken) + .ContinueWith(entity => entity?.Logic as WeaponBase); + } + + /// + /// 异步显示特效实体。 + /// + public static UniTask ShowEffectAsync(this EntityComponent entityComponent, + EffectData data, + float timeout = 30f, + CancellationToken cancellationToken = default) + { + return ShowEntityByDataAsync(entityComponent, typeof(Effect), "Effect", + Constant.AssetPriority.EffectAsset, data, timeout, cancellationToken); + } + + /// + /// 异步显示金币掉落实体。 + /// + public static UniTask ShowCoinAsync(this EntityComponent entityComponent, + CoinData data, + float timeout = 30f, + CancellationToken cancellationToken = default) + { + return ShowEntityByDataAsync(entityComponent, typeof(CoinEntity), "Drop", + Constant.AssetPriority.EffectAsset, data, timeout, cancellationToken); + } + + /// + /// 异步显示经验掉落实体。 + /// + public static UniTask ShowExpAsync(this EntityComponent entityComponent, + ExpData data, + float timeout = 30f, + CancellationToken cancellationToken = default) + { + return ShowEntityByDataAsync(entityComponent, typeof(ExpEntity), "Drop", + Constant.AssetPriority.EffectAsset, data, timeout, cancellationToken); + } + /// /// 异步隐藏实体 /// @@ -80,16 +253,19 @@ namespace SepCore.AsyncTask /// 实体编号 /// 用户自定义数据 /// 超时时间(秒),0表示不超时 + /// 取消令牌 /// 隐藏完成事件 public static UniTask HideEntityAsync(this EntityComponent entityComponent, int entityId, object userData = null, - float timeout = 30f) + float timeout = 30f, + CancellationToken cancellationToken = default) { UniTask waitTask = AsyncTaskHelper.WaitEventAsync( HideEntityCompleteEventArgs.EventId, args => args.EntityId == entityId, - timeout + timeout, + cancellationToken ); entityComponent.HideEntity(entityId, userData); @@ -103,13 +279,76 @@ namespace SepCore.AsyncTask /// 要隐藏的实体 /// 用户自定义数据 /// 超时时间(秒),0表示不超时 + /// 取消令牌 /// 隐藏完成事件 public static UniTask HideEntityAsync(this EntityComponent entityComponent, UnityGameFramework.Runtime.Entity entity, object userData = null, - float timeout = 30f) + float timeout = 30f, + CancellationToken cancellationToken = default) { - return HideEntityAsync(entityComponent, entity.Id, userData, timeout); + return HideEntityAsync(entityComponent, entity.Id, userData, timeout, cancellationToken); + } + + private static UniTask ShowEntityByDataAsync(EntityComponent entityComponent, + Type logicType, + string entityGroupName, + int priority, + EntityDataBase data, + float timeout, + CancellationToken cancellationToken) where T : EntityLogic + { + if (data == null) + { + Log.Warning("Data is invalid."); + return UniTask.FromResult(null); + } + + DREntity drEntity = GameEntry.DataTable.GetDataTableRow(data.TypeId); + if (drEntity == null) + { + Log.Warning("Can not load entity id '{0}' from data table.", data.TypeId.ToString()); + return UniTask.FromResult(null); + } + + return entityComponent.ShowEntityAsync(data.Id, AssetUtility.GetEntityAsset(drEntity.AssetName), + entityGroupName, priority, data, timeout, cancellationToken); + } + + private static Type TryGetType(string rawTypeName) + { + string typeName = EntityNamespace + rawTypeName; + if (!_typeDict.TryGetValue(typeName, out Type type)) + { + type = Type.GetType(typeName); + if (type == null) + { + Log.Warning("Can not load entity type '{0}'.", typeName); + return null; + } + + _typeDict.Add(typeName, type); + } + + return type; + } + + private static string TryGetAssetName(int entityId) + { + if (!_assetNameDict.TryGetValue(entityId, out string assetName)) + { + DREntity drEntity = GameEntry.DataTable.GetDataTableRow(entityId); + if (drEntity == null) + { + Log.Warning("Can not load entity id '{0}' from data table.", entityId.ToString()); + return null; + } + + assetName = drEntity.AssetName; + _assetNameDict.Add(entityId, assetName); + } + + return assetName; } } }