using System; using Data; using System.Collections.Generic; using System.Linq; namespace Managers { public class SkillTreeManager : Utils.Singleton, ILaunchManager, ISavableSingleton { public string StepDescription => "正在加载技能树"; // 内部数据结构,用于高效查询和图遍历 private Dictionary _skillNodesByDefName; private Dictionary> _skillNodesByTag; private Dictionary> _skillNodesByFaction; private Dictionary> _childrenOfNode; [Savable] public HashSet UnlockedSkillTrees { get; set; } = new(); public SkillTreeManager() { SaveManager.Instance.RegisterSavable(this); } ~SkillTreeManager() { SaveManager.Instance.UnregisterSavable(this); } public void Init() { // 假设 DefineManager.Instance 存在且 QueryDefinesByType 方法可用 // 如果 DefineManager 是单例,这里直接调用即可。 // 否则,需要确保 DefineManager 在此之前已被正确初始化。 var allSkillTreeNodes = DefineManager.Instance.QueryDefinesByType(); // 1. 初始化字典 _skillNodesByDefName = new Dictionary(); _skillNodesByTag = new Dictionary>(); _skillNodesByFaction = new Dictionary>(); _childrenOfNode = new Dictionary>(); // 2. 填充基本查询字典 foreach (var node in allSkillTreeNodes) { if (string.IsNullOrEmpty(node.defName)) { // 可以选择抛出异常或记录警告,取决于项目的错误处理策略 // 例如: Log.Warning($"SkillTreeDef with empty defName found. Skipping."); continue; } if (!_skillNodesByDefName.TryAdd(node.defName, node)) { // 避免重复defName,通常defName应该是唯一的 // 例如: Log.Error($"Duplicate SkillTreeDef defName '{node.defName}' found. Only the first one will be used."); continue; // 跳过此重复节点 } // 填充 _skillNodesByTag if (!string.IsNullOrEmpty(node.tag)) { if (!_skillNodesByTag.ContainsKey(node.tag)) { _skillNodesByTag[node.tag] = new List(); } _skillNodesByTag[node.tag].Add(node); } // 填充 _skillNodesByFaction // 假设 AffiliationDef 也有 defName 属性作为唯一标识 if (node.faction != null && !string.IsNullOrEmpty(node.faction.defName)) { if (!_skillNodesByFaction.ContainsKey(node.faction.defName)) { _skillNodesByFaction[node.faction.defName] = new List(); } _skillNodesByFaction[node.faction.defName].Add(node); } } // 3. 填充 _childrenOfNode 字典(构建父 -> 子关系) // 需要再次遍历,因为在填充 _skillNodesByDefName 之前,prerequisites 中的引用可能尚未完全解析。 foreach (var childNode in allSkillTreeNodes) { if (childNode.prerequisites != null) { foreach (var prerequisite in childNode.prerequisites) { // 确保父节点在 _skillNodesByDefName 中存在,避免野指针或无效引用 if (prerequisite != null && _skillNodesByDefName.TryGetValue(prerequisite.defName, out var parentNode)) { if (!_childrenOfNode.ContainsKey(parentNode.defName)) { _childrenOfNode[parentNode.defName] = new List(); } _childrenOfNode[parentNode.defName].Add(childNode); } else if (prerequisite != null) { // 记录警告:prerequisites中引用的父节点找不到定义,可能是数据配置错误 // 例如: Log.Warning($"SkillTreeDef '{childNode.defName}' references unknown prerequisite '{prerequisite.defName}'."); } } } } } public void Clear() { // 清理所有数据结构,释放内存 _skillNodesByDefName?.Clear(); _skillNodesByTag?.Clear(); _skillNodesByFaction?.Clear(); _childrenOfNode?.Clear(); // 将引用设为null,有助于GC _skillNodesByDefName = null; _skillNodesByTag = null; _skillNodesByFaction = null; _childrenOfNode = null; } // --- 节点查询 --- /// /// 根据定义名查询技能树节点 /// /// 技能树节点的定义名 /// 匹配的 SkillTreeDef,如果未找到则为 null public SkillTreeDef GetNodeByDefName(string defName) { if (string.IsNullOrEmpty(defName)) return null; _skillNodesByDefName.TryGetValue(defName, out var node); return node; } /// /// 根据标签查询技能树节点列表 /// /// 技能树节点的标签 /// 匹配的 SkillTreeDef 列表,如果未找到则返回空列表 public List GetNodesByTag(string tag) { if (string.IsNullOrEmpty(tag)) return new List(); _skillNodesByTag.TryGetValue(tag, out var nodes); return nodes ?? new List(); } /// /// 根据派系名称查询技能树节点列表 /// /// 派系的定义名 /// 匹配的 SkillTreeDef 列表,如果未找到则返回空列表 public List GetNodesByFaction(string factionName) { if (string.IsNullOrEmpty(factionName)) return new List(); _skillNodesByFaction.TryGetValue(factionName, out var nodes); return nodes ?? new List(); } public string[] GetAllTag() { return _skillNodesByTag.Keys.ToArray(); } // --- 父子关系查询 --- /// /// 判断 targetNode 是否是 baseNode 的直接父节点 /// /// 作为父节点候选的节点 /// 作为子节点候选的节点 /// 如果是直接父节点则为 true,否则为 false public bool IsDirectParentOf(SkillTreeDef baseNode, SkillTreeDef targetNode) { if (baseNode == null || targetNode == null || targetNode.prerequisites == null) return false; return targetNode.prerequisites.Any(prerequisite => prerequisite != null && prerequisite.defName == baseNode.defName); } /// /// 判断 targetNode 是否是 baseNode 的直接子节点 /// /// 作为父节点的节点 /// 作为子节点候选的节点 /// 如果是直接子节点则为 true,否则为 false public bool IsDirectChildOf(SkillTreeDef baseNode, SkillTreeDef targetNode) { if (baseNode == null || targetNode == null) return false; // 查找 baseNode 的子节点列表中是否包含 targetNode _childrenOfNode.TryGetValue(baseNode.defName, out var children); return children != null && children.Any(c => c.defName == targetNode.defName); } /// /// 判断 ancestor 是否是 descendant 的任何一级父节点(包括直接和间接) /// /// 祖先节点候选 /// 后代节点候选 /// 如果是祖先节点则为 true,否则为 false public bool IsAncestorOf(SkillTreeDef ancestor, SkillTreeDef descendant) { if (ancestor == null || descendant == null) return false; if (ancestor.defName == descendant.defName) return false; // 自己不是自己的祖先 return GetAllAncestors(descendant).Any(n => n.defName == ancestor.defName); } /// /// 判断 descendant 是否是 ancestor 的任何一级子节点(包括直接和间接) /// /// 后代节点候选 /// 祖先节点候选 /// 如果是后代节点则为 true,否则为 false public bool IsDescendantOf(SkillTreeDef descendant, SkillTreeDef ancestor) { if (descendant == null || ancestor == null) return false; if (descendant.defName == ancestor.defName) return false; // 自己不是自己的后代 return GetAllDescendants(ancestor).Any(n => n.defName == descendant.defName); } // --- 获取所有相关节点 --- /// /// 获取所有直接父节点 /// /// 要查询的节点 /// 直接父节点列表,如果无父节点则返回空列表 public List GetAllDirectParents(SkillTreeDef node) { if (node == null || node.prerequisites == null) return new List(); // 确保返回的是真实存在于管理器中的节点,而不是可能无效的引用 return node.prerequisites.Where(p => p != null && _skillNodesByDefName.ContainsKey(p.defName)) .Select(p => _skillNodesByDefName[p.defName]) .ToList(); } /// /// 获取所有直接子节点 /// /// 要查询的节点 /// 直接子节点列表,如果无子节点则返回空列表 public List GetAllDirectChildren(SkillTreeDef node) { if (node == null) return new List(); _childrenOfNode.TryGetValue(node.defName, out var children); return children ?? new List(); } /// /// 获取所有祖先节点(包括直接和间接父节点),使用 BFS 算法避免循环依赖 /// /// 要查询的节点 /// 所有祖先节点列表 public List GetAllAncestors(SkillTreeDef node) { if (node == null) return new List(); var ancestors = new HashSet(); // 使用HashSet避免重复和循环 var queue = new Queue(); // 将当前节点的直接父节点作为起点加入队列 if (node.prerequisites != null) { foreach (var directParentRef in node.prerequisites) { if (directParentRef != null && _skillNodesByDefName.TryGetValue(directParentRef.defName, out var parentNode)) { if (!ancestors.Contains(parentNode)) { ancestors.Add(parentNode); queue.Enqueue(parentNode); } } } } while (queue.Count > 0) { var current = queue.Dequeue(); if (current.prerequisites != null) { foreach (var prerequisiteRef in current.prerequisites) { if (prerequisiteRef != null && _skillNodesByDefName.TryGetValue(prerequisiteRef.defName, out var actualParentNode)) { if (!ancestors.Contains(actualParentNode)) { ancestors.Add(actualParentNode); queue.Enqueue(actualParentNode); } } } } } return ancestors.ToList(); } /// /// 获取所有后代节点(包括直接和间接子节点),使用 BFS 算法避免循环依赖 /// /// 要查询的节点 /// 所有后代节点列表 public List GetAllDescendants(SkillTreeDef node) { if (node == null) return new List(); var descendants = new HashSet(); // 使用HashSet避免重复和循环 var queue = new Queue(); // 将当前节点的直接子节点作为起点加入队列 _childrenOfNode.TryGetValue(node.defName, out var directChildren); if (directChildren != null) { foreach (var child in directChildren) { if (!descendants.Contains(child)) { descendants.Add(child); queue.Enqueue(child); } } } while (queue.Count > 0) { var current = queue.Dequeue(); _childrenOfNode.TryGetValue(current.defName, out var children); if (children != null) { foreach (var child in children) { if (!descendants.Contains(child)) { descendants.Add(child); queue.Enqueue(child); } } } } return descendants.ToList(); } /// /// 确保技能树定义名称有效。 /// /// 要验证的技能树定义名称。 /// 如果技能树定义名称无效(不在 _skillNodesByDefName 中),则抛出。 private bool ValidateSkillTreeDefName(string skillTreeDefName) { return _skillNodesByDefName.ContainsKey(skillTreeDefName); } /// /// 尝试解锁一个技能树。 /// 必须是有效的 skillTreeDefName,否则会抛出 ArgumentException。 /// /// 要解锁的技能树的定义名称。 /// 如果技能树成功解锁(之前未解锁),则为 true;如果技能树已经解锁,则为 false。 /// 如果 skillTreeDefName 无效。 public bool UnlockSkillTree(string skillTreeDefName) { return ValidateSkillTreeDefName(skillTreeDefName) && UnlockedSkillTrees.Add(skillTreeDefName); } /// /// 尝试加锁(锁定)一个技能树。 /// 必须是有效的 skillTreeDefName,否则会抛出 ArgumentException。 /// /// 要加锁的技能树的定义名称。 /// 如果技能树成功加锁(之前已解锁),则为 true;如果技能树已经加锁,则为 false。 /// 如果 skillTreeDefName 无效。 public bool LockSkillTree(string skillTreeDefName) { return ValidateSkillTreeDefName(skillTreeDefName) && UnlockedSkillTrees.Remove(skillTreeDefName); } /// /// 查询指定技能树是否已解锁。 /// 必须是有效的 skillTreeDefName,否则会抛出 ArgumentException。 /// /// 要查询的技能树的定义名称。 /// 如果技能树已解锁,则为 true;否则为 false。 /// 如果 skillTreeDefName 无效。 public bool IsSkillTreeUnlocked(string skillTreeDefName) { return ValidateSkillTreeDefName(skillTreeDefName) && UnlockedSkillTrees.Contains(skillTreeDefName); } } }