L2World.java 25 KB

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