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; } /// /// 检查条件是否满足 /// /// /// bool Check(List args); /// /// 获取条件参数对应的本地化文本数组 /// /// /// string[] GetArgLocalizations(List args); /// /// 获取进度 /// /// /// float GetProgress(List args); } public class ConditionException : Exception { public ConditionException(string message) : base(message) { } } public sealed class ConditionManager : Singlenton, IInitable { /// /// 条件前缀 /// private const string CONDITION_PREFIX = "Condition"; /// /// 条件描述前缀 /// private const string CONDITION_DESC_PREFIX = "condition_desc_"; private const string CONDITION_REGEX = @"\([^)]*\)"; private const string CONDITION_ARG_REGEX = @"\((.*?)\)"; //避免GC private List _tempConditionArgs = new(); // 缓存条件描述的 key,避免每次拼接字符串产生 GC private Dictionary _conditionDescKeyCache; private ICondition[] m_conditions; #region MainLife public void Init() { m_conditions = new ICondition[(int)ConditionType.Max]; _conditionDescKeyCache = new Dictionary((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 Type,name:{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; } /// /// 检查条件是否满足条件 /// /// /// /// /// public bool CheckCondition(ConditionType conditionType, List 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); } /// /// 获取条件参数的本地化文本数组 /// /// /// /// /// public string[] GetArgLocalizations(ConditionType conditionType, List listArg) { ICondition iCondition = m_conditions[(int)conditionType] ?? throw new Exception($"条件类型超出范围!类型:{conditionType}"); return iCondition.GetArgLocalizations(listArg); } /// /// 获取条件进度 /// /// public float GetProgress(ConditionType conditionType, List listArg) { ICondition iCondition = m_conditions[(int)conditionType] ?? throw new Exception($"条件类型超出范围!类型:{conditionType}"); return iCondition.GetProgress(listArg); } /// /// 获取条件进度 /// /// 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; } /// /// 获取条件参数 /// /// /// public void GetConditionStringArgs(string condition, ref List _args) { _args.Clear(); MatchCollection matches = Regex.Matches(condition, CONDITION_ARG_REGEX); foreach (Match match in matches.Cast()) { 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 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 _args) { _args.Clear(); _args.Add(conditionCfg.Param1); _args.Add(conditionCfg.Param2); _args.Add(conditionCfg.Param3); } #endregion } }