NLDClient-yudde/ProjectNLD/Assets/Code/Scripts/Framework/Condition/ConditionManager.cs

355 lines
12 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using cfg;
using Obfuz;
using PhxhSDK;
using static Framework.EventManager;
namespace Framework.Condition
{
[ObfuzIgnore]
public interface ICondition
{
public EventName[] SignalNames { get; }
/// <summary>
/// 检查条件是否满足
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
bool Check(List<float> args);
/// <summary>
/// 获取条件参数对应的本地化文本数组
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
string[] GetArgLocalizations(List<float> args);
/// <summary>
/// 获取进度
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
float GetProgress(List<float> args);
}
public class ConditionException : Exception
{
public ConditionException(string message) : base(message)
{
}
}
public sealed class ConditionManager : Singlenton<ConditionManager>, IInitable
{
/// <summary>
/// 条件前缀
/// </summary>
private const string CONDITION_PREFIX = "Condition";
/// <summary>
/// 条件描述前缀
/// </summary>
private const string CONDITION_DESC_PREFIX = "condition_desc_";
private const string CONDITION_REGEX = @"\([^)]*\)";
private const string CONDITION_ARG_REGEX = @"\((.*?)\)";
//避免GC
private List<float> _tempConditionArgs = new();
// 缓存条件描述的 key避免每次拼接字符串产生 GC
private Dictionary<ConditionType, string> _conditionDescKeyCache;
private ICondition[] m_conditions;
#region MainLife
public void Init()
{
m_conditions = new ICondition[(int)ConditionType.Max];
_conditionDescKeyCache = new Dictionary<ConditionType, string>((int)ConditionType.Max);
foreach (ConditionType conditionType in Enum.GetValues(typeof(ConditionType)))
{
if (conditionType == ConditionType.None || conditionType == ConditionType.Max)
continue;
// 预缓存条件描述的 key
_conditionDescKeyCache[conditionType] = $"{CONDITION_DESC_PREFIX}{conditionType}";
string typeName = $"{CONDITION_PREFIX}{conditionType}";
Type type = CommonUtilsFramework.GamePlayAssembly.GetType(typeName);
if (type == null)
{
DebugUtil.LogError($"Cant find Typename:{typeName}");
continue;
}
if (Activator.CreateInstance(type) is ICondition condition)
m_conditions[(int)conditionType] = condition;
else
DebugUtil.LogError($"cant construct condition,type:{type},please check if your type is correctly implement ICondition");
}
}
public void Release()
{
m_conditions = null;
_tempConditionArgs = null;
_conditionDescKeyCache = null;
}
#endregion
#region API
public bool CheckCondition(int conditionID)
{
DataCondition conditionCfg = GetConditionCfg(conditionID);
GetConditionCfgArgs(conditionCfg, ref _tempConditionArgs);
return CheckCondition(conditionCfg.Type, _tempConditionArgs);
}
public bool CheckCondition(string condition)
{
string conditionName = Regex.Replace(condition, @"\(.*?\)", string.Empty);
ConditionType conditionType = GetConditionType(conditionName);
GetConditionStringArgs(condition, ref _tempConditionArgs);
return CheckCondition(conditionType, _tempConditionArgs);
}
public bool CheckCondition(int[] conditionGroup, bool useAnd = true)
{
foreach (var conditionID in conditionGroup)
{
var isSuccess = CheckCondition(conditionID);
if (useAnd)
{
if (!isSuccess)
{
return false;
}
}
else
{
if (isSuccess)
return true;
}
}
return useAnd;
}
public bool CheckCondition(string[] conditionGroups, bool useAnd = true)
{
if (null == conditionGroups || 0 == conditionGroups.Length)
return false;
foreach (string condition in conditionGroups)
{
bool isSuccess = CheckCondition(condition);
if (useAnd)
{
if (!isSuccess)
return false;
}
else
{
if (isSuccess)
return true;
}
}
return useAnd;
}
/// <summary>
/// 检查条件是否满足条件
/// </summary>
/// <param name="conditionType"></param>
/// <param name="conditionArg"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public bool CheckCondition(ConditionType conditionType, List<float> conditionArg)
{
if (m_conditions[(int)conditionType] == null)
throw new Exception($"condition type is outside of range!condition type:{conditionType}");
return m_conditions[(int)conditionType].Check(conditionArg);
}
/// <summary>
/// 获取条件参数的本地化文本数组
/// </summary>
/// <param name="conditionType"></param>
/// <param name="listArg"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public string[] GetArgLocalizations(ConditionType conditionType, List<float> listArg)
{
ICondition iCondition = m_conditions[(int)conditionType] ?? throw new Exception($"条件类型超出范围!类型:{conditionType}");
return iCondition.GetArgLocalizations(listArg);
}
/// <summary>
/// 获取条件进度
/// </summary>
/// <returns></returns>
public float GetProgress(ConditionType conditionType, List<float> listArg)
{
ICondition iCondition = m_conditions[(int)conditionType] ?? throw new Exception($"条件类型超出范围!类型:{conditionType}");
return iCondition.GetProgress(listArg);
}
/// <summary>
/// 获取条件进度
/// </summary>
/// <returns></returns>
public float GetProgress(ConditionModifier conditionModifier)
{
return GetProgress(conditionModifier.conditionType, conditionModifier._args);
}
public EventName[] GetConditionSignal(int conditionID)
{
DataCondition conditionCfg = GetConditionCfg(conditionID);
if (null != conditionCfg)
{
return GetConditionSignal(conditionCfg.Type);
}
DebugUtil.LogError($"cant find condition!conditionID:{conditionID}");
return new EventName[1] { EventName.None };
}
public ConditionType GetConditionType(string conditionName)
{
conditionName = Regex.Replace(conditionName, CONDITION_REGEX, string.Empty);
if (Enum.TryParse(conditionName, out ConditionType result))
return result;
DebugUtil.LogError($"没有该条件类型:{conditionName}");
return ConditionType.None;
}
public EventName[] GetConditionSignal(string conditionName)
{
EventName[] eventNames = GetConditionSignal(GetConditionType(conditionName));
if (null == eventNames)
DebugUtil.LogError($"cant find condition!conditionName:{conditionName}");
return eventNames;
}
/// <summary>
/// 获取条件参数
/// </summary>
/// <param name="condition"></param>
/// <param name="_args"></param>
public void GetConditionStringArgs(string condition, ref List<float> _args)
{
_args.Clear();
MatchCollection matches = Regex.Matches(condition, CONDITION_ARG_REGEX);
foreach (Match match in matches.Cast<Match>())
{
string[] paramStrs = match.Groups[1].Value.Split(',');
foreach (string paramStr in paramStrs)
{
if (!float.TryParse(paramStr, out float param))
continue;
_args.Add(param);
}
}
}
public EventName[] GetConditionSignal(ConditionType conditionType)
{
ICondition condition = GetConditionByType(conditionType);
if (null != condition)
return condition.SignalNames;
DebugUtil.LogError($"cant find condition!conditionType:{conditionType}");
return null;
}
#region 获取条件本地化
public string GetConditionLocalization(int conditionID)
{
var conditionCfg = GetConditionCfg(conditionID);
if (conditionCfg != null)
{
GetConditionCfgArgs(conditionCfg, ref _tempConditionArgs);
return GetConditionLocalization(conditionCfg.Type, _tempConditionArgs);
}
DebugUtil.LogError($"cant find condition!conditionID:{conditionID}");
return null;
}
public string GetConditionLocalization(string condition)
{
string conditionName = Regex.Replace(condition, CONDITION_ARG_REGEX, string.Empty);
GetConditionStringArgs(condition, ref _tempConditionArgs);
return GetConditionLocalization(GetConditionType(conditionName), _tempConditionArgs);
}
public string GetConditionLocalization(ConditionType conditionType, List<float> args)
{
// 使用缓存的 key避免每次拼接字符串产生 GC
if (!_conditionDescKeyCache.TryGetValue(conditionType, out string key))
{
// 回退方案,理论上不应该走到这里
key = $"{CONDITION_DESC_PREFIX}{conditionType}";
}
return StringManager.Instance.GetLocalizeTextByKeyAndList(key, GetArgLocalizations(conditionType, args));
}
public string GetConditionLocalization(ConditionModifier conditionModifier)
{
return GetConditionLocalization(conditionModifier.conditionType, conditionModifier._args);
}
#endregion
#endregion
#region InnerFunction
private DataCondition GetConditionCfg(int conditionID)
{
return TableManager.Instance.Tables.ConditionConfig.Get(conditionID);
}
private ICondition GetConditionByType(ConditionType conditionType)
{
var index = (int)conditionType;
if (index < 0 || index >= m_conditions.Length)
{
DebugUtil.LogError("cant find condition!");
return null;
}
return m_conditions[index];
}
private void GetConditionCfgArgs(DataCondition conditionCfg, ref List<float> _args)
{
_args.Clear();
_args.Add(conditionCfg.Param1);
_args.Add(conditionCfg.Param2);
_args.Add(conditionCfg.Param3);
}
#endregion
}
}