using DeepCore; using DeepCore.Astar; using DeepCore.GameData.Zone.ZoneEditor; using DeepCore.Geometry; using DeepCore.Log; using System; using System.Collections.Generic; namespace DeepMMO.Server.AreaManager { /// /// 跨场景寻路网格 /// public class MapSceneGrapAstar : Astar { private static Logger log = new LazyLogger(nameof(MapSceneGrapAstar)); private SceneGraphMap terrain; public MapSceneGrapAstar(MapTemplateData[] nodes) { this.terrain = new SceneGraphMap(nodes); base.InitGraph(terrain); } public override SceneGraphPath GenWayPoint(SceneGraphNode node) { return new SceneGraphPath(node); } /// /// 找到最近的入口 /// /// /// public SceneNextLink GetNearEntry(int mapID, Vector3 pos) { var node = terrain.GetNode(mapID); if (node != null) { return node.GetNearEntry(pos); } return null; } protected override void SetTempNode(IMapNode node, ITempMapNode temp) { (node as SceneGraphNode).TempNode = temp; } protected override ITempMapNode GetTempNode(IMapNode node) { return (node as SceneGraphNode).TempNode; } /// /// 跨场景寻路 /// /// /// /// 目标场景最近点 /// public ArrayList FindPath(int srcMapID, int dstMapID, Vector3? dstMapNearPos) { var snode = terrain.GetNode(srcMapID); if (snode == null) return null; var dnode = terrain.GetNode(dstMapID); if (dnode == null) return null; SceneGraphPath path; lock (this) { path = base.FindPath(snode, dnode, null); } if (path != null) { var ret = new ArrayList(); foreach (SceneGraphPath wp in path) { var next = wp.Next; if (next != null) { var info = wp.Node.GetNextInfo(next.Node.MapID); ret.Add(info); } } if (ret.Count > 0 && dstMapNearPos.HasValue) { var near = dnode.GetNearEntry(dstMapNearPos.Value); if (near != ret[ret.Count - 1]) { ret.Add(near); } } return ret; } return null; } public class SceneGraphMap : IAstarGraph { private readonly HashMap nodes; public int TotalNodeCount { get { return nodes.Count; } } public SceneGraphMap(MapTemplateData[] nodes) { this.nodes = new HashMap(nodes.Length); foreach (var data in nodes) { var node = new SceneGraphNode(data); this.nodes.Add(node.MapID, node); } foreach (var node in this.nodes.Values) { node.InitNexts(this); } } public void Dispose() { foreach (var node in this.nodes.Values) { node.Dispose(); } nodes.Clear(); } public void ForEachNodes(Action action) { foreach (var node in this.nodes.Values) { action(node); } } internal SceneGraphNode GetNode(int mapID) { return nodes.Get(mapID); } } public class SceneGraphNode : IMapNode { /// /// 下个场景连接点 /// private SceneGraphNode[] nexts_array; private HashMap nexts = new HashMap(1); /// /// 当前场景所有入口 /// private List current_entries = new List(); public int MapID { get; private set; } public MapTemplateData Data { get; private set; } public override IMapNode[] Nexts { get { return nexts_array; } } public override int CloseAreaIndex { get { return 0; } protected set { } } public override object Tag { get; set; } internal ITempMapNode TempNode; public SceneGraphNode(MapTemplateData data) { this.Data = data; this.MapID = data.id; } public override void Dispose() { nexts.Clear(); } public override bool TestCross(IMapNode other) { return nexts.ContainsKey((other as SceneGraphNode).MapID); } public override float GetFatherG(IMapNode father) { return 1; } public override float GetTargetH(IMapNode target ) { return 1; } internal void InitNexts(SceneGraphMap map) { nexts.Clear(); current_entries.Clear(); var list = new List(1); if (Data.connect != null) { this.current_entries.AddRange(Data.connect); foreach (var next in Data.connect) { var ss = RPGServerBattleManager.Instance.GetSceneAsCache(Data.zone_template_id); if (ss != null && ss.Regions.TryFind(e => e.Name == next.from_flag_name, out var from_rg)) { next.from_flag_pos = new Vector3(from_rg.X, from_rg.Y, from_rg.Z); } else { throw new Exception($"Currernt Link Data Error : MapID={MapID} : {next}"); } var next_node = map.GetNode(next.to_map_id); if (next_node != null) { if (!nexts.ContainsKey(next_node.MapID)) { var ds = RPGServerBattleManager.Instance.GetSceneAsCache(next_node.Data.zone_template_id); if (ds != null && ds.Regions.TryFind(e => e.Name == next.to_flag_name, out var next_rg)) { next.to_flag_pos = new Vector3(next_rg.X, next_rg.Y, next_rg.Z); nexts.Add(next_node.MapID, next); } else { //throw new Exception($"Next Link Data Error : MapID={MapID} : {next}"); log.Error($"Next Link Data Error : MapID={MapID} : {next}"); } } list.Add(next_node); } else { log.Error($"Next Link Data Error : MapID={MapID} : {next}"); } } } this.nexts_array = list.ToArray(); } internal SceneNextLink GetNextInfo(int mapID) { return nexts.Get(mapID); } /// /// 找到最近的入口 /// /// /// internal SceneNextLink GetNearEntry(Vector3 pos) { SceneNextLink ret = null; var min = float.MaxValue; foreach (var entry in current_entries) { var d = Vector3.DistanceSquared(entry.from_flag_pos, pos); if (d < min) { ret = entry; min = d; } } return ret; } } public class SceneGraphPath : IWayPoint { public MapTemplateData Data { get; private set; } public SceneGraphPath(SceneGraphNode map_node) : base(map_node) { this.Data = base.Node.Data; } public override bool PosEquals(SceneGraphPath w) { return Data.id == w.Data.id; } } } }