L2Object.java 14 KB

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