diff --git a/Entity/Entity.csproj b/Entity/Entity.csproj index fed989a..c9ca112 100644 --- a/Entity/Entity.csproj +++ b/Entity/Entity.csproj @@ -19,7 +19,6 @@ - diff --git a/Entity/Game/Condition/ConditionContext.cs b/Entity/Game/Condition/ConditionContext.cs new file mode 100644 index 0000000..b0411fc --- /dev/null +++ b/Entity/Game/Condition/ConditionContext.cs @@ -0,0 +1,9 @@ +namespace NB.Game; + +/// +/// 条件判断上下文 +/// +public class ConditionContext +{ + +} \ No newline at end of file diff --git a/Entity/Game/Condition/ConditionManageComponent.cs b/Entity/Game/Condition/ConditionManageComponent.cs new file mode 100644 index 0000000..dd34713 --- /dev/null +++ b/Entity/Game/Condition/ConditionManageComponent.cs @@ -0,0 +1,111 @@ +using Fantasy; +using Fantasy.Assembly; +using Fantasy.Async; +using Fantasy.DataStructure.Collection; +using Fantasy.Entitas; +using NB.Game; + +/// +/// 条件管理组件 - 参考 ItemUseComponent 设计 +/// +public class ConditionManageComponent : Entity, IAssemblyLifecycle +{ + private readonly Dictionary _handlers = new(); + private readonly OneToManyList _assemblyHandlers = new(); + + + public override void Dispose() + { + base.Dispose(); + _handlers.Clear(); + _assemblyHandlers.Clear(); + } + + public async FTask Initialize() + { + await AssemblyLifecycle.Add(this); + } + + #region Assembly Lifecycle - 参考 ItemUseComponent + + public async FTask OnLoad(AssemblyManifest assemblyManifest) + { + var tcs = FTask.Create(false); + Scene.ThreadSynchronizationContext.Post(() => + { + InnerLoad(assemblyManifest); + tcs.SetResult(); + }); + await tcs; + } + + public async FTask OnUnload(AssemblyManifest assemblyManifest) + { + var tcs = FTask.Create(false); + Scene.ThreadSynchronizationContext.Post(() => + { + InnerUnLoad(assemblyManifest); + tcs.SetResult(); + }); + await tcs; + } + + private void InnerLoad(AssemblyManifest assemblyManifest) + { + var assembly = assemblyManifest.Assembly; + var assemblyIdentity = assemblyManifest.AssemblyManifestId; + + foreach (var type in assembly.GetTypes()) + { + if (!typeof(ICondition).IsAssignableFrom(type)) continue; + if (type.IsInterface || type.IsAbstract) continue; + + var attributes = type.GetCustomAttributes(typeof(ConditionTypeAttribute), false); + if (attributes.Length == 0) + { + Log.Warning($"类型 {type.FullName} 实现了 ICondition,但未添加 ConditionTypeAttribute"); + continue; + } + + var instance = (ICondition)Activator.CreateInstance(type)!; + foreach (ConditionTypeAttribute attr in attributes) + { + _handlers[(int)attr.Type] = instance; + _assemblyHandlers.Add(assemblyIdentity, (int)attr.Type); + } + } + } + + private void InnerUnLoad(AssemblyManifest assemblyManifest) + { + var assemblyIdentity = assemblyManifest.AssemblyManifestId; + if (!_assemblyHandlers.TryGetValue(assemblyIdentity, out var handlers)) return; + + foreach (var handler in handlers) + { + _handlers.Remove(handler); + } + + _assemblyHandlers.Remove(assemblyIdentity); + } + + #endregion + + #region 条件检查 + + /// + /// 检查单个条件 + /// + public bool Check(ConditionContext context, ConditionParam param, ConditionType type) + { + if (!_handlers.TryGetValue((int)type, out var handler)) + { + Log.Warning($"未找到条件处理器: {type}"); + return false; + } + + return handler.Check(context, param); + } + + #endregion +} \ No newline at end of file diff --git a/Entity/Game/Condition/ConditionParam.cs b/Entity/Game/Condition/ConditionParam.cs new file mode 100644 index 0000000..97739c9 --- /dev/null +++ b/Entity/Game/Condition/ConditionParam.cs @@ -0,0 +1,6 @@ +namespace NB.Game; + +public class ConditionParam +{ + +} \ No newline at end of file diff --git a/Entity/Game/Condition/ICondition.cs b/Entity/Game/Condition/ICondition.cs new file mode 100644 index 0000000..f8ca335 --- /dev/null +++ b/Entity/Game/Condition/ICondition.cs @@ -0,0 +1,64 @@ +// 条件接口 - 参考 IItemUse 设计模式 + +namespace NB.Game; + +/// +/// 条件类型属性 +/// +[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)] +public sealed class ConditionTypeAttribute : Attribute +{ + public ConditionType Type { get; } + + public ConditionTypeAttribute(ConditionType type) + { + Type = type; + } +} + +/// +/// 条件类型枚举 +/// +public enum ConditionType +{ + // 基础条件 + None = 0, + + // 玩家条件 + PlayerLevel = 1, // 玩家等级 + PlayerExp = 2, // 玩家经验 + PlayerOnlineTime = 3, // 玩家在线时间 + PlayerLoginCount = 4, // 玩家登录次数 + + // 钓鱼条件 + CatchFish = 10, // 钓鱼数量 + CatchFishType = 11, // 钓指定类型鱼 + CatchFishQuality = 12, // 钓指定品质鱼 + + // 物品条件 + UseItem = 20, // 使用物品 + HaveItem = 21, // 拥有物品 + SellFish = 22, // 卖鱼 + + // 社交条件 + JoinClub = 30, // 加入俱乐部 + SendMessage = 31, // 发送消息 + + // 计算条件 + Formula = 100, // 公式计算 + Script = 101, // 脚本计算 +} + +/// +/// 条件判断接口 +/// +public interface ICondition +{ + /// + /// 检查条件是否满足 + /// + /// 条件上下文 + /// + /// true=满足, false=不满足 + bool Check(ConditionContext context, ConditionParam param); +} \ No newline at end of file