L2Object.java 17 KB

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