vampire-like/Assets/GameMain/Scripts/Runtime/BuiltinComponent/AsyncTask/EntityAsyncExtension.cs

355 lines
15 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
{
/// <summary>
/// Entity 异步扩展方法
/// </summary>
public static class EntityAsyncExtension
{
private const string EntityNamespace = "SepCore.Entity.";
private static readonly Dictionary<string, Type> _typeDict = new();
private static readonly Dictionary<int, string> _assetNameDict = new();
/// <summary>
/// 异步显示实体
/// </summary>
/// <param name="entityComponent">实体组件</param>
/// <param name="entityId">实体编号</param>
/// <param name="entityLogicType">实体逻辑类型</param>
/// <param name="entityAssetName">实体资源名称</param>
/// <param name="entityGroupName">实体组名称</param>
/// <param name="userData">用户自定义数据</param>
/// <param name="timeout">超时时间0表示不超时</param>
/// <param name="cancellationToken">取消令牌</param>
/// <returns>显示的实体</returns>
public static UniTask<UnityGameFramework.Runtime.Entity> 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);
}
/// <summary>
/// 异步显示实体
/// </summary>
/// <param name="entityComponent">实体组件</param>
/// <param name="entityId">实体编号</param>
/// <param name="entityLogicType">实体逻辑类型</param>
/// <param name="entityAssetName">实体资源名称</param>
/// <param name="entityGroupName">实体组名称</param>
/// <param name="priority">加载优先级</param>
/// <param name="userData">用户自定义数据</param>
/// <param name="timeout">超时时间0表示不超时</param>
/// <param name="cancellationToken">取消令牌</param>
/// <returns>显示的实体</returns>
public static UniTask<UnityGameFramework.Runtime.Entity> ShowEntityAsync(this EntityComponent entityComponent,
int entityId,
Type entityLogicType,
string entityAssetName,
string entityGroupName,
int priority,
object userData = null,
float timeout = 30f,
CancellationToken cancellationToken = default)
{
UniTask<UnityGameFramework.Runtime.Entity> waitTask = AsyncTaskHelper.WaitSuccessOrFailureAsync<ShowEntitySuccessEventArgs, ShowEntityFailureEventArgs>(
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;
}
/// <summary>
/// 异步显示实体(泛型版本)
/// </summary>
/// <typeparam name="T">实体逻辑类型</typeparam>
/// <param name="entityComponent">实体组件</param>
/// <param name="entityId">实体编号</param>
/// <param name="entityAssetName">实体资源名称</param>
/// <param name="entityGroupName">实体组名称</param>
/// <param name="userData">用户自定义数据</param>
/// <param name="timeout">超时时间0表示不超时</param>
/// <param name="cancellationToken">取消令牌</param>
/// <returns>显示的实体</returns>
public static UniTask<T> ShowEntityAsync<T>(this EntityComponent entityComponent,
int entityId,
string entityAssetName,
string entityGroupName,
object userData = null,
float timeout = 30f,
CancellationToken cancellationToken = default) where T : EntityLogic
{
return ShowEntityAsync<T>(entityComponent, entityId, entityAssetName, entityGroupName, 0, userData, timeout,
cancellationToken);
}
/// <summary>
/// 异步显示实体(泛型版本)
/// </summary>
/// <typeparam name="T">实体逻辑类型</typeparam>
/// <param name="entityComponent">实体组件</param>
/// <param name="entityId">实体编号</param>
/// <param name="entityAssetName">实体资源名称</param>
/// <param name="entityGroupName">实体组名称</param>
/// <param name="priority">加载优先级</param>
/// <param name="userData">用户自定义数据</param>
/// <param name="timeout">超时时间0表示不超时</param>
/// <param name="cancellationToken">取消令牌</param>
/// <returns>显示的实体</returns>
public static UniTask<T> ShowEntityAsync<T>(this EntityComponent entityComponent,
int entityId,
string entityAssetName,
string entityGroupName,
int priority,
object userData = null,
float timeout = 30f,
CancellationToken cancellationToken = default) where T : EntityLogic
{
UniTask<T> waitTask = AsyncTaskHelper.WaitSuccessOrFailureAsync<ShowEntitySuccessEventArgs, ShowEntityFailureEventArgs>(
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<T>(entityId, entityAssetName, entityGroupName, priority, userData);
return waitTask;
}
/// <summary>
/// 异步显示玩家实体。
/// </summary>
public static UniTask<Player> ShowPlayerAsync(this EntityComponent entityComponent,
PlayerData data,
float timeout = 30f,
CancellationToken cancellationToken = default)
{
return ShowEntityByDataAsync<Player>(entityComponent, typeof(Player), "Player",
Constant.AssetPriority.PlayerAsset, data, timeout, cancellationToken);
}
/// <summary>
/// 异步显示敌人实体。
/// </summary>
public static UniTask<EnemyBase> ShowEnemyAsync(this EntityComponent entityComponent,
EnemyData data,
float timeout = 30f,
CancellationToken cancellationToken = default)
{
if (data == null)
{
Log.Warning("Enemy data is invalid.");
return UniTask.FromResult<EnemyBase>(null);
}
Type enemyType = TryGetType(data.EnemyType.ToString());
string assetName = TryGetAssetName(data.EntityTypeId);
if (enemyType == null || string.IsNullOrEmpty(assetName))
{
return UniTask.FromResult<EnemyBase>(null);
}
return entityComponent
.ShowEntityAsync(data.Id, enemyType, AssetUtility.GetEntityAsset(assetName), "Enemy",
Constant.AssetPriority.BulletAsset, data, timeout, cancellationToken)
.ContinueWith(entity => entity?.Logic as EnemyBase);
}
/// <summary>
/// 异步显示武器实体。
/// </summary>
public static UniTask<WeaponBase> ShowWeaponAsync(this EntityComponent entityComponent,
WeaponData data,
float timeout = 30f,
CancellationToken cancellationToken = default)
{
if (data == null)
{
Log.Warning("Weapon data is invalid.");
return UniTask.FromResult<WeaponBase>(null);
}
Type weaponType = TryGetType("Weapon." + data.WeaponType);
string assetName = TryGetAssetName(data.EntityTypeId);
if (weaponType == null || string.IsNullOrEmpty(assetName))
{
return UniTask.FromResult<WeaponBase>(null);
}
return entityComponent
.ShowEntityAsync(data.Id, weaponType, AssetUtility.GetEntityAsset(assetName), "Weapon",
Constant.AssetPriority.BulletAsset, data, timeout, cancellationToken)
.ContinueWith(entity => entity?.Logic as WeaponBase);
}
/// <summary>
/// 异步显示特效实体。
/// </summary>
public static UniTask<Effect> ShowEffectAsync(this EntityComponent entityComponent,
EffectData data,
float timeout = 30f,
CancellationToken cancellationToken = default)
{
return ShowEntityByDataAsync<Effect>(entityComponent, typeof(Effect), "Effect",
Constant.AssetPriority.EffectAsset, data, timeout, cancellationToken);
}
/// <summary>
/// 异步显示金币掉落实体。
/// </summary>
public static UniTask<CoinEntity> ShowCoinAsync(this EntityComponent entityComponent,
CoinData data,
float timeout = 30f,
CancellationToken cancellationToken = default)
{
return ShowEntityByDataAsync<CoinEntity>(entityComponent, typeof(CoinEntity), "Drop",
Constant.AssetPriority.EffectAsset, data, timeout, cancellationToken);
}
/// <summary>
/// 异步显示经验掉落实体。
/// </summary>
public static UniTask<ExpEntity> ShowExpAsync(this EntityComponent entityComponent,
ExpData data,
float timeout = 30f,
CancellationToken cancellationToken = default)
{
return ShowEntityByDataAsync<ExpEntity>(entityComponent, typeof(ExpEntity), "Drop",
Constant.AssetPriority.EffectAsset, data, timeout, cancellationToken);
}
/// <summary>
/// 异步隐藏实体
/// </summary>
/// <param name="entityComponent">实体组件</param>
/// <param name="entityId">实体编号</param>
/// <param name="userData">用户自定义数据</param>
/// <param name="timeout">超时时间0表示不超时</param>
/// <param name="cancellationToken">取消令牌</param>
/// <returns>隐藏完成事件</returns>
public static UniTask<HideEntityCompleteEventArgs> HideEntityAsync(this EntityComponent entityComponent,
int entityId,
object userData = null,
float timeout = 30f,
CancellationToken cancellationToken = default)
{
UniTask<HideEntityCompleteEventArgs> waitTask = AsyncTaskHelper.WaitEventAsync<HideEntityCompleteEventArgs>(
HideEntityCompleteEventArgs.EventId,
args => args.EntityId == entityId,
timeout,
cancellationToken
);
entityComponent.HideEntity(entityId, userData);
return waitTask;
}
/// <summary>
/// 异步隐藏实体(通过实体对象)
/// </summary>
/// <param name="entityComponent">实体组件</param>
/// <param name="entity">要隐藏的实体</param>
/// <param name="userData">用户自定义数据</param>
/// <param name="timeout">超时时间0表示不超时</param>
/// <param name="cancellationToken">取消令牌</param>
/// <returns>隐藏完成事件</returns>
public static UniTask<HideEntityCompleteEventArgs> 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<T> ShowEntityByDataAsync<T>(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<T>(null);
}
DREntity drEntity = GameEntry.DataTable.GetDataTableRow<DREntity>(data.TypeId);
if (drEntity == null)
{
Log.Warning("Can not load entity id '{0}' from data table.", data.TypeId.ToString());
return UniTask.FromResult<T>(null);
}
return entityComponent.ShowEntityAsync<T>(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<DREntity>(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;
}
}
}