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; using ShowEntitySuccessEventArgs = UnityGameFramework.Runtime.ShowEntitySuccessEventArgs; namespace SepCore.AsyncTask { /// /// Entity 异步扩展方法 /// public static class EntityAsyncExtension { private const string EntityNamespace = "SepCore.Entity."; private static readonly Dictionary _typeDict = new(); private static readonly Dictionary _assetNameDict = new(); /// /// 异步显示实体 /// /// 实体组件 /// 实体编号 /// 实体逻辑类型 /// 实体资源名称 /// 实体组名称 /// 用户自定义数据 /// 超时时间(秒),0表示不超时 /// 取消令牌 /// 显示的实体 public static UniTask ShowEntityAsync(this EntityComponent entityComponent, int entityId, Type entityLogicType, string entityAssetName, string entityGroupName, object userData = null, 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, cancellationToken ).ContinueWith(successArgs => successArgs.Entity); entityComponent.ShowEntity(entityId, entityLogicType, entityAssetName, entityGroupName, priority, userData); return waitTask; } /// /// 异步显示实体(泛型版本) /// /// 实体逻辑类型 /// 实体组件 /// 实体编号 /// 实体资源名称 /// 实体组名称 /// 用户自定义数据 /// 超时时间(秒),0表示不超时 /// 取消令牌 /// 显示的实体 public static UniTask ShowEntityAsync(this EntityComponent entityComponent, int entityId, string entityAssetName, string entityGroupName, object userData = null, 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, cancellationToken ).ContinueWith(successArgs => (T)successArgs.Entity.Logic); 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); } /// /// 异步隐藏实体 /// /// 实体组件 /// 实体编号 /// 用户自定义数据 /// 超时时间(秒),0表示不超时 /// 取消令牌 /// 隐藏完成事件 public static UniTask HideEntityAsync(this EntityComponent entityComponent, int entityId, object userData = null, float timeout = 30f, CancellationToken cancellationToken = default) { UniTask waitTask = AsyncTaskHelper.WaitEventAsync( HideEntityCompleteEventArgs.EventId, args => args.EntityId == entityId, timeout, cancellationToken ); entityComponent.HideEntity(entityId, userData); return waitTask; } /// /// 异步隐藏实体(通过实体对象) /// /// 实体组件 /// 要隐藏的实体 /// 用户自定义数据 /// 超时时间(秒),0表示不超时 /// 取消令牌 /// 隐藏完成事件 public static UniTask HideEntityAsync(this EntityComponent entityComponent, UnityGameFramework.Runtime.Entity entity, object userData = null, float timeout = 30f, CancellationToken cancellationToken = default) { 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; } } }