InstanceZone.Terrain.cs 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using CommonLang;
  6. using CommonAI.RTS.Manhattan;
  7. using CommonAI.Zone.Helper;
  8. using CommonAI.RTS;
  9. using CommonLang.Vector;
  10. using CommonAI.Zone.Interface;
  11. using static CommonAI.ZoneServer.JSGModule.MSpaceNodeCache;
  12. using CommonAI.ZoneServer.JSGModule;
  13. namespace CommonAI.Zone.Instance
  14. {
  15. partial class InstanceZone
  16. {
  17. #region COLLIDE
  18. /// <summary>
  19. /// 2个单位是否碰撞
  20. /// </summary>
  21. /// <param name="s"></param>
  22. /// <param name="d"></param>
  23. /// <returns></returns>
  24. public virtual bool TouchObject2(InstanceZoneObject s, InstanceZoneObject d)
  25. {
  26. if (s == d) return false;
  27. float w = s.X - d.X;
  28. float h = s.Y - d.Y;
  29. float r = s.BodyBlockSize + d.BodyBlockSize;
  30. if (w * w + h * h <= r * r)
  31. {
  32. return true;
  33. }
  34. return false;
  35. }
  36. /// <summary>
  37. /// 单位和地图碰撞检测
  38. /// </summary>
  39. /// <param name="o"></param>
  40. /// <returns></returns>
  41. public virtual bool TouchMap(InstanceZoneObject o)
  42. {
  43. return path_finder.TouchMapBlock(
  44. (int)((o.X) / m_TerrainSrc.GridCellW),
  45. (int)((o.Y) / m_TerrainSrc.GridCellH));
  46. }
  47. /// <summary>
  48. /// 单位尝试用心的坐标和地图碰撞
  49. /// </summary>
  50. /// <param name="o"></param>
  51. /// <param name="x"></param>
  52. /// <param name="y"></param>
  53. /// <returns></returns>
  54. public virtual bool TryTouchMap(InstanceZoneObject o, float x, float y)
  55. {
  56. return path_finder.TouchMapBlock(
  57. (int)((x) / m_TerrainSrc.GridCellW),
  58. (int)((y) / m_TerrainSrc.GridCellH));
  59. }
  60. /// <summary>
  61. /// 单位尝试移动,并自动对齐到地图边界
  62. /// </summary>
  63. /// <param name="o"></param>
  64. /// <param name="x"></param>
  65. /// <param name="y"></param>
  66. /// <param name="dx"></param>
  67. /// <param name="dy"></param>
  68. /// <returns></returns>
  69. public virtual CommonAI.RTS.Manhattan.AstarManhattan.TryMoveToMapBorderResult TryMoveToMapBorder(InstanceZoneObject o, ref float x, ref float y, float dx, float dy)
  70. {
  71. return path_finder.TryMoveToMapBorder(ref x, ref y, dx, dy);
  72. }
  73. public virtual CommonAI.RTS.Manhattan.AstarManhattan.TryMoveToMapBorderResult TryMoveToMapBorder(InstanceZoneObject o, ref Vector2 pos, float dx, float dy)
  74. {
  75. float x = pos.X;
  76. float y = pos.Y;
  77. var result = path_finder.TryMoveToMapBorder(ref x, ref y, dx, dy);
  78. pos.SetX(x);
  79. pos.SetY(y);
  80. return result;
  81. }
  82. /// <summary>
  83. /// 单位视线是否和地图相交
  84. /// </summary>
  85. /// <param name="src"></param>
  86. /// <param name="sx"></param>
  87. /// <param name="sy"></param>
  88. /// <param name="dx"></param>
  89. /// <param name="dy"></param>
  90. /// <returns></returns>
  91. public virtual bool RaycastMap(InstanceUnit src, float sx, float sy, float dx, float dy)
  92. {
  93. if (CMath.includeRectPoint(0, 0, m_TerrainSrc.TotalWidth, m_TerrainSrc.TotalHeight, sx, sy) &&
  94. CMath.includeRectPoint(0, 0, m_TerrainSrc.TotalWidth, m_TerrainSrc.TotalHeight, dx, dy))
  95. {
  96. return path_finder.TouchMapLine(sx, sy, dx, dy);
  97. }
  98. return false;
  99. }
  100. public bool intersectMapByBlock(int bx, int by)
  101. {
  102. return path_finder.TouchMapBlock(bx, by);
  103. }
  104. public bool intersectMapByPos(float x, float y)
  105. {
  106. return path_finder.TouchMapBlock(
  107. (int)((x) / m_TerrainSrc.GridCellW),
  108. (int)((y) / m_TerrainSrc.GridCellH));
  109. }
  110. /// <summary>
  111. /// 当前单位是否和建筑碰撞
  112. /// </summary>
  113. /// <param name="a"></param>
  114. /// <returns></returns>
  115. public InstanceZoneObject intersectNearStaticBlockable(InstanceZoneObject a)
  116. {
  117. InstanceZoneObject ret = null;
  118. ForEachNearObjects(a.X, a.Y, (InstanceZoneObject o, ref bool cancel) =>
  119. {
  120. if (o.IsStaticBlockable && o.IntersectObj && TouchObject2(a, o))
  121. {
  122. ret = o;
  123. cancel = true;
  124. }
  125. });
  126. return ret;
  127. }
  128. /// <summary>
  129. /// 包含身体高度和建筑碰撞
  130. /// </summary>
  131. /// <param name="a"></param>
  132. /// <returns></returns>
  133. public InstanceZoneObject intersectNearStaticBlockableZ(InstanceZoneObject a)
  134. {
  135. InstanceZoneObject ret = null;
  136. ForEachNearObjects(a.X, a.Y, (InstanceZoneObject o, ref bool cancel) =>
  137. {
  138. if (o.IsStaticBlockable && o.IntersectObj)
  139. {
  140. if (CMath.IsIntersect2(a.Z, a.BodyHeight, o.Z, o.BodyHeight) && TouchObject2(a, o))
  141. {
  142. ret = o;
  143. cancel = true;
  144. }
  145. }
  146. });
  147. return ret;
  148. }
  149. /// <summary>
  150. /// 当前单位是否和单位碰撞
  151. /// </summary>
  152. /// <param name="a"></param>
  153. /// <returns></returns>
  154. public InstanceZoneObject intersectNearUnit(InstanceZoneObject a)
  155. {
  156. InstanceZoneObject ret = null;
  157. ForEachNearObjects(a.X, a.Y, (InstanceZoneObject o, ref bool cancel) =>
  158. {
  159. if ((o.IntersectObj) && TouchObject2(a, o))
  160. {
  161. ret = o;
  162. cancel = true;
  163. }
  164. });
  165. return ret;
  166. }
  167. #endregion
  168. //-------------------------------------------------------------------------------------------------------//
  169. #region MANHATTAN_MAP
  170. private ZoneManhattanMap path_terrain_data;
  171. private AstarManhattan path_finder;
  172. private ManhattanMapAreaGenerator path_terrain_area_gen;
  173. protected virtual void InitTerrain(ZoneEditor.SceneData data, int spaceDiv, out ZoneManhattanMap terrain_data, out AstarManhattan path_finder, out ManhattanMapAreaGenerator area_gen)
  174. {
  175. terrain_data = new ZoneManhattanMap(m_TerrainSrc.Clone() as ZoneInfo, Templates.TerrainDefinition);
  176. path_finder = new AstarManhattan(data.TemplateID, terrain_data, true, spaceDiv);
  177. area_gen = new ManhattanMapAreaGenerator(terrain_data.Data);
  178. }
  179. protected virtual void DisposeTerrain()
  180. {
  181. this.path_finder.Dispose();
  182. this.path_terrain_data.Dispose();
  183. this.path_finder = null;
  184. this.path_terrain_data = null;
  185. this.path_terrain_area_gen = null;
  186. this.sync_pos_list.Clear();
  187. }
  188. public AstarManhattan PathFinder
  189. {
  190. get { return path_finder; }
  191. }
  192. public ZoneManhattanMap PathFinderTerrain
  193. {
  194. get { return path_terrain_data; }
  195. }
  196. public ManhattanMapAreaGenerator TerrainAreaGenerator
  197. {
  198. get { return path_terrain_area_gen; }
  199. }
  200. public AstarManhattan.MWayPoint findPath(float sx, float sy, float dx, float dy)
  201. {
  202. AstarManhattan.MWayPoint ret;
  203. var result = path_finder.findPath(sx, sy, dx, dy, out ret);
  204. switch (result)
  205. {
  206. case AstarManhattan.FindPathResult.Cross:
  207. case AstarManhattan.FindPathResult.Destination:
  208. return ret;
  209. default:
  210. return null;
  211. }
  212. }
  213. public ZoneArea GetArea(float x, float y)
  214. {
  215. var node = PathFinder.GetMapNodeByPos(x, y) as ZoneMapNode;
  216. if (node != null)
  217. {
  218. return node.ServerArea;
  219. }
  220. return null;
  221. }
  222. public ZoneArea GetAreaByBlock(int bx, int by)
  223. {
  224. var node = PathFinder.GetMapNode(bx, by) as ZoneMapNode;
  225. if (node != null)
  226. {
  227. return node.ServerArea;
  228. }
  229. return null;
  230. }
  231. #endregion
  232. //-------------------------------------------------------------------------------------------------------//
  233. #region SPACE_DIVISION
  234. public int SpaceXCount { get { return mSpaceDiv.SpaceXCount; } }
  235. public int SpaceYCount { get { return mSpaceDiv.SpaceYCount; } }
  236. /// <summary>
  237. /// 按坐标取分割块
  238. /// </summary>
  239. /// <param name="x"></param>
  240. /// <param name="y"></param>
  241. /// <returns></returns>
  242. public SpaceDivision.SpaceCellNode GetSpaceCellNode(float x, float y)
  243. {
  244. return mSpaceDiv.GetSpaceCellNode(x, y);
  245. }
  246. /// <summary>
  247. /// 按格取分割块
  248. /// </summary>
  249. /// <param name="bx"></param>
  250. /// <param name="by"></param>
  251. /// <returns></returns>
  252. public SpaceDivision.SpaceCellNode GetSpaceCellNodeByBlock(int bx, int by)
  253. {
  254. return mSpaceDiv.GetSpaceCellNodeByBlock(bx, by);
  255. }
  256. public List<SpaceDivision.SpaceCellNode> ListSpaceCellNodes()
  257. {
  258. return mSpaceDiv.ListSpaceCellNodes();
  259. }
  260. /// <summary>
  261. /// 刷新空间分割位置为有改变
  262. /// </summary>
  263. /// <param name="obj"></param>
  264. internal void nearChange(InstanceZoneObject obj)
  265. {
  266. mSpaceDiv.NearChange(obj.mCurCellNode);
  267. }
  268. /// <summary>
  269. /// 清除空间位置
  270. /// </summary>
  271. /// <param name="obj"></param>
  272. internal void clearSpace(InstanceZoneObject obj)
  273. {
  274. mSpaceDiv.ClearSpace(obj.mCurCellNode);
  275. }
  276. internal bool swapSpace(InstanceZoneObject obj, bool nearchange)
  277. {
  278. SpaceDivision.SpaceCellNode old_cell = obj.CurrentSpaceCellNode;
  279. if (mSpaceDiv.SwapSpace(obj.mCurCellNode, obj.X, obj.Y, nearchange))
  280. {
  281. if (mOnObjectSpaceChanged != null)
  282. {
  283. SpaceDivision.SpaceCellNode new_cell = obj.CurrentSpaceCellNode;
  284. mOnObjectSpaceChanged.Invoke(this, obj, old_cell, new_cell);
  285. }
  286. return true;
  287. }
  288. return false;
  289. }
  290. internal void swapArea(InstanceZoneObject obj, ZoneArea o, ZoneArea n)
  291. {
  292. if (o != null && o.Enable) { o.do_onUnitLeave(obj); }
  293. if (n != null && n.Enable) { n.do_onUnitEnter(obj); }
  294. if (mOnObjectAreaChanged != null)
  295. {
  296. mOnObjectAreaChanged.Invoke(this, obj, o, n);
  297. }
  298. }
  299. /// <summary>
  300. /// 判断是否附近有位置变化
  301. /// </summary>
  302. /// <param name="x"></param>
  303. /// <param name="y"></param>
  304. /// <returns></returns>
  305. public bool IsNearChanged(float x, float y)
  306. {
  307. return mSpaceDiv.IsNearChanged(x, y);
  308. }
  309. public bool IsNearChanged(float x, float y, float r)
  310. {
  311. return mSpaceDiv.IsNearChanged(x, y, r);
  312. }
  313. public bool IsNearChanged(float x1, float y1, float x2, float y2)
  314. {
  315. return mSpaceDiv.IsNearChanged(x1, y1, x2, y2);
  316. }
  317. /// <summary>
  318. /// 获取当前坐标附近的所有单位容量
  319. /// </summary>
  320. /// <param name="x"></param>
  321. /// <param name="y"></param>
  322. /// <returns></returns>
  323. public int getNearObjectsCapacity(float x, float y)
  324. {
  325. return mSpaceDiv.GetNearObjectsCapacity(x, y);
  326. }
  327. //---------------------------------------------------------------------------------------------------------------
  328. #region _Deprecated_
  329. /// <summary>
  330. /// 获取当前坐标附近的所有单位
  331. /// </summary>
  332. /// <param name="x"></param>
  333. /// <param name="y"></param>
  334. /// <returns></returns>
  335. [Obsolete("use {@link #ForEachNearObjects} for best performance!")]
  336. public List<InstanceZoneObject> getNearObjects(float x, float y)
  337. {
  338. List<InstanceZoneObject> list = new List<InstanceZoneObject>(getNearObjectsCapacity(x, y));
  339. getNearObjects(x, y, list);
  340. return list;
  341. }
  342. /// <summary>
  343. /// 获取当前圆形坐标附近所有单位
  344. /// </summary>
  345. /// <param name="x"></param>
  346. /// <param name="y"></param>
  347. /// <param name="r"></param>
  348. /// <returns></returns>
  349. [Obsolete("use {@link #ForEachNearObjects} for best performance!")]
  350. public List<InstanceZoneObject> getNearObjects(float x, float y, float r)
  351. {
  352. List<InstanceZoneObject> list = new List<InstanceZoneObject>(getNearObjectsCapacity(x, y));
  353. getNearObjects(x, y, r, list);
  354. return list;
  355. }
  356. /// <summary>
  357. /// 获取当前矩形附近所有单位
  358. /// </summary>
  359. /// <param name="x1"></param>
  360. /// <param name="y1"></param>
  361. /// <param name="x2"></param>
  362. /// <param name="y2"></param>
  363. /// <returns></returns>
  364. [Obsolete("use {@link #ForEachNearObjectsRect} for best performance!")]
  365. public List<InstanceZoneObject> getNearObjectsRect(float x1, float y1, float x2, float y2)
  366. {
  367. List<InstanceZoneObject> list = new List<InstanceZoneObject>();
  368. getNearObjectsRect(x1, y1, x2, y2, list);
  369. return list;
  370. }
  371. //----------------------------------------------------------------------------------------------------------------------------
  372. /// <summary>
  373. /// 获取当前坐标附近的所有单位
  374. /// </summary>
  375. /// <param name="x"></param>
  376. /// <param name="y"></param>
  377. /// <param name="list"></param>
  378. [Obsolete]
  379. private void getNearObjects(float x, float y, List<InstanceZoneObject> list)
  380. {
  381. SpaceDivision.SpaceCellNode node = mSpaceDiv.GetSpaceCellNode(x, y);
  382. if (node != null)
  383. {
  384. list.AddRange(node.AsChildList<InstanceZoneObject>());
  385. for (int i = node.nears.Count - 1; i >= 0; --i)
  386. {
  387. list.AddRange(node.nears[i].AsChildList<InstanceZoneObject>());
  388. }
  389. }
  390. }
  391. /// <summary>
  392. /// 获取当前坐标附近的所有单位
  393. /// </summary>
  394. /// <param name="x"></param>
  395. /// <param name="y"></param>
  396. /// <param name="r"></param>
  397. /// <param name="list"></param>
  398. [Obsolete]
  399. private void getNearObjects(float x, float y, float r, List<InstanceZoneObject> list)
  400. {
  401. if (r < mSpaceDiv.SpaceCellW && r < mSpaceDiv.SpaceCellH)
  402. {
  403. SpaceDivision.SpaceCellNode node = mSpaceDiv.GetSpaceCellNode(x, y);
  404. if (node != null)
  405. {
  406. list.AddRange(node.AsChildList<InstanceZoneObject>());
  407. for (int i = node.nears.Count - 1; i >= 0; --i)
  408. {
  409. list.AddRange(node.nears[i].AsChildList<InstanceZoneObject>());
  410. }
  411. }
  412. }
  413. else
  414. {
  415. int cx1 = ((int)((x - r) / mSpaceDiv.SpaceCellW)) - 1;
  416. int cy1 = ((int)((y - r) / mSpaceDiv.SpaceCellH)) - 1;
  417. int cx2 = ((int)((x + r) / mSpaceDiv.SpaceCellW)) + 1;
  418. int cy2 = ((int)((y + r) / mSpaceDiv.SpaceCellH)) + 1;
  419. cx1 = Math.Max(cx1, 0);
  420. cy1 = Math.Max(cy1, 0);
  421. cx2 = Math.Min(cx2, mSpaceDiv.SpaceXCount - 1);
  422. cy2 = Math.Min(cy2, mSpaceDiv.SpaceYCount - 1);
  423. for (int cx = cx1; cx <= cx2; ++cx)
  424. {
  425. for (int cy = cy1; cy <= cy2; ++cy)
  426. {
  427. SpaceDivision.SpaceCellNode cn = mSpaceDiv.GetSpaceCellNodeByBlock(cx, cy);
  428. list.AddRange(cn.AsChildList<InstanceZoneObject>());
  429. }
  430. }
  431. }
  432. }
  433. /// <summary>
  434. /// 获取当前坐标附近的所有单位
  435. /// </summary>
  436. /// <param name="x1"></param>
  437. /// <param name="y1"></param>
  438. /// <param name="x2"></param>
  439. /// <param name="y2"></param>
  440. /// <param name="list"></param>
  441. [Obsolete]
  442. private void getNearObjectsRect(float x1, float y1, float x2, float y2, List<InstanceZoneObject> list)
  443. {
  444. int cx1 = ((int)((Math.Min(x1, x2)) / mSpaceDiv.SpaceCellW)) - 1;
  445. int cy1 = ((int)((Math.Min(y1, y2)) / mSpaceDiv.SpaceCellH)) - 1;
  446. int cx2 = ((int)((Math.Max(x1, x2)) / mSpaceDiv.SpaceCellW)) + 1;
  447. int cy2 = ((int)((Math.Max(y1, y2)) / mSpaceDiv.SpaceCellH)) + 1;
  448. cx1 = Math.Max(cx1, 0);
  449. cy1 = Math.Max(cy1, 0);
  450. cx2 = Math.Min(cx2, mSpaceDiv.SpaceXCount - 1);
  451. cy2 = Math.Min(cy2, mSpaceDiv.SpaceYCount - 1);
  452. for (int cx = cx1; cx <= cx2; ++cx)
  453. {
  454. for (int cy = cy1; cy <= cy2; ++cy)
  455. {
  456. SpaceDivision.SpaceCellNode cn = mSpaceDiv.GetSpaceCellNodeByBlock(cx, cy);
  457. list.AddRange(cn.AsChildList<InstanceZoneObject>());
  458. }
  459. }
  460. }
  461. #endregion
  462. //----------------------------------------------------------------------------------------------------------------------------
  463. /// <summary>
  464. /// 获取当前坐标附近的所有单位
  465. /// </summary>
  466. /// <param name="x"></param>
  467. /// <param name="y"></param>
  468. /// <param name="indexer"></param>
  469. /// <returns>is cancel</returns>
  470. public bool ForEachNearObjects<T>(float x, float y, SpaceDivision.ObjectForEachAction<T> indexer) where T : InstanceZoneObject
  471. {
  472. return mSpaceDiv.ForEachNearObjects(x, y, indexer);
  473. }
  474. /// <summary>
  475. /// 获取当前坐标附近的所有单位
  476. /// </summary>
  477. /// <param name="x"></param>
  478. /// <param name="y"></param>
  479. /// <param name="r"></param>
  480. /// <param name="indexer"></param>
  481. /// <returns>is cancel</returns>
  482. public bool ForEachNearObjects<T>(float x, float y, float r, SpaceDivision.ObjectForEachAction<T> indexer) where T : InstanceZoneObject
  483. {
  484. return mSpaceDiv.ForEachNearObjects(x, y, r, indexer);
  485. }
  486. /// <summary>
  487. /// 获取当前坐标附近的所有单位
  488. /// </summary>
  489. /// <param name="x1"></param>
  490. /// <param name="y1"></param>
  491. /// <param name="x2"></param>
  492. /// <param name="y2"></param>
  493. /// <param name="indexer"></param>
  494. /// <returns>is cancel</returns>
  495. public bool ForEachNearObjectsRect<T>(float x1, float y1, float x2, float y2, SpaceDivision.ObjectForEachAction<T> indexer) where T : InstanceZoneObject
  496. {
  497. return mSpaceDiv.ForEachNearObjectsRect(x1, y1, x2, y2, indexer);
  498. }
  499. //----------------------------------------------------------------------------------------------------------------------------
  500. /// <summary>
  501. /// 获取【矩形】范围内的所有单位
  502. /// </summary>
  503. /// <typeparam name="T"></typeparam>
  504. /// <param name="func"></param>
  505. /// <param name="x1"></param>
  506. /// <param name="y1"></param>
  507. /// <param name="x2"></param>
  508. /// <param name="y2"></param>
  509. /// <param name="list"></param>
  510. /// <param name="aoi"></param>
  511. /// <returns></returns>
  512. public int getObjectsRectRange<T>(
  513. Collider.ObjectBodyTouchRect func,
  514. float x1, float y1,
  515. float x2, float y2,
  516. List<T> list, ObjectAoiStatus aoi) where T : InstanceZoneObject
  517. {
  518. int count = 0;
  519. ForEachNearObjectsRect<T>(x1, y1, x2, y2, (T o, ref bool cancel) =>
  520. {
  521. if (o.AoiStatus == aoi && func(o, x1, y1, x2, y2))
  522. {
  523. if (list != null) list.Add(o as T);
  524. count++;
  525. }
  526. });
  527. return count;
  528. }
  529. [Obsolete]
  530. public List<T> getObjectsRectRange<T>(
  531. Collider.ObjectBodyTouchRect func,
  532. float x1, float y1,
  533. float x2, float y2, ObjectAoiStatus aoi) where T : InstanceZoneObject
  534. {
  535. List<T> ret = new List<T>(getNearObjectsCapacity(x1, y1));
  536. getObjectsRectRange<T>(func, x1, y1, x2, y2, ret, aoi);
  537. return ret;
  538. }
  539. public int getObjectsCountRectRange<T>(
  540. Collider.ObjectBodyTouchRect func,
  541. float x1, float y1,
  542. float x2, float y2, ObjectAoiStatus aoi) where T : InstanceZoneObject
  543. {
  544. return getObjectsRectRange<T>(func, x1, y1, x2, y2, null, aoi);
  545. }
  546. /// <summary>
  547. /// 获取【圆形】范围内的所有单位
  548. /// </summary>
  549. /// <typeparam name="T"></typeparam>
  550. /// <param name="func"></param>
  551. /// <param name="x"></param>
  552. /// <param name="y"></param>
  553. /// <param name="r"></param>
  554. /// <param name="list"></param>
  555. /// <param name="aoi"></param>
  556. /// <returns></returns>
  557. public int getObjectsRoundRange<T>(
  558. Collider.ObjectBodyTouchRound func,
  559. float x, float y, float r,
  560. List<T> list, ObjectAoiStatus aoi) where T : InstanceZoneObject
  561. {
  562. int count = 0;
  563. ForEachNearObjects(x, y, r, (T o, ref bool cancel) =>
  564. {
  565. if (o.AoiStatus == aoi && func(o, x, y, r))
  566. {
  567. if (list != null) list.Add(o as T);
  568. count++;
  569. }
  570. });
  571. return count;
  572. }
  573. //单位是否在范围内
  574. public InstanceUnit isUnitInRoundRange<T>(int unitID, float x, float y, float r, ObjectAoiStatus aoi) where T : InstanceUnit
  575. {
  576. InstanceUnit unit = null;
  577. ForEachNearObjects(x, y, r, (T o, ref bool cancel) =>
  578. {
  579. if (o.AoiStatus == aoi && o.Info.TemplateID == unitID)
  580. {
  581. cancel = true;
  582. unit = o;
  583. }
  584. });
  585. return unit;
  586. }
  587. [Obsolete]
  588. public List<T> getObjectsRoundRange<T>(
  589. Collider.ObjectBodyTouchRound func,
  590. float x, float y, float r, ObjectAoiStatus aoi) where T : InstanceZoneObject
  591. {
  592. List<T> ret = new List<T>(getNearObjectsCapacity(x, y));
  593. getObjectsRoundRange<T>(func, x, y, r, ret, aoi);
  594. return ret;
  595. }
  596. public int getObjectsCountRoundRange<T>(
  597. Collider.ObjectBodyTouchRound func,
  598. float x, float y, float r, ObjectAoiStatus aoi) where T : InstanceZoneObject
  599. {
  600. return getObjectsRoundRange<T>(func, x, y, r, null, aoi);
  601. }
  602. /// <summary>
  603. /// 获取【扇形】范围内的所有单位,扇形范围为【弧度】
  604. /// </summary>
  605. /// <typeparam name="T"></typeparam>
  606. /// <param name="func"></param>
  607. /// <param name="x"></param>
  608. /// <param name="y"></param>
  609. /// <param name="distance"></param>
  610. /// <param name="startAngle"></param>
  611. /// <param name="endAngle"></param>
  612. /// <param name="list"></param>
  613. /// <param name="aoi"></param>
  614. /// <returns></returns>
  615. public int getObjectsFanRange<T>(
  616. Collider.ObjectBodyTouchFan func,
  617. float x, float y, float distance,
  618. float startAngle, float endAngle,
  619. List<T> list, ObjectAoiStatus aoi) where T : InstanceZoneObject
  620. {
  621. int count = 0;
  622. ForEachNearObjects(x, y, distance, (T o, ref bool cancel) =>
  623. {
  624. if (o.AoiStatus == aoi && func(o, x, y, distance, startAngle, endAngle))
  625. {
  626. if (list != null) list.Add(o as T);
  627. count++;
  628. }
  629. });
  630. return count;
  631. }
  632. [Obsolete]
  633. public List<T> getObjectsFanRange<T>(
  634. Collider.ObjectBodyTouchFan func,
  635. float x, float y, float distance,
  636. float startAngle, float endAngle, ObjectAoiStatus aoi) where T : InstanceZoneObject
  637. {
  638. List<T> ret = new List<T>(getNearObjectsCapacity(x, y));
  639. getObjectsFanRange<T>(func, x, y, distance, startAngle, endAngle, ret, aoi);
  640. return ret;
  641. }
  642. /// <summary>
  643. /// 获取【直线】穿过范围内的所有单位(粗线段)
  644. /// </summary>
  645. /// <typeparam name="T"></typeparam>
  646. /// <param name="func"></param>
  647. /// <param name="x1"></param>
  648. /// <param name="y1"></param>
  649. /// <param name="x2"></param>
  650. /// <param name="y2"></param>
  651. /// <param name="line_r"></param>
  652. /// <param name="list"></param>
  653. /// <param name="aoi"></param>
  654. /// <returns></returns>
  655. public int getObjectsRectLineRange<T>(
  656. Collider.ObjectBodyTouchRectLine func,
  657. float x1, float y1, float x2, float y2, float line_r,
  658. List<T> list, ObjectAoiStatus aoi) where T : InstanceZoneObject
  659. {
  660. int count = 0;
  661. ForEachNearObjectsRect(x1, y1, x2, y2, (T o, ref bool cancel) =>
  662. {
  663. if (o.AoiStatus == aoi && func(o, x1, y1, x2, y2, line_r))
  664. {
  665. if (list != null) list.Add(o as T);
  666. count++;
  667. }
  668. });
  669. return count;
  670. }
  671. [Obsolete]
  672. public List<T> getObjectsRectLineRange<T>(
  673. Collider.ObjectBodyTouchRectLine func,
  674. float x1, float y1, float x2, float y2, float line_r, ObjectAoiStatus aoi) where T : InstanceZoneObject
  675. {
  676. List<T> ret = new List<T>(getNearObjectsCapacity(x1, y1));
  677. getObjectsRectLineRange(func, x1, y1, x2, y2, line_r, ret, aoi);
  678. return ret;
  679. }
  680. /// <summary>
  681. /// 单位【运动轨迹】从A点移动到B点经过的碰撞
  682. /// </summary>
  683. /// <typeparam name="T"></typeparam>
  684. /// <param name="func"></param>
  685. /// <param name="sx"></param>
  686. /// <param name="sy"></param>
  687. /// <param name="dx"></param>
  688. /// <param name="dy"></param>
  689. /// <param name="line_r"></param>
  690. /// <param name="list"></param>
  691. /// <param name="aoi"></param>
  692. /// <returns></returns>
  693. public int getObjectsRoundLineRange<T>(
  694. Collider.ObjectBodyTouchRoundLine func,
  695. float sx, float sy, float dx, float dy, float line_r,
  696. List<T> list , ObjectAoiStatus aoi) where T : InstanceZoneObject
  697. {
  698. int count = 0;
  699. ForEachNearObjectsRect(sx, sy, dx, dy, (T o, ref bool cancel) =>
  700. {
  701. if (aoi == o.AoiStatus && func(o, sx, sy, dx, dy, line_r))
  702. {
  703. if (list != null) list.Add(o as T);
  704. count++;
  705. }
  706. });
  707. return count;
  708. }
  709. [Obsolete]
  710. public List<T> getObjectsRoundLineRange<T>(
  711. Collider.ObjectBodyTouchRoundLine func,
  712. float sx, float sy, float dx, float dy, float line_r, ObjectAoiStatus aoi) where T : InstanceZoneObject
  713. {
  714. List<T> ret = new List<T>(getNearObjectsCapacity(sx, sy));
  715. getObjectsRoundLineRange<T>(func, sx, sy, dx, dy, line_r, ret , aoi);
  716. return ret;
  717. }
  718. #endregion
  719. //-------------------------------------------------------------------------------------------------------//
  720. #region SYNC_POS
  721. /// <summary>
  722. /// 获得场景当前所有装饰物状态
  723. /// </summary>
  724. /// <returns></returns>
  725. public ZoneClient.SyncFlagsEvent GetSyncFlagsEvent()
  726. {
  727. var ret = new ZoneClient.SyncFlagsEvent();
  728. foreach (InstanceFlag flag in mFlags.Values)
  729. {
  730. if (flag is ZoneDecoration)
  731. {
  732. ZoneDecoration d = flag as ZoneDecoration;
  733. if (!d.Enable)
  734. {
  735. ret.ClosedDecorations.Add(d.Name);
  736. }
  737. }
  738. if (flag.Tag != flag.SrcTag)
  739. {
  740. ret.ChangedTags.Add(flag.Name, flag.Tag);
  741. }
  742. }
  743. return ret;
  744. }
  745. /// <summary>
  746. /// 获得所有单位同步信息,一般在进入场景时同步
  747. /// </summary>
  748. /// <param name="exclude"></param>
  749. /// <returns></returns>
  750. public ZoneClient.SyncObjectsEvent GetSyncUnitsEvent(InstanceUnit exclude = null)
  751. {
  752. var objs = mObjects.Objects;
  753. ZoneClient.SyncObjectsEvent ret = new ZoneClient.SyncObjectsEvent(mObjects.ObjectsCount);
  754. foreach (InstanceZoneObject o in objs)
  755. {
  756. if ((exclude == null || o != exclude) && o.ClientVisible)
  757. {
  758. var sync = o.GenSyncInfo(true);
  759. ret.Objects.Add(sync);
  760. }
  761. }
  762. return ret;
  763. }
  764. /// <summary>
  765. /// 获得半径内所有单位同步信息
  766. /// </summary>
  767. /// <param name="x"></param>
  768. /// <param name="y"></param>
  769. /// <param name="r"></param>
  770. /// <param name="exclude"></param>
  771. /// <returns></returns>
  772. public ZoneClient.SyncObjectsEvent GetSyncUnitsEventInRange(float x, float y, float r, InstanceUnit exclude = null)
  773. {
  774. ZoneClient.SyncObjectsEvent ret = new ZoneClient.SyncObjectsEvent(getNearObjectsCapacity(x, y));
  775. ForEachNearObjects(x, y, r, (InstanceZoneObject o, ref bool cancel) =>
  776. {
  777. if ((exclude == null || o != exclude) && o.ClientVisible)
  778. {
  779. if (Collider.Object_Pos_IncludeInRound(o, x, y, r))
  780. {
  781. var sync = o.GenSyncInfo(true);
  782. ret.Objects.Add(sync);
  783. }
  784. }
  785. });
  786. return ret;
  787. }
  788. /// <summary>
  789. /// 获得空间分割块所有单位同步信息
  790. /// </summary>
  791. /// <param name="bx"></param>
  792. /// <param name="by"></param>
  793. /// <param name="exclude"></param>
  794. /// <returns></returns>
  795. public ZoneClient.SyncObjectsEvent GetSyncUnitsEventBySpace(int bx, int by, InstanceUnit exclude = null)
  796. {
  797. SpaceDivision.SpaceCellNode space = GetSpaceCellNodeByBlock(bx, by);
  798. if (space != null)
  799. {
  800. ZoneClient.SyncObjectsEvent ret = new ZoneClient.SyncObjectsEvent(space.Count);
  801. space.ForEach((InstanceZoneObject o, ref bool cancel) =>
  802. {
  803. if ((exclude == null || o != exclude) && o.ClientVisible)
  804. {
  805. var sync = o.GenSyncInfo(true);
  806. ret.Objects.Add(sync);
  807. }
  808. });
  809. return ret;
  810. }
  811. return null;
  812. }
  813. public ZoneClient.SyncObjectsEvent GetSyncObjectsEvent(ICollection<InstanceZoneObject> objs)
  814. {
  815. ZoneClient.SyncObjectsEvent ret = new ZoneClient.SyncObjectsEvent(objs.Count);
  816. foreach (InstanceZoneObject o in objs)
  817. {
  818. if (o.ClientVisible)
  819. {
  820. var sync = o.GenSyncInfo(true);
  821. ret.Objects.Add(sync);
  822. }
  823. }
  824. return ret;
  825. }
  826. /// <summary>
  827. /// 得到半径范围内的所有移动信息
  828. /// </summary>
  829. /// <param name="x"></param>
  830. /// <param name="y"></param>
  831. /// <param name="range"></param>
  832. /// <returns></returns>
  833. public SyncPosEvent GetSyncPosEventInRange(float x, float y, float range)
  834. {
  835. using (var units = ListObjectPool<SyncPosEvent.UnitPos>.AllocAutoRelease())
  836. using (var units_st = ListObjectPool<SyncPosEvent.UnitState>.AllocAutoRelease())
  837. {
  838. SyncPosEvent.UnitPos pos = new SyncPosEvent.UnitPos();
  839. SyncPosEvent.UnitState st = new SyncPosEvent.UnitState();
  840. ForEachNearObjects(x, y, range, (InstanceZoneObject u, ref bool cancel) =>
  841. {
  842. if (u.ClientVisible && u.SyncPos && u.mCurCellNode.PosDirty())
  843. {
  844. if (Collider.Object_Pos_IncludeInRound(u, x, y, range))
  845. {
  846. if (u.GenSyncPos(ref pos))
  847. {
  848. units.Add(pos);
  849. }
  850. if (u is InstanceUnit)
  851. {
  852. InstanceUnit unit = u as InstanceUnit;
  853. if (unit.GenSyncState(ref st))
  854. {
  855. units_st.Add(st);
  856. }
  857. }
  858. }
  859. }
  860. });
  861. if (units.Count > 0 || units_st.Count > 0)
  862. {
  863. SyncPosEvent ret = new SyncPosEvent(IsHalfSync, IsSyncZ, (uint)PassTimeMS);
  864. ret.units_pos = units.ToArray();
  865. ret.units_st = units_st.ToArray();
  866. return ret;
  867. }
  868. }
  869. return null;
  870. }
  871. /// <summary>
  872. /// 得到空间分割块范围内的所有移动信息
  873. /// </summary>
  874. /// <param name="bx"></param>
  875. /// <param name="by"></param>
  876. /// <returns></returns>
  877. public SyncPosEvent GetSyncPosEventBySpace(int bx, int by)
  878. {
  879. SpaceDivision.SpaceCellNode space = GetSpaceCellNodeByBlock(bx, by);
  880. if (space != null)
  881. {
  882. List<SyncPosEvent.UnitPos> units = new List<SyncPosEvent.UnitPos>(space.Count);
  883. List<SyncPosEvent.UnitState> units_st = new List<SyncPosEvent.UnitState>(space.Count);
  884. SyncPosEvent.UnitPos pos = new SyncPosEvent.UnitPos();
  885. SyncPosEvent.UnitState st = new SyncPosEvent.UnitState();
  886. space.ForEach((InstanceZoneObject u, ref bool cancel) =>
  887. {
  888. if (u.mCurCellNode.PosDirty() && u.ClientVisible && u.SyncPos)
  889. {
  890. if (u.GenSyncPos(ref pos))
  891. {
  892. units.Add(pos);
  893. }
  894. if (u is InstanceUnit)
  895. {
  896. InstanceUnit unit = u as InstanceUnit;
  897. if (unit.GenSyncState(ref st))
  898. {
  899. units_st.Add(st);
  900. }
  901. }
  902. }
  903. });
  904. if (units.Count > 0 || units_st.Count > 0)
  905. {
  906. SyncPosEvent ret = new SyncPosEvent(IsHalfSync, IsSyncZ, (uint)PassTimeMS);
  907. ret.units_pos = units.ToArray();
  908. ret.units_st = units_st.ToArray();
  909. return ret;
  910. }
  911. }
  912. return null;
  913. }
  914. public SyncPosEvent GetSyncPosEvent(ICollection<InstanceZoneObject> objs, InstancePlayer Actor, PlayerClientObject playerClient)
  915. {
  916. if (objs.Count > 0)
  917. {
  918. //using (var units = ListObjectPool<SyncPosEvent.UnitPos>.AllocAutoRelease())
  919. //using (var units_st = ListObjectPool<SyncPosEvent.UnitState>.AllocAutoRelease())
  920. List<SyncPosEvent.UnitPos> units = new List<SyncPosEvent.UnitPos>();
  921. List<SyncPosEvent.UnitState> units_st = new List<SyncPosEvent.UnitState>();
  922. {
  923. SyncPosEvent.UnitPos pos = new SyncPosEvent.UnitPos();
  924. SyncPosEvent.UnitState st = new SyncPosEvent.UnitState();
  925. foreach (InstanceZoneObject u in objs)
  926. {
  927. if (u.mCurCellNode.PosDirty() && u.ClientVisible && u.SyncPos)
  928. {
  929. InstanceUnit unitTemp = u as InstanceUnit;
  930. if(unitTemp != null && unitTemp.CurrentActionSubstate != 0 && Actor.CurrentActionSubstate != unitTemp.CurrentActionSubstate)
  931. {
  932. if (playerClient.RemoveInRange(u))
  933. {
  934. continue;
  935. }
  936. }
  937. if (u.GenSyncPos(ref pos))
  938. {
  939. units.Add(pos);
  940. }
  941. if (u is InstanceUnit)
  942. {
  943. InstanceUnit unit = u as InstanceUnit;
  944. if (unit.GenSyncState(ref st))
  945. {
  946. units_st.Add(st);
  947. }
  948. }
  949. }
  950. }
  951. if (units.Count > 0 || units_st.Count > 0)
  952. {
  953. SyncPosEvent ret = new SyncPosEvent(IsHalfSync, IsSyncZ, PassTimeMS);
  954. ret.units_pos = units.ToArray();
  955. ret.units_st = units_st.ToArray();
  956. return ret;
  957. }
  958. }
  959. }
  960. return null;
  961. }
  962. readonly private PositionList sync_pos_list = new PositionList();
  963. internal class PositionList
  964. {
  965. public bool Enable = true;
  966. private List<InstanceZoneObject> units = new List<InstanceZoneObject>();
  967. public void Add(InstanceZoneObject u)
  968. {
  969. if (Enable)
  970. {
  971. units.Add(u);
  972. }
  973. }
  974. public void Clear()
  975. {
  976. units.Clear();
  977. }
  978. public SyncPosEvent AsEvent(InstanceZone zone)
  979. {
  980. if (Enable)
  981. {
  982. using (var units_pos = ListObjectPool<SyncPosEvent.UnitPos>.AllocAutoRelease())
  983. using (var units_st = ListObjectPool<SyncPosEvent.UnitState>.AllocAutoRelease())
  984. {
  985. SyncPosEvent.UnitPos pos = new SyncPosEvent.UnitPos();
  986. SyncPosEvent.UnitState st = new SyncPosEvent.UnitState();
  987. for (int i = units.Count - 1; i >= 0; --i)
  988. {
  989. InstanceZoneObject obj = units[i];
  990. if (obj.GenSyncPos(ref pos))
  991. {
  992. units_pos.Add(pos);
  993. }
  994. if (obj is InstanceUnit)
  995. {
  996. InstanceUnit unit = obj as InstanceUnit;
  997. if (unit.GenSyncState(ref st))
  998. {
  999. units_st.Add(st);
  1000. }
  1001. }
  1002. }
  1003. SyncPosEvent ret = new SyncPosEvent(zone.IsHalfSync, zone.IsSyncZ, (uint)zone.PassTimeMS);
  1004. ret.units_pos = units_pos.ToArray();
  1005. ret.units_st = units_st.ToArray();
  1006. return ret;
  1007. }
  1008. }
  1009. return null;
  1010. }
  1011. public int Count { get { return units.Count; } }
  1012. }
  1013. #endregion
  1014. }
  1015. }