L2World.java 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770
  1. /*
  2. * This program is free software: you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation, either version 3 of the License, or (at your option) any later
  5. * version.
  6. *
  7. * This program is distributed in the hope that it will be useful, but WITHOUT
  8. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  9. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  10. * details.
  11. *
  12. * You should have received a copy of the GNU General Public License along with
  13. * this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. package com.l2jserver.gameserver.model;
  16. import gnu.trove.procedure.TObjectProcedure;
  17. import java.util.ArrayList;
  18. import java.util.Collection;
  19. import java.util.List;
  20. import java.util.Map;
  21. import java.util.logging.Level;
  22. import java.util.logging.Logger;
  23. import com.l2jserver.Config;
  24. import com.l2jserver.gameserver.datatables.AdminTable;
  25. import com.l2jserver.gameserver.datatables.CharNameTable;
  26. import com.l2jserver.gameserver.model.actor.L2Playable;
  27. import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
  28. import com.l2jserver.gameserver.model.actor.instance.L2PetInstance;
  29. import com.l2jserver.gameserver.util.L2TIntObjectHashMap;
  30. import com.l2jserver.gameserver.util.Point3D;
  31. import com.l2jserver.util.StringUtil;
  32. /**
  33. * This class ...
  34. *
  35. * @version $Revision: 1.21.2.5.2.7 $ $Date: 2005/03/27 15:29:32 $
  36. */
  37. public final class L2World
  38. {
  39. private static Logger _log = Logger.getLogger(L2World.class.getName());
  40. /**
  41. * Gracia border
  42. * Flying objects not allowed to the east of it.
  43. */
  44. public static final int GRACIA_MAX_X = -166168;
  45. public static final int GRACIA_MAX_Z = 6105;
  46. public static final int GRACIA_MIN_Z = -895;
  47. /*
  48. * biteshift, defines number of regions
  49. * note, shifting by 15 will result in regions corresponding to map tiles
  50. * shifting by 12 divides one tile to 8x8 regions
  51. */
  52. public static final int SHIFT_BY = 12;
  53. private static final int TILE_SIZE = 32768;
  54. /** Map dimensions */
  55. public static final int MAP_MIN_X = (Config.WORLD_X_MIN - 20) * TILE_SIZE;
  56. public static final int MAP_MAX_X = (Config.WORLD_X_MAX - 19) * TILE_SIZE;
  57. public static final int MAP_MIN_Y = (Config.WORLD_Y_MIN - 18) * TILE_SIZE;
  58. public static final int MAP_MAX_Y = (Config.WORLD_Y_MAX - 17) * TILE_SIZE;
  59. /** calculated offset used so top left region is 0,0 */
  60. public static final int OFFSET_X = Math.abs(MAP_MIN_X >> SHIFT_BY);
  61. public static final int OFFSET_Y = Math.abs(MAP_MIN_Y >> SHIFT_BY);
  62. /** number of regions */
  63. private static final int REGIONS_X = (MAP_MAX_X >> SHIFT_BY) + OFFSET_X;
  64. private static final int REGIONS_Y = (MAP_MAX_Y >> SHIFT_BY) + OFFSET_Y;
  65. //private FastMap<String, L2PcInstance> _allGms;
  66. /** HashMap(Integer Player id, L2PcInstance) containing all the players in game */
  67. private final L2TIntObjectHashMap<L2PcInstance> _allPlayers;
  68. /** L2ObjectHashMap(L2Object) containing all visible objects */
  69. private final L2TIntObjectHashMap<L2Object> _allObjects;
  70. private final L2TIntObjectHashMap<String> _allObjectsDebug;
  71. /** List with the pets instances and their owner id */
  72. private final L2TIntObjectHashMap<L2PetInstance> _petsInstance;
  73. private L2WorldRegion[][] _worldRegions;
  74. /**
  75. * Constructor of L2World.<BR><BR>
  76. */
  77. private L2World()
  78. {
  79. _allPlayers = new L2TIntObjectHashMap<L2PcInstance>();
  80. _allObjects = new L2TIntObjectHashMap<L2Object>();
  81. _allObjectsDebug = new L2TIntObjectHashMap<String>();
  82. _petsInstance = new L2TIntObjectHashMap<L2PetInstance>();
  83. initRegions();
  84. }
  85. /**
  86. * @return the current instance of L2World.
  87. */
  88. public static L2World getInstance()
  89. {
  90. return SingletonHolder._instance;
  91. }
  92. /**
  93. * Add L2Object object in _allObjects.<BR><BR>
  94. *
  95. * <B><U> Example of use </U> :</B><BR><BR>
  96. * <li> Withdraw an item from the warehouse, create an item</li>
  97. * <li> Spawn a L2Character (PC, NPC, Pet)</li><BR>
  98. * @param object
  99. */
  100. public void storeObject(L2Object object)
  101. {
  102. if (_allObjects.containsKey(object.getObjectId()))
  103. {
  104. _log.log(Level.WARNING, "--------[L2World] object: " + object + " already exist in OID map!--------");
  105. _log.log(Level.WARNING, "New object: " + StringUtil.getTraceString(Thread.currentThread().getStackTrace()));
  106. _log.log(Level.WARNING, "----------------- Previous Put -----------------");
  107. _log.log(Level.WARNING, "Previous: " + _allObjectsDebug.get(object.getObjectId()));
  108. _log.log(Level.WARNING, "---------------------- End ---------------------");
  109. return;
  110. }
  111. _allObjects.put(object.getObjectId(), object);
  112. _allObjectsDebug.put(object.getObjectId(), StringUtil.getTraceString(Thread.currentThread().getStackTrace()));
  113. }
  114. /**
  115. * Remove L2Object object from _allObjects of L2World.<BR><BR>
  116. *
  117. * <B><U> Example of use </U> :</B><BR><BR>
  118. * <li> Delete item from inventory, tranfer Item from inventory to warehouse</li>
  119. * <li> Crystallize item</li>
  120. * <li> Remove NPC/PC/Pet from the world</li><BR>
  121. *
  122. * @param object L2Object to remove from _allObjects of L2World
  123. *
  124. */
  125. public void removeObject(L2Object object)
  126. {
  127. _allObjects.remove(object.getObjectId()); // suggestion by whatev
  128. _allObjectsDebug.remove(object.getObjectId());
  129. }
  130. public void removeObjects(List<L2Object> list)
  131. {
  132. for (L2Object o : list)
  133. {
  134. if (o != null)
  135. {
  136. _allObjects.remove(o.getObjectId()); // suggestion by whatev
  137. _allObjectsDebug.remove(o.getObjectId());
  138. }
  139. }
  140. }
  141. public void removeObjects(L2Object[] objects)
  142. {
  143. for (L2Object o : objects)
  144. {
  145. _allObjects.remove(o.getObjectId()); // suggestion by whatev
  146. _allObjectsDebug.remove(o.getObjectId());
  147. }
  148. }
  149. /**
  150. * <B><U> Example of use </U> :</B><BR><BR>
  151. * <li> Client packets : Action, AttackRequest, RequestJoinParty, RequestJoinPledge...</li><BR>
  152. *
  153. * @param oID Identifier of the L2Object
  154. * @return the L2Object object that belongs to an ID or null if no object found.
  155. */
  156. public L2Object findObject(int oID)
  157. {
  158. return _allObjects.get(oID);
  159. }
  160. public final L2Object[] getAllVisibleObjectsArray()
  161. {
  162. return _allObjects.values(new L2Object[0]);
  163. }
  164. public final boolean forEachObject(final TObjectProcedure<L2Object> proc)
  165. {
  166. return _allObjects.forEachValue(proc);
  167. }
  168. /**
  169. * Get the count of all visible objects in world.<br><br>
  170. *
  171. * @return count off all L2World objects
  172. */
  173. public final int getAllVisibleObjectsCount()
  174. {
  175. return _allObjects.size();
  176. }
  177. /**
  178. * @return a table containing all GMs.
  179. */
  180. public List<L2PcInstance> getAllGMs()
  181. {
  182. return AdminTable.getInstance().getAllGms(true);
  183. }
  184. public L2TIntObjectHashMap<L2PcInstance> getAllPlayers()
  185. {
  186. return _allPlayers;
  187. }
  188. public final L2PcInstance[] getAllPlayersArray()
  189. {
  190. return _allPlayers.values(new L2PcInstance[0]);
  191. }
  192. public final boolean forEachPlayer(final TObjectProcedure<L2PcInstance> proc)
  193. {
  194. return _allPlayers.forEachValue(proc);
  195. }
  196. /**
  197. * Return how many players are online.<BR><BR>
  198. *
  199. * @return number of online players.
  200. */
  201. public int getAllPlayersCount()
  202. {
  203. return _allPlayers.size();
  204. }
  205. /**
  206. * <B>If you have access to player objectId use {@link #getPlayer(int playerObjId)}</B>
  207. * @param name Name of the player to get Instance
  208. * @return the player instance corresponding to the given name.
  209. */
  210. public L2PcInstance getPlayer(String name)
  211. {
  212. return getPlayer(CharNameTable.getInstance().getIdByName(name));
  213. }
  214. /**
  215. * @param playerObjId Object ID of the player to get Instance
  216. * @return the player instance corresponding to the given object ID.
  217. */
  218. public L2PcInstance getPlayer(int playerObjId)
  219. {
  220. return _allPlayers.get(playerObjId);
  221. }
  222. /**
  223. * @param ownerId ID of the owner
  224. * @return the pet instance from the given ownerId.
  225. */
  226. public L2PetInstance getPet(int ownerId)
  227. {
  228. return _petsInstance.get(ownerId);
  229. }
  230. /**
  231. * Add the given pet instance from the given ownerId.<BR><BR>
  232. *
  233. * @param ownerId ID of the owner
  234. * @param pet L2PetInstance of the pet
  235. * @return
  236. */
  237. public L2PetInstance addPet(int ownerId, L2PetInstance pet)
  238. {
  239. return _petsInstance.put(ownerId, pet);
  240. }
  241. /**
  242. * Remove the given pet instance.<BR><BR>
  243. *
  244. * @param ownerId ID of the owner
  245. */
  246. public void removePet(int ownerId)
  247. {
  248. _petsInstance.remove(ownerId);
  249. }
  250. /**
  251. * Remove the given pet instance.<BR><BR>
  252. *
  253. * @param pet the pet to remove
  254. */
  255. public void removePet(L2PetInstance pet)
  256. {
  257. _petsInstance.remove(pet.getOwner().getObjectId());
  258. }
  259. /**
  260. * Add a L2Object in the world.<BR><BR>
  261. *
  262. * <B><U> Concept</U> :</B><BR><BR>
  263. * L2Object (including L2PcInstance) are identified in <B>_visibleObjects</B> of his current L2WorldRegion and in <B>_knownObjects</B> of other surrounding L2Characters <BR>
  264. * L2PcInstance are identified in <B>_allPlayers</B> of L2World, in <B>_allPlayers</B> of his current L2WorldRegion and in <B>_knownPlayer</B> of other surrounding L2Characters <BR><BR>
  265. *
  266. * <B><U> Actions</U> :</B><BR><BR>
  267. * <li>Add the L2Object object in _allPlayers* of L2World </li>
  268. * <li>Add the L2Object object in _gmList** of GmListTable </li>
  269. * <li>Add object in _knownObjects and _knownPlayer* of all surrounding L2WorldRegion L2Characters </li><BR>
  270. *
  271. * <li>If object is a L2Character, add all surrounding L2Object in its _knownObjects and all surrounding L2PcInstance in its _knownPlayer </li><BR>
  272. *
  273. * <I>* only if object is a L2PcInstance</I><BR>
  274. * <I>** only if object is a GM L2PcInstance</I><BR><BR>
  275. *
  276. * <FONT COLOR=#FF0000><B> <U>Caution</U> : This method DOESN'T ADD the object in _visibleObjects and _allPlayers* of L2WorldRegion (need synchronisation)</B></FONT><BR>
  277. * <FONT COLOR=#FF0000><B> <U>Caution</U> : This method DOESN'T ADD the object to _allObjects and _allPlayers* of L2World (need synchronisation)</B></FONT><BR><BR>
  278. *
  279. * <B><U> Example of use </U> :</B><BR><BR>
  280. * <li> Drop an Item </li>
  281. * <li> Spawn a L2Character</li>
  282. * <li> Apply Death Penalty of a L2PcInstance </li><BR><BR>
  283. *
  284. * @param object L2object to add in the world
  285. * @param newRegion L2WorldRegion in wich the object will be add (not used)
  286. */
  287. public void addVisibleObject(L2Object object, L2WorldRegion newRegion)
  288. {
  289. // If selected L2Object is a L2PcIntance, add it in L2ObjectHashSet(L2PcInstance) _allPlayers of L2World
  290. // XXX TODO: this code should be obsoleted by protection in putObject func...
  291. if (object instanceof L2PcInstance)
  292. {
  293. L2PcInstance player = (L2PcInstance) object;
  294. if (!player.isTeleporting())
  295. {
  296. L2PcInstance tmp = getPlayer(player.getObjectId());
  297. if (tmp != null)
  298. {
  299. _log.warning("Duplicate character!? Closing both characters (" + player.getName() + ")");
  300. player.logout();
  301. tmp.logout();
  302. return;
  303. }
  304. addToAllPlayers(player);
  305. }
  306. }
  307. if (!newRegion.isActive())
  308. return;
  309. // Get all visible objects contained in the _visibleObjects of L2WorldRegions
  310. // in a circular area of 2000 units
  311. List<L2Object> visibles = getVisibleObjects(object, 2000);
  312. if (Config.DEBUG)
  313. _log.finest("objects in range:" + visibles.size());
  314. // tell the player about the surroundings
  315. // Go through the visible objects contained in the circular area
  316. for (L2Object visible : visibles)
  317. {
  318. if (visible == null)
  319. continue;
  320. // Add the object in L2ObjectHashSet(L2Object) _knownObjects of the visible L2Character according to conditions :
  321. // - L2Character is visible
  322. // - object is not already known
  323. // - object is in the watch distance
  324. // If L2Object is a L2PcInstance, add L2Object in L2ObjectHashSet(L2PcInstance) _knownPlayer of the visible L2Character
  325. visible.getKnownList().addKnownObject(object);
  326. // Add the visible L2Object in L2ObjectHashSet(L2Object) _knownObjects of the object according to conditions
  327. // If visible L2Object is a L2PcInstance, add visible L2Object in L2ObjectHashSet(L2PcInstance) _knownPlayer of the object
  328. object.getKnownList().addKnownObject(visible);
  329. }
  330. }
  331. /**
  332. * Add the L2PcInstance to _allPlayers of L2World.<BR><BR>
  333. * @param cha
  334. */
  335. public void addToAllPlayers(L2PcInstance cha)
  336. {
  337. _allPlayers.put(cha.getObjectId(), cha);
  338. }
  339. /**
  340. * Remove the L2PcInstance from _allPlayers of L2World.<BR><BR>
  341. *
  342. * <B><U> Example of use </U> :</B><BR><BR>
  343. * <li> Remove a player from the visible objects </li><BR>
  344. * @param cha
  345. */
  346. public void removeFromAllPlayers(L2PcInstance cha)
  347. {
  348. _allPlayers.remove(cha.getObjectId());
  349. }
  350. /**
  351. * Remove a L2Object from the world.<BR><BR>
  352. *
  353. * <B><U> Concept</U> :</B><BR><BR>
  354. * L2Object (including L2PcInstance) are identified in <B>_visibleObjects</B> of his current L2WorldRegion and in <B>_knownObjects</B> of other surrounding L2Characters <BR>
  355. * L2PcInstance are identified in <B>_allPlayers</B> of L2World, in <B>_allPlayers</B> of his current L2WorldRegion and in <B>_knownPlayer</B> of other surrounding L2Characters <BR><BR>
  356. *
  357. * <B><U> Actions</U> :</B><BR><BR>
  358. * <li>Remove the L2Object object from _allPlayers* of L2World </li>
  359. * <li>Remove the L2Object object from _visibleObjects and _allPlayers* of L2WorldRegion </li>
  360. * <li>Remove the L2Object object from _gmList** of GmListTable </li>
  361. * <li>Remove object from _knownObjects and _knownPlayer* of all surrounding L2WorldRegion L2Characters </li><BR>
  362. *
  363. * <li>If object is a L2Character, remove all L2Object from its _knownObjects and all L2PcInstance from its _knownPlayer </li><BR><BR>
  364. *
  365. * <FONT COLOR=#FF0000><B> <U>Caution</U> : This method DOESN'T REMOVE the object from _allObjects of L2World</B></FONT><BR><BR>
  366. *
  367. * <I>* only if object is a L2PcInstance</I><BR>
  368. * <I>** only if object is a GM L2PcInstance</I><BR><BR>
  369. *
  370. * <B><U> Example of use </U> :</B><BR><BR>
  371. * <li> Pickup an Item </li>
  372. * <li> Decay a L2Character</li><BR><BR>
  373. *
  374. * @param object L2object to remove from the world
  375. * @param oldRegion L2WorldRegion in which the object was before removing
  376. *
  377. */
  378. public void removeVisibleObject(L2Object object, L2WorldRegion oldRegion)
  379. {
  380. if (object == null)
  381. return;
  382. //removeObject(object);
  383. if (oldRegion != null)
  384. {
  385. // Remove the object from the L2ObjectHashSet(L2Object) _visibleObjects of L2WorldRegion
  386. // If object is a L2PcInstance, remove it from the L2ObjectHashSet(L2PcInstance) _allPlayers of this L2WorldRegion
  387. oldRegion.removeVisibleObject(object);
  388. // Go through all surrounding L2WorldRegion L2Characters
  389. for (L2WorldRegion reg : oldRegion.getSurroundingRegions())
  390. {
  391. Collection<L2Object> vObj = reg.getVisibleObjects().values();
  392. for (L2Object obj : vObj)
  393. {
  394. if (obj != null)
  395. {
  396. obj.getKnownList().removeKnownObject(object);
  397. object.getKnownList().removeKnownObject(obj);
  398. }
  399. }
  400. }
  401. // If object is a L2Character :
  402. // Remove all L2Object from L2ObjectHashSet(L2Object) containing all L2Object detected by the L2Character
  403. // Remove all L2PcInstance from L2ObjectHashSet(L2PcInstance) containing all player ingame detected by the L2Character
  404. object.getKnownList().removeAllKnownObjects();
  405. // If selected L2Object is a L2PcIntance, remove it from L2ObjectHashSet(L2PcInstance) _allPlayers of L2World
  406. if (object instanceof L2PcInstance)
  407. {
  408. if (!((L2PcInstance) object).isTeleporting())
  409. removeFromAllPlayers((L2PcInstance) object);
  410. // If selected L2Object is a GM L2PcInstance, remove it from Set(L2PcInstance) _gmList of GmListTable
  411. //if (((L2PcInstance)object).isGM())
  412. //GmListTable.getInstance().deleteGm((L2PcInstance)object);
  413. }
  414. }
  415. }
  416. /**
  417. * Return all visible objects of the L2WorldRegion object's and of its surrounding L2WorldRegion.<BR><BR>
  418. *
  419. * <B><U> Concept</U> :</B><BR><BR>
  420. * All visible object are identified in <B>_visibleObjects</B> of their current L2WorldRegion <BR>
  421. * All surrounding L2WorldRegion are identified in <B>_surroundingRegions</B> of the selected L2WorldRegion in order to scan a large area around a L2Object<BR><BR>
  422. *
  423. * <B><U> Example of use </U> :</B><BR><BR>
  424. * <li> Find Close Objects for L2Character </li><BR>
  425. *
  426. * @param object L2object that determine the current L2WorldRegion
  427. * @return
  428. */
  429. public List<L2Object> getVisibleObjects(L2Object object)
  430. {
  431. L2WorldRegion reg = object.getWorldRegion();
  432. if (reg == null)
  433. return null;
  434. // Create an FastList in order to contain all visible L2Object
  435. List<L2Object> result = new ArrayList<L2Object>();
  436. // Go through the FastList of region
  437. for (L2WorldRegion regi : reg.getSurroundingRegions())
  438. {
  439. // Go through visible objects of the selected region
  440. Collection<L2Object> vObj = regi.getVisibleObjects().values();
  441. for (L2Object _object : vObj)
  442. {
  443. if (_object == null || _object.equals(object))
  444. continue; // skip our own character
  445. else if (!_object.isVisible())
  446. continue; // skip dying objects
  447. result.add(_object);
  448. }
  449. }
  450. return result;
  451. }
  452. /**
  453. * Return all visible objects of the L2WorldRegions in the circular area (radius) centered on the object.<BR><BR>
  454. *
  455. * <B><U> Concept</U> :</B><BR><BR>
  456. * All visible object are identified in <B>_visibleObjects</B> of their current L2WorldRegion <BR>
  457. * All surrounding L2WorldRegion are identified in <B>_surroundingRegions</B> of the selected L2WorldRegion in order to scan a large area around a L2Object<BR><BR>
  458. *
  459. * <B><U> Example of use </U> :</B><BR><BR>
  460. * <li> Define the aggrolist of monster </li>
  461. * <li> Define visible objects of a L2Object </li>
  462. * <li> Skill : Confusion... </li><BR>
  463. *
  464. * @param object L2object that determine the center of the circular area
  465. * @param radius Radius of the circular area
  466. * @return
  467. */
  468. public List<L2Object> getVisibleObjects(L2Object object, int radius)
  469. {
  470. if (object == null || !object.isVisible())
  471. return new ArrayList<L2Object>();
  472. int x = object.getX();
  473. int y = object.getY();
  474. int sqRadius = radius * radius;
  475. // Create an FastList in order to contain all visible L2Object
  476. List<L2Object> result = new ArrayList<L2Object>();
  477. // Go through the FastList of region
  478. for (L2WorldRegion regi : object.getWorldRegion().getSurroundingRegions())
  479. {
  480. // Go through visible objects of the selected region
  481. Collection<L2Object> vObj = regi.getVisibleObjects().values();
  482. for (L2Object _object : vObj)
  483. {
  484. if (_object == null || _object.equals(object))
  485. continue; // skip our own character
  486. int x1 = _object.getX();
  487. int y1 = _object.getY();
  488. double dx = x1 - x;
  489. double dy = y1 - y;
  490. if (dx * dx + dy * dy < sqRadius)
  491. result.add(_object);
  492. }
  493. }
  494. return result;
  495. }
  496. /**
  497. * Return all visible objects of the L2WorldRegions in the spheric area (radius) centered on the object.<BR><BR>
  498. *
  499. * <B><U> Concept</U> :</B><BR><BR>
  500. * All visible object are identified in <B>_visibleObjects</B> of their current L2WorldRegion <BR>
  501. * All surrounding L2WorldRegion are identified in <B>_surroundingRegions</B> of the selected L2WorldRegion in order to scan a large area around a L2Object<BR><BR>
  502. *
  503. * <B><U> Example of use </U> :</B><BR><BR>
  504. * <li> Define the target list of a skill </li>
  505. * <li> Define the target list of a polearme attack </li><BR><BR>
  506. *
  507. * @param object L2object that determine the center of the circular area
  508. * @param radius Radius of the spheric area
  509. * @return
  510. */
  511. public List<L2Object> getVisibleObjects3D(L2Object object, int radius)
  512. {
  513. if (object == null || !object.isVisible())
  514. return new ArrayList<L2Object>();
  515. int x = object.getX();
  516. int y = object.getY();
  517. int z = object.getZ();
  518. int sqRadius = radius * radius;
  519. // Create an FastList in order to contain all visible L2Object
  520. List<L2Object> result = new ArrayList<L2Object>();
  521. // Go through visible object of the selected region
  522. for (L2WorldRegion regi : object.getWorldRegion().getSurroundingRegions())
  523. {
  524. Collection<L2Object> vObj = regi.getVisibleObjects().values();
  525. for (L2Object _object : vObj)
  526. {
  527. if (_object == null || _object.equals(object))
  528. continue; // skip our own character
  529. int x1 = _object.getX();
  530. int y1 = _object.getY();
  531. int z1 = _object.getZ();
  532. long dx = x1 - x;
  533. long dy = y1 - y;
  534. long dz = z1 - z;
  535. if (dx * dx + dy * dy + dz * dz < sqRadius)
  536. result.add(_object);
  537. }
  538. }
  539. return result;
  540. }
  541. /**
  542. * <B><U> Concept</U> :</B><BR><BR>
  543. * All visible object are identified in <B>_visibleObjects</B> of their current L2WorldRegion <BR>
  544. * All surrounding L2WorldRegion are identified in <B>_surroundingRegions</B> of the selected L2WorldRegion in order to scan a large area around a L2Object<BR><BR>
  545. *
  546. * <B><U> Example of use </U> :</B><BR><BR>
  547. * <li> Find Close Objects for L2Character </li><BR>
  548. *
  549. * @param object L2object that determine the current L2WorldRegion
  550. * @return all visible players of the L2WorldRegion object's and of its surrounding L2WorldRegion.
  551. */
  552. public List<L2Playable> getVisiblePlayable(L2Object object)
  553. {
  554. L2WorldRegion reg = object.getWorldRegion();
  555. if (reg == null)
  556. return null;
  557. // Create an FastList in order to contain all visible L2Object
  558. List<L2Playable> result = new ArrayList<L2Playable>();
  559. // Go through the FastList of region
  560. for (L2WorldRegion regi : reg.getSurroundingRegions())
  561. {
  562. // Create an Iterator to go through the visible L2Object of the L2WorldRegion
  563. Map<Integer, L2Playable> _allpls = regi.getVisiblePlayable();
  564. Collection<L2Playable> _playables = _allpls.values();
  565. // Go through visible object of the selected region
  566. for (L2Playable _object : _playables)
  567. {
  568. if (_object == null || _object.equals(object))
  569. continue; // skip our own character
  570. if (!_object.isVisible()) // GM invisible is different than this...
  571. continue; // skip dying objects
  572. result.add(_object);
  573. }
  574. }
  575. return result;
  576. }
  577. /**
  578. * Calculate the current L2WorldRegions of the object according to its position (x,y).<BR><BR>
  579. *
  580. * <B><U> Example of use </U> :</B><BR><BR>
  581. * <li> Set position of a new L2Object (drop, spawn...) </li>
  582. * <li> Update position of a L2Object after a movement </li><BR>
  583. *
  584. * @param point position of the object
  585. * @return
  586. */
  587. public L2WorldRegion getRegion(Point3D point)
  588. {
  589. return _worldRegions[(point.getX() >> SHIFT_BY) + OFFSET_X][(point.getY() >> SHIFT_BY) + OFFSET_Y];
  590. }
  591. public L2WorldRegion getRegion(int x, int y)
  592. {
  593. return _worldRegions[(x >> SHIFT_BY) + OFFSET_X][(y >> SHIFT_BY) + OFFSET_Y];
  594. }
  595. /**
  596. * Returns the whole 2d array containing the world regions
  597. * used by ZoneData.java to setup zones inside the world regions
  598. * @return
  599. */
  600. public L2WorldRegion[][] getAllWorldRegions()
  601. {
  602. return _worldRegions;
  603. }
  604. /**
  605. * Check if the current L2WorldRegions of the object is valid according to its position (x,y).<BR><BR>
  606. *
  607. * <B><U> Example of use </U> :</B><BR><BR>
  608. * <li> Init L2WorldRegions </li><BR>
  609. *
  610. * @param x X position of the object
  611. * @param y Y position of the object
  612. *
  613. * @return True if the L2WorldRegion is valid
  614. */
  615. private boolean validRegion(int x, int y)
  616. {
  617. return (x >= 0 && x <= REGIONS_X && y >= 0 && y <= REGIONS_Y);
  618. }
  619. /**
  620. * Init each L2WorldRegion and their surrounding table.<BR><BR>
  621. *
  622. * <B><U> Concept</U> :</B><BR><BR>
  623. * All surrounding L2WorldRegion are identified in <B>_surroundingRegions</B> of the selected L2WorldRegion in order to scan a large area around a L2Object<BR><BR>
  624. *
  625. * <B><U> Example of use </U> :</B><BR><BR>
  626. * <li> Constructor of L2World </li><BR>
  627. *
  628. */
  629. private void initRegions()
  630. {
  631. _worldRegions = new L2WorldRegion[REGIONS_X + 1][REGIONS_Y + 1];
  632. for (int i = 0; i <= REGIONS_X; i++)
  633. {
  634. for (int j = 0; j <= REGIONS_Y; j++)
  635. {
  636. _worldRegions[i][j] = new L2WorldRegion(i, j);
  637. }
  638. }
  639. for (int x = 0; x <= REGIONS_X; x++)
  640. {
  641. for (int y = 0; y <= REGIONS_Y; y++)
  642. {
  643. for (int a = -1; a <= 1; a++)
  644. {
  645. for (int b = -1; b <= 1; b++)
  646. {
  647. if (validRegion(x + a, y + b))
  648. {
  649. _worldRegions[x + a][y + b].addSurroundingRegion(_worldRegions[x][y]);
  650. }
  651. }
  652. }
  653. }
  654. }
  655. _log.info("L2World: (" + REGIONS_X + " by " + REGIONS_Y + ") World Region Grid set up.");
  656. }
  657. /**
  658. * Deleted all spawns in the world.
  659. */
  660. public void deleteVisibleNpcSpawns()
  661. {
  662. _log.info("Deleting all visible NPC's.");
  663. for (int i = 0; i <= REGIONS_X; i++)
  664. {
  665. for (int j = 0; j <= REGIONS_Y; j++)
  666. {
  667. _worldRegions[i][j].deleteVisibleNpcSpawns();
  668. }
  669. }
  670. _log.info("All visible NPC's deleted.");
  671. }
  672. @SuppressWarnings("synthetic-access")
  673. private static class SingletonHolder
  674. {
  675. protected static final L2World _instance = new L2World();
  676. }
  677. }