MapSceneGraph.cs 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. using DeepCore;
  2. using DeepCore.Astar;
  3. using DeepCore.GameData.Zone.ZoneEditor;
  4. using DeepCore.Geometry;
  5. using DeepCore.Log;
  6. using System;
  7. using System.Collections.Generic;
  8. namespace DeepMMO.Server.AreaManager
  9. {
  10. /// <summary>
  11. /// 跨场景寻路网格
  12. /// </summary>
  13. public class MapSceneGrapAstar : Astar<MapSceneGrapAstar.SceneGraphNode, MapSceneGrapAstar.SceneGraphPath>
  14. {
  15. private static Logger log = new LazyLogger(nameof(MapSceneGrapAstar));
  16. private SceneGraphMap terrain;
  17. public MapSceneGrapAstar(MapTemplateData[] nodes)
  18. {
  19. this.terrain = new SceneGraphMap(nodes);
  20. base.InitGraph(terrain);
  21. }
  22. public override SceneGraphPath GenWayPoint(SceneGraphNode node)
  23. {
  24. return new SceneGraphPath(node);
  25. }
  26. /// <summary>
  27. /// 找到最近的入口
  28. /// </summary>
  29. /// <param name="pos"></param>
  30. /// <returns></returns>
  31. public SceneNextLink GetNearEntry(int mapID, Vector3 pos)
  32. {
  33. var node = terrain.GetNode(mapID);
  34. if (node != null)
  35. {
  36. return node.GetNearEntry(pos);
  37. }
  38. return null;
  39. }
  40. protected override void SetTempNode(IMapNode node, ITempMapNode temp)
  41. {
  42. (node as SceneGraphNode).TempNode = temp;
  43. }
  44. protected override ITempMapNode GetTempNode(IMapNode node)
  45. {
  46. return (node as SceneGraphNode).TempNode;
  47. }
  48. /// <summary>
  49. /// 跨场景寻路
  50. /// </summary>
  51. /// <param name="srcMapID"></param>
  52. /// <param name="dstMapID"></param>
  53. /// <param name="dstMapNearPos">目标场景最近点</param>
  54. /// <returns></returns>
  55. public ArrayList<SceneNextLink> FindPath(int srcMapID, int dstMapID, Vector3? dstMapNearPos)
  56. {
  57. var snode = terrain.GetNode(srcMapID);
  58. if (snode == null) return null;
  59. var dnode = terrain.GetNode(dstMapID);
  60. if (dnode == null) return null;
  61. SceneGraphPath path;
  62. lock (this)
  63. {
  64. path = base.FindPath(snode, dnode, null);
  65. }
  66. if (path != null)
  67. {
  68. var ret = new ArrayList<SceneNextLink>();
  69. foreach (SceneGraphPath wp in path)
  70. {
  71. var next = wp.Next;
  72. if (next != null)
  73. {
  74. var info = wp.Node.GetNextInfo(next.Node.MapID);
  75. ret.Add(info);
  76. }
  77. }
  78. if (ret.Count > 0 && dstMapNearPos.HasValue)
  79. {
  80. var near = dnode.GetNearEntry(dstMapNearPos.Value);
  81. if (near != ret[ret.Count - 1])
  82. {
  83. ret.Add(near);
  84. }
  85. }
  86. return ret;
  87. }
  88. return null;
  89. }
  90. public class SceneGraphMap : IAstarGraph<SceneGraphNode>
  91. {
  92. private readonly HashMap<int, SceneGraphNode> nodes;
  93. public int TotalNodeCount { get { return nodes.Count; } }
  94. public SceneGraphMap(MapTemplateData[] nodes)
  95. {
  96. this.nodes = new HashMap<int, SceneGraphNode>(nodes.Length);
  97. foreach (var data in nodes)
  98. {
  99. var node = new SceneGraphNode(data);
  100. this.nodes.Add(node.MapID, node);
  101. }
  102. foreach (var node in this.nodes.Values)
  103. {
  104. node.InitNexts(this);
  105. }
  106. }
  107. public void Dispose()
  108. {
  109. foreach (var node in this.nodes.Values)
  110. {
  111. node.Dispose();
  112. }
  113. nodes.Clear();
  114. }
  115. public void ForEachNodes(Action<SceneGraphNode> action)
  116. {
  117. foreach (var node in this.nodes.Values)
  118. {
  119. action(node);
  120. }
  121. }
  122. internal SceneGraphNode GetNode(int mapID)
  123. {
  124. return nodes.Get(mapID);
  125. }
  126. }
  127. public class SceneGraphNode : IMapNode
  128. {
  129. /// <summary>
  130. /// 下个场景连接点
  131. /// </summary>
  132. private SceneGraphNode[] nexts_array;
  133. private HashMap<int, SceneNextLink> nexts = new HashMap<int, SceneNextLink>(1);
  134. /// <summary>
  135. /// 当前场景所有入口
  136. /// </summary>
  137. private List<SceneNextLink> current_entries = new List<SceneNextLink>();
  138. public int MapID { get; private set; }
  139. public MapTemplateData Data { get; private set; }
  140. public override IMapNode[] Nexts { get { return nexts_array; } }
  141. public override int CloseAreaIndex { get { return 0; } protected set { } }
  142. public override object Tag { get; set; }
  143. internal ITempMapNode TempNode;
  144. public SceneGraphNode(MapTemplateData data)
  145. {
  146. this.Data = data;
  147. this.MapID = data.id;
  148. }
  149. public override void Dispose()
  150. {
  151. nexts.Clear();
  152. }
  153. public override bool TestCross(IMapNode other)
  154. {
  155. return nexts.ContainsKey((other as SceneGraphNode).MapID);
  156. }
  157. public override float GetFatherG(IMapNode father) { return 1; }
  158. public override float GetTargetH(IMapNode target ) { return 1; }
  159. internal void InitNexts(SceneGraphMap map)
  160. {
  161. nexts.Clear();
  162. current_entries.Clear();
  163. var list = new List<SceneGraphNode>(1);
  164. if (Data.connect != null)
  165. {
  166. this.current_entries.AddRange(Data.connect);
  167. foreach (var next in Data.connect)
  168. {
  169. var ss = RPGServerBattleManager.Instance.GetSceneAsCache(Data.zone_template_id);
  170. if (ss != null && ss.Regions.TryFind(e => e.Name == next.from_flag_name, out var from_rg))
  171. {
  172. next.from_flag_pos = new Vector3(from_rg.X, from_rg.Y, from_rg.Z);
  173. }
  174. else
  175. {
  176. throw new Exception($"Currernt Link Data Error : MapID={MapID} : {next}");
  177. }
  178. var next_node = map.GetNode(next.to_map_id);
  179. if (next_node != null)
  180. {
  181. if (!nexts.ContainsKey(next_node.MapID))
  182. {
  183. var ds = RPGServerBattleManager.Instance.GetSceneAsCache(next_node.Data.zone_template_id);
  184. if (ds != null && ds.Regions.TryFind(e => e.Name == next.to_flag_name, out var next_rg))
  185. {
  186. next.to_flag_pos = new Vector3(next_rg.X, next_rg.Y, next_rg.Z);
  187. nexts.Add(next_node.MapID, next);
  188. }
  189. else
  190. {
  191. //throw new Exception($"Next Link Data Error : MapID={MapID} : {next}");
  192. log.Error($"Next Link Data Error : MapID={MapID} : {next}");
  193. }
  194. }
  195. list.Add(next_node);
  196. }
  197. else
  198. {
  199. log.Error($"Next Link Data Error : MapID={MapID} : {next}");
  200. }
  201. }
  202. }
  203. this.nexts_array = list.ToArray();
  204. }
  205. internal SceneNextLink GetNextInfo(int mapID)
  206. {
  207. return nexts.Get(mapID);
  208. }
  209. /// <summary>
  210. /// 找到最近的入口
  211. /// </summary>
  212. /// <param name="pos"></param>
  213. /// <returns></returns>
  214. internal SceneNextLink GetNearEntry(Vector3 pos)
  215. {
  216. SceneNextLink ret = null;
  217. var min = float.MaxValue;
  218. foreach (var entry in current_entries)
  219. {
  220. var d = Vector3.DistanceSquared(entry.from_flag_pos, pos);
  221. if (d < min)
  222. {
  223. ret = entry;
  224. min = d;
  225. }
  226. }
  227. return ret;
  228. }
  229. }
  230. public class SceneGraphPath : IWayPoint<SceneGraphNode, SceneGraphPath>
  231. {
  232. public MapTemplateData Data { get; private set; }
  233. public SceneGraphPath(SceneGraphNode map_node) : base(map_node)
  234. {
  235. this.Data = base.Node.Data;
  236. }
  237. public override bool PosEquals(SceneGraphPath w)
  238. {
  239. return Data.id == w.Data.id;
  240. }
  241. }
  242. }
  243. }