L2Object.java 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717
  1. /*
  2. * Copyright (C) 2004-2013 L2J Server
  3. *
  4. * This file is part of L2J Server.
  5. *
  6. * L2J Server is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * L2J Server is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. package com.l2jserver.gameserver.model;
  20. import java.util.Map;
  21. import javolution.util.FastMap;
  22. import com.l2jserver.gameserver.enums.InstanceType;
  23. import com.l2jserver.gameserver.enums.ShotType;
  24. import com.l2jserver.gameserver.handler.ActionHandler;
  25. import com.l2jserver.gameserver.handler.ActionShiftHandler;
  26. import com.l2jserver.gameserver.handler.IActionHandler;
  27. import com.l2jserver.gameserver.idfactory.IdFactory;
  28. import com.l2jserver.gameserver.instancemanager.InstanceManager;
  29. import com.l2jserver.gameserver.model.actor.L2Character;
  30. import com.l2jserver.gameserver.model.actor.L2Npc;
  31. import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
  32. import com.l2jserver.gameserver.model.actor.knownlist.ObjectKnownList;
  33. import com.l2jserver.gameserver.model.actor.poly.ObjectPoly;
  34. import com.l2jserver.gameserver.model.actor.position.ObjectPosition;
  35. import com.l2jserver.gameserver.model.entity.Instance;
  36. import com.l2jserver.gameserver.model.interfaces.IIdentifiable;
  37. import com.l2jserver.gameserver.model.interfaces.INamable;
  38. import com.l2jserver.gameserver.model.interfaces.ISpawnable;
  39. import com.l2jserver.gameserver.model.zone.ZoneId;
  40. import com.l2jserver.gameserver.network.SystemMessageId;
  41. import com.l2jserver.gameserver.network.serverpackets.ActionFailed;
  42. import com.l2jserver.gameserver.network.serverpackets.ExSendUIEvent;
  43. import com.l2jserver.gameserver.network.serverpackets.L2GameServerPacket;
  44. /**
  45. * Mother class of all objects in the world which ones is it possible to interact (PC, NPC, Item...)<BR>
  46. * <BR>
  47. * L2Object :<BR>
  48. * <BR>
  49. * <li>L2Character</li> <li>L2ItemInstance</li>
  50. */
  51. public abstract class L2Object extends ObjectPosition implements IIdentifiable, INamable, ISpawnable
  52. {
  53. private boolean _isVisible; // Object visibility
  54. private ObjectKnownList _knownList;
  55. private String _name;
  56. private int _objectId; // Object identifier
  57. private ObjectPoly _poly;
  58. private InstanceType _instanceType = null;
  59. private volatile Map<String, Object> _scripts;
  60. public L2Object(int objectId)
  61. {
  62. super();
  63. setInstanceType(InstanceType.L2Object);
  64. _objectId = objectId;
  65. initKnownList();
  66. setActiveObject(this);
  67. }
  68. protected final void setInstanceType(InstanceType i)
  69. {
  70. _instanceType = i;
  71. }
  72. public final InstanceType getInstanceType()
  73. {
  74. return _instanceType;
  75. }
  76. public final boolean isInstanceType(InstanceType i)
  77. {
  78. return _instanceType.isType(i);
  79. }
  80. public final boolean isInstanceTypes(InstanceType... i)
  81. {
  82. return _instanceType.isTypes(i);
  83. }
  84. public final void onAction(L2PcInstance player)
  85. {
  86. onAction(player, true);
  87. }
  88. public void onAction(L2PcInstance player, boolean interact)
  89. {
  90. IActionHandler handler = ActionHandler.getInstance().getHandler(getInstanceType());
  91. if (handler != null)
  92. {
  93. handler.action(player, this, interact);
  94. }
  95. player.sendPacket(ActionFailed.STATIC_PACKET);
  96. }
  97. public void onActionShift(L2PcInstance player)
  98. {
  99. IActionHandler handler = ActionShiftHandler.getInstance().getHandler(getInstanceType());
  100. if (handler != null)
  101. {
  102. handler.action(player, this, true);
  103. }
  104. player.sendPacket(ActionFailed.STATIC_PACKET);
  105. }
  106. public void onForcedAttack(L2PcInstance player)
  107. {
  108. player.sendPacket(ActionFailed.STATIC_PACKET);
  109. }
  110. /**
  111. * Do Nothing.<BR>
  112. * <BR>
  113. * <B><U> Overridden in </U> :</B><BR>
  114. * <BR>
  115. * <li>L2GuardInstance : Set the home location of its L2GuardInstance</li> <li>L2Attackable : Reset the Spoiled flag</li><BR>
  116. * <BR>
  117. */
  118. public void onSpawn()
  119. {
  120. }
  121. /**
  122. * UnAfraid: TODO: Add listener here.
  123. * @param instanceId The id of the instance zone the object is in - id 0 is global
  124. */
  125. @Override
  126. public void setInstanceId(int instanceId)
  127. {
  128. if ((instanceId < 0) || (getInstanceId() == instanceId))
  129. {
  130. return;
  131. }
  132. Instance oldI = InstanceManager.getInstance().getInstance(getInstanceId());
  133. Instance newI = InstanceManager.getInstance().getInstance(instanceId);
  134. if (newI == null)
  135. {
  136. return;
  137. }
  138. if (isPlayer())
  139. {
  140. L2PcInstance player = getActingPlayer();
  141. if ((getInstanceId() > 0) && (oldI != null))
  142. {
  143. oldI.removePlayer(getObjectId());
  144. if (oldI.isShowTimer())
  145. {
  146. int startTime = (int) ((System.currentTimeMillis() - oldI.getInstanceStartTime()) / 1000);
  147. int endTime = (int) ((oldI.getInstanceEndTime() - oldI.getInstanceStartTime()) / 1000);
  148. if (oldI.isTimerIncrease())
  149. {
  150. sendPacket(new ExSendUIEvent(getActingPlayer(), true, true, startTime, endTime, oldI.getTimerText()));
  151. }
  152. else
  153. {
  154. sendPacket(new ExSendUIEvent(getActingPlayer(), true, false, endTime - startTime, 0, oldI.getTimerText()));
  155. }
  156. }
  157. }
  158. if (instanceId > 0)
  159. {
  160. newI.addPlayer(getObjectId());
  161. if (newI.isShowTimer())
  162. {
  163. int startTime = (int) ((System.currentTimeMillis() - newI.getInstanceStartTime()) / 1000);
  164. int endTime = (int) ((newI.getInstanceEndTime() - newI.getInstanceStartTime()) / 1000);
  165. if (newI.isTimerIncrease())
  166. {
  167. sendPacket(new ExSendUIEvent(getActingPlayer(), false, true, startTime, endTime, newI.getTimerText()));
  168. }
  169. else
  170. {
  171. sendPacket(new ExSendUIEvent(getActingPlayer(), false, false, endTime - startTime, 0, newI.getTimerText()));
  172. }
  173. }
  174. }
  175. if (player.hasSummon())
  176. {
  177. player.getSummon().setInstanceId(instanceId);
  178. }
  179. }
  180. else if (isNpc())
  181. {
  182. L2Npc npc = (L2Npc) this;
  183. if ((getInstanceId() > 0) && (oldI != null))
  184. {
  185. oldI.removeNpc(npc);
  186. }
  187. if (instanceId > 0)
  188. {
  189. newI.addNpc(npc);
  190. }
  191. }
  192. super.setInstanceId(instanceId);
  193. // If we change it for visible objects, me must clear & revalidates knownlists
  194. if (_isVisible && (_knownList != null))
  195. {
  196. if (isPlayer())
  197. {
  198. // We don't want some ugly looking disappear/appear effects, so don't update
  199. // the knownlist here, but players usually enter instancezones through teleporting
  200. // and the teleport will do the revalidation for us.
  201. }
  202. else
  203. {
  204. decayMe();
  205. spawnMe();
  206. }
  207. }
  208. }
  209. /**
  210. * Remove a L2Object from the world.<BR>
  211. * <BR>
  212. * <B><U> Actions</U> :</B><BR>
  213. * <BR>
  214. * <li>Remove the L2Object from the world</li><BR>
  215. * <BR>
  216. * <FONT COLOR=#FF0000><B> <U>Caution</U> : This method DOESN'T REMOVE the object from _allObjects of L2World </B></FONT><BR>
  217. * <FONT COLOR=#FF0000><B> <U>Caution</U> : This method DOESN'T SEND Server->Client packets to players</B></FONT><BR>
  218. * <BR>
  219. * <B><U> Assert </U> :</B><BR>
  220. * <BR>
  221. * <li>_worldRegion != null <I>(L2Object is visible at the beginning)</I></li><BR>
  222. * <BR>
  223. * <B><U> Example of use </U> :</B><BR>
  224. * <BR>
  225. * <li>Delete NPC/PC or Unsummon</li><BR>
  226. * <BR>
  227. */
  228. public void decayMe()
  229. {
  230. assert getWorldRegion() != null;
  231. L2WorldRegion reg = getWorldRegion();
  232. synchronized (this)
  233. {
  234. _isVisible = false;
  235. setWorldRegion(null);
  236. }
  237. // this can synchronize on others instances, so it's out of
  238. // synchronized, to avoid deadlocks
  239. // Remove the L2Object from the world
  240. L2World.getInstance().removeVisibleObject(this, reg);
  241. L2World.getInstance().removeObject(this);
  242. }
  243. public void refreshID()
  244. {
  245. L2World.getInstance().removeObject(this);
  246. IdFactory.getInstance().releaseId(getObjectId());
  247. _objectId = IdFactory.getInstance().getNextId();
  248. }
  249. /**
  250. * Init the position of a L2Object spawn and add it in the world as a visible object.<BR>
  251. * <BR>
  252. * <B><U> Actions</U> :</B><BR>
  253. * <BR>
  254. * <li>Set the x,y,z position of the L2Object spawn and update its _worldregion</li> <li>Add the L2Object spawn in the _allobjects of L2World</li> <li>Add the L2Object spawn to _visibleObjects of its L2WorldRegion</li> <li>Add the L2Object spawn in the world as a <B>visible</B> object</li><BR>
  255. * <BR>
  256. * <B><U> Assert </U> :</B><BR>
  257. * <BR>
  258. * <li>_worldRegion == null <I>(L2Object is invisible at the beginning)</I></li><BR>
  259. * <BR>
  260. * <B><U> Example of use </U> :</B><BR>
  261. * <BR>
  262. * <li>Create Door</li> <li>Spawn : Monster, Minion, CTs, Summon...</li><BR>
  263. */
  264. @Override
  265. public final boolean spawnMe()
  266. {
  267. assert (getWorldRegion() == null) && (getWorldPosition().getX() != 0) && (getWorldPosition().getY() != 0) && (getWorldPosition().getZ() != 0);
  268. synchronized (this)
  269. {
  270. // Set the x,y,z position of the L2Object spawn and update its _worldregion
  271. _isVisible = true;
  272. setWorldRegion(L2World.getInstance().getRegion(getWorldPosition()));
  273. // Add the L2Object spawn in the _allobjects of L2World
  274. L2World.getInstance().storeObject(this);
  275. // Add the L2Object spawn to _visibleObjects and if necessary to _allplayers of its L2WorldRegion
  276. getWorldRegion().addVisibleObject(this);
  277. }
  278. // this can synchronize on others instances, so it's out of synchronized, to avoid deadlocks
  279. // Add the L2Object spawn in the world as a visible object
  280. L2World.getInstance().addVisibleObject(this, getWorldRegion());
  281. onSpawn();
  282. return true;
  283. }
  284. public final void spawnMe(int x, int y, int z)
  285. {
  286. assert getWorldRegion() == null;
  287. synchronized (this)
  288. {
  289. // Set the x,y,z position of the L2Object spawn and update its _worldregion
  290. _isVisible = true;
  291. if (x > L2World.MAP_MAX_X)
  292. {
  293. x = L2World.MAP_MAX_X - 5000;
  294. }
  295. if (x < L2World.MAP_MIN_X)
  296. {
  297. x = L2World.MAP_MIN_X + 5000;
  298. }
  299. if (y > L2World.MAP_MAX_Y)
  300. {
  301. y = L2World.MAP_MAX_Y - 5000;
  302. }
  303. if (y < L2World.MAP_MIN_Y)
  304. {
  305. y = L2World.MAP_MIN_Y + 5000;
  306. }
  307. setXYZ(x, y, z);
  308. setWorldRegion(L2World.getInstance().getRegion(getWorldPosition()));
  309. // Add the L2Object spawn in the _allobjects of L2World
  310. }
  311. L2World.getInstance().storeObject(this);
  312. // these can synchronize on others instances, so they're out of
  313. // synchronized, to avoid deadlocks
  314. // Add the L2Object spawn to _visibleObjects and if necessary to _allplayers of its L2WorldRegion
  315. getWorldRegion().addVisibleObject(this);
  316. // Add the L2Object spawn in the world as a visible object
  317. L2World.getInstance().addVisibleObject(this, getWorldRegion());
  318. onSpawn();
  319. }
  320. public void toggleVisible()
  321. {
  322. if (isVisible())
  323. {
  324. decayMe();
  325. }
  326. else
  327. {
  328. spawnMe();
  329. }
  330. }
  331. public boolean isAttackable()
  332. {
  333. return false;
  334. }
  335. public abstract boolean isAutoAttackable(L2Character attacker);
  336. /**
  337. * Return the visibility state of the L2Object. <B><U> Concept</U> :</B><BR>
  338. * <BR>
  339. * A L2Object is visible if <B>__IsVisible</B>=true and <B>_worldregion</B>!=null <BR>
  340. * <BR>
  341. * @return
  342. */
  343. public final boolean isVisible()
  344. {
  345. return getWorldRegion() != null;
  346. }
  347. public final void setIsVisible(boolean value)
  348. {
  349. _isVisible = value;
  350. if (!_isVisible)
  351. {
  352. setWorldRegion(null);
  353. }
  354. }
  355. public ObjectKnownList getKnownList()
  356. {
  357. return _knownList;
  358. }
  359. /**
  360. * Initializes the KnownList of the L2Object, is overwritten in classes that require a different knownlist Type. Removes the need for instanceof checks.
  361. */
  362. public void initKnownList()
  363. {
  364. _knownList = new ObjectKnownList(this);
  365. }
  366. public final void setKnownList(ObjectKnownList value)
  367. {
  368. _knownList = value;
  369. }
  370. @Override
  371. public final String getName()
  372. {
  373. return _name;
  374. }
  375. public void setName(String value)
  376. {
  377. _name = value;
  378. }
  379. public final int getObjectId()
  380. {
  381. return _objectId;
  382. }
  383. public final ObjectPoly getPoly()
  384. {
  385. if (_poly == null)
  386. {
  387. _poly = new ObjectPoly(this);
  388. }
  389. return _poly;
  390. }
  391. public L2PcInstance getActingPlayer()
  392. {
  393. return null;
  394. }
  395. /**
  396. * Sends the Server->Client info packet for the object. <br>
  397. * Is Overridden in:
  398. * <ul>
  399. * <li>L2AirShipInstance</li>
  400. * <li>L2BoatInstance</li>
  401. * <li>L2DoorInstance</li>
  402. * <li>L2PcInstance</li>
  403. * <li>L2StaticObjectInstance</li>
  404. * <li>L2Decoy</li>
  405. * <li>L2Npc</li>
  406. * <li>L2Summon</li>
  407. * <li>L2Trap</li>
  408. * <li>L2ItemInstance</li>
  409. * </ul>
  410. * @param activeChar
  411. */
  412. public void sendInfo(L2PcInstance activeChar)
  413. {
  414. }
  415. /**
  416. * Not Implemented.<BR>
  417. * <BR>
  418. * <B><U> Overridden in </U> :</B><BR>
  419. * <BR>
  420. * <li>L2PcInstance</li><BR>
  421. * <BR>
  422. * @param mov
  423. */
  424. public void sendPacket(L2GameServerPacket mov)
  425. {
  426. // default implementation
  427. }
  428. /**
  429. * Not Implemented.<BR>
  430. * <BR>
  431. * <B><U> Overridden in </U> :</B><BR>
  432. * <BR>
  433. * <li>L2PcInstance</li><BR>
  434. * <BR>
  435. * @param id
  436. */
  437. public void sendPacket(SystemMessageId id)
  438. {
  439. // default implementation
  440. }
  441. /**
  442. * @return {@code true} if object is instance of L2PcInstance
  443. */
  444. public boolean isPlayer()
  445. {
  446. return false;
  447. }
  448. /**
  449. * @return {@code true} if object is instance of L2Playable
  450. */
  451. public boolean isPlayable()
  452. {
  453. return false;
  454. }
  455. /**
  456. * @return {@code true} if object is instance of L2Summon
  457. */
  458. public boolean isSummon()
  459. {
  460. return false;
  461. }
  462. /**
  463. * @return {@code true} if object is instance of L2PetInstance
  464. */
  465. public boolean isPet()
  466. {
  467. return false;
  468. }
  469. /**
  470. * @return {@code true} if object is instance of L2ServitorInstance
  471. */
  472. public boolean isServitor()
  473. {
  474. return false;
  475. }
  476. /**
  477. * @return {@code true} if object is instance of L2Attackable
  478. */
  479. public boolean isCharacter()
  480. {
  481. return false;
  482. }
  483. /**
  484. * @return {@code true} if object is instance of L2DoorInstance
  485. */
  486. public boolean isDoor()
  487. {
  488. return false;
  489. }
  490. /**
  491. * @return {@code true} if object is instance of L2Npc
  492. */
  493. public boolean isNpc()
  494. {
  495. return false;
  496. }
  497. /**
  498. * @return {@code true} if object is instance of L2Attackable
  499. */
  500. public boolean isL2Attackable()
  501. {
  502. return false;
  503. }
  504. /**
  505. * @return {@code true} if object is instance of L2MonsterInstance
  506. */
  507. public boolean isMonster()
  508. {
  509. return false;
  510. }
  511. /**
  512. * @return {@code true} if object is instance of L2TrapInstance
  513. */
  514. public boolean isTrap()
  515. {
  516. return false;
  517. }
  518. /**
  519. * @return {@code true} if object is instance of L2ItemInstance
  520. */
  521. public boolean isItem()
  522. {
  523. return false;
  524. }
  525. /**
  526. * @return {@code true} if object Npc Walker or Vehicle
  527. */
  528. public boolean isWalker()
  529. {
  530. return false;
  531. }
  532. /**
  533. * @return {@code true} if object Can be targeted
  534. */
  535. public boolean isTargetable()
  536. {
  537. return true;
  538. }
  539. /**
  540. * Check if the object is in the given zone Id.
  541. * @param zone the zone Id to check
  542. * @return {@code true} if the object is in that zone Id
  543. */
  544. public boolean isInsideZone(ZoneId zone)
  545. {
  546. return false;
  547. }
  548. /**
  549. * Check if current object has charged shot.
  550. * @param type of the shot to be checked.
  551. * @return {@code true} if the object has charged shot
  552. */
  553. public boolean isChargedShot(ShotType type)
  554. {
  555. return false;
  556. }
  557. /**
  558. * Charging shot into the current object.
  559. * @param type of the shot to be charged.
  560. * @param charged
  561. */
  562. public void setChargedShot(ShotType type, boolean charged)
  563. {
  564. }
  565. /**
  566. * Try to recharge a shot.
  567. * @param physical skill are using Soul shots.
  568. * @param magical skill are using Spirit shots.
  569. */
  570. public void rechargeShots(boolean physical, boolean magical)
  571. {
  572. }
  573. /**
  574. * @param <T>
  575. * @param script
  576. * @return
  577. */
  578. public final <T> T addScript(T script)
  579. {
  580. if (_scripts == null)
  581. {
  582. // Double-checked locking
  583. synchronized (this)
  584. {
  585. if (_scripts == null)
  586. {
  587. _scripts = new FastMap<String, Object>().shared();
  588. }
  589. }
  590. }
  591. _scripts.put(script.getClass().getName(), script);
  592. return script;
  593. }
  594. /**
  595. * @param <T>
  596. * @param script
  597. * @return
  598. */
  599. @SuppressWarnings("unchecked")
  600. public final <T> T removeScript(Class<T> script)
  601. {
  602. if (_scripts == null)
  603. {
  604. return null;
  605. }
  606. return (T) _scripts.remove(script.getName());
  607. }
  608. /**
  609. * @param <T>
  610. * @param script
  611. * @return
  612. */
  613. @SuppressWarnings("unchecked")
  614. public final <T> T getScript(Class<T> script)
  615. {
  616. if (_scripts == null)
  617. {
  618. return null;
  619. }
  620. return (T) _scripts.get(script.getName());
  621. }
  622. public void removeStatusListener(L2Character object)
  623. {
  624. }
  625. @Override
  626. public String toString()
  627. {
  628. return (getClass().getSimpleName() + ":" + getName() + "[" + getObjectId() + "]");
  629. }
  630. }