Instance.java 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835
  1. /*
  2. * Copyright (C) 2004-2014 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.entity;
  20. import java.io.File;
  21. import java.io.IOException;
  22. import java.util.ArrayList;
  23. import java.util.Collection;
  24. import java.util.HashMap;
  25. import java.util.List;
  26. import java.util.Map;
  27. import java.util.concurrent.ConcurrentHashMap;
  28. import java.util.concurrent.ScheduledFuture;
  29. import java.util.logging.Level;
  30. import java.util.logging.Logger;
  31. import javax.xml.parsers.DocumentBuilderFactory;
  32. import javolution.util.FastList;
  33. import javolution.util.FastMap;
  34. import org.w3c.dom.Document;
  35. import org.w3c.dom.NamedNodeMap;
  36. import org.w3c.dom.Node;
  37. import com.l2jserver.Config;
  38. import com.l2jserver.gameserver.Announcements;
  39. import com.l2jserver.gameserver.ThreadPoolManager;
  40. import com.l2jserver.gameserver.datatables.DoorTable;
  41. import com.l2jserver.gameserver.datatables.NpcData;
  42. import com.l2jserver.gameserver.idfactory.IdFactory;
  43. import com.l2jserver.gameserver.instancemanager.InstanceManager;
  44. import com.l2jserver.gameserver.model.L2Spawn;
  45. import com.l2jserver.gameserver.model.L2World;
  46. import com.l2jserver.gameserver.model.L2WorldRegion;
  47. import com.l2jserver.gameserver.model.Location;
  48. import com.l2jserver.gameserver.model.StatsSet;
  49. import com.l2jserver.gameserver.model.TeleportWhereType;
  50. import com.l2jserver.gameserver.model.actor.L2Attackable;
  51. import com.l2jserver.gameserver.model.actor.L2Character;
  52. import com.l2jserver.gameserver.model.actor.L2Npc;
  53. import com.l2jserver.gameserver.model.actor.instance.L2DoorInstance;
  54. import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
  55. import com.l2jserver.gameserver.model.actor.templates.L2DoorTemplate;
  56. import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
  57. import com.l2jserver.gameserver.model.instancezone.InstanceWorld;
  58. import com.l2jserver.gameserver.network.SystemMessageId;
  59. import com.l2jserver.gameserver.network.clientpackets.Say2;
  60. import com.l2jserver.gameserver.network.serverpackets.CreatureSay;
  61. import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
  62. /**
  63. * Main class for game instances.
  64. * @author evill33t, GodKratos
  65. */
  66. public final class Instance
  67. {
  68. private static final Logger _log = Logger.getLogger(Instance.class.getName());
  69. private final int _id;
  70. private String _name;
  71. private int _ejectTime = Config.EJECT_DEAD_PLAYER_TIME;
  72. /** Allow random walk for NPCs, global parameter. */
  73. private boolean _allowRandomWalk = true;
  74. private final List<Integer> _players = new FastList<Integer>().shared();
  75. private final List<L2Npc> _npcs = new FastList<L2Npc>().shared();
  76. private final Map<Integer, L2DoorInstance> _doors = new ConcurrentHashMap<>();
  77. private final Map<String, List<L2Spawn>> _manualSpawn = new HashMap<>();
  78. private Location _spawnLoc = null;
  79. private boolean _allowSummon = true;
  80. private long _emptyDestroyTime = -1;
  81. private long _lastLeft = -1;
  82. private long _instanceStartTime = -1;
  83. private long _instanceEndTime = -1;
  84. private boolean _isPvPInstance = false;
  85. private boolean _showTimer = false;
  86. private boolean _isTimerIncrease = true;
  87. private String _timerText = "";
  88. protected ScheduledFuture<?> _checkTimeUpTask = null;
  89. protected final Map<Integer, ScheduledFuture<?>> _ejectDeadTasks = new FastMap<>();
  90. public Instance(int id)
  91. {
  92. _id = id;
  93. _instanceStartTime = System.currentTimeMillis();
  94. }
  95. public Instance(int id, String name)
  96. {
  97. _id = id;
  98. _name = name;
  99. _instanceStartTime = System.currentTimeMillis();
  100. }
  101. /**
  102. * @return the ID of this instance.
  103. */
  104. public int getId()
  105. {
  106. return _id;
  107. }
  108. /**
  109. * @return the name of this instance
  110. */
  111. public String getName()
  112. {
  113. return _name;
  114. }
  115. public void setName(String name)
  116. {
  117. _name = name;
  118. }
  119. /**
  120. * @return the eject time
  121. */
  122. public int getEjectTime()
  123. {
  124. return _ejectTime;
  125. }
  126. /**
  127. * @param ejectTime the player eject time upon death
  128. */
  129. public void setEjectTime(int ejectTime)
  130. {
  131. _ejectTime = ejectTime;
  132. }
  133. /**
  134. * @return whether summon friend type skills are allowed for this instance
  135. */
  136. public boolean isSummonAllowed()
  137. {
  138. return _allowSummon;
  139. }
  140. /**
  141. * Sets the status for the instance for summon friend type skills
  142. * @param b
  143. */
  144. public void setAllowSummon(boolean b)
  145. {
  146. _allowSummon = b;
  147. }
  148. /**
  149. * Returns true if entire instance is PvP zone
  150. * @return
  151. */
  152. public boolean isPvPInstance()
  153. {
  154. return _isPvPInstance;
  155. }
  156. /**
  157. * Sets PvP zone status of the instance
  158. * @param b
  159. */
  160. public void setPvPInstance(boolean b)
  161. {
  162. _isPvPInstance = b;
  163. }
  164. /**
  165. * Set the instance duration task
  166. * @param duration in milliseconds
  167. */
  168. public void setDuration(int duration)
  169. {
  170. if (_checkTimeUpTask != null)
  171. {
  172. _checkTimeUpTask.cancel(true);
  173. }
  174. _checkTimeUpTask = ThreadPoolManager.getInstance().scheduleGeneral(new CheckTimeUp(duration), 500);
  175. _instanceEndTime = System.currentTimeMillis() + duration + 500;
  176. }
  177. /**
  178. * Set time before empty instance will be removed
  179. * @param time in milliseconds
  180. */
  181. public void setEmptyDestroyTime(long time)
  182. {
  183. _emptyDestroyTime = time;
  184. }
  185. /**
  186. * Checks if the player exists within this instance
  187. * @param objectId
  188. * @return true if player exists in instance
  189. */
  190. public boolean containsPlayer(int objectId)
  191. {
  192. return _players.contains(objectId);
  193. }
  194. /**
  195. * Adds the specified player to the instance
  196. * @param objectId Players object ID
  197. */
  198. public void addPlayer(int objectId)
  199. {
  200. _players.add(objectId);
  201. }
  202. /**
  203. * Removes the specified player from the instance list.
  204. * @param objectId the player's object Id
  205. */
  206. public void removePlayer(Integer objectId)
  207. {
  208. _players.remove(objectId);
  209. if (_players.isEmpty() && (_emptyDestroyTime >= 0))
  210. {
  211. _lastLeft = System.currentTimeMillis();
  212. setDuration((int) (_instanceEndTime - System.currentTimeMillis() - 500));
  213. }
  214. }
  215. public void addNpc(L2Npc npc)
  216. {
  217. _npcs.add(npc);
  218. }
  219. public void removeNpc(L2Npc npc)
  220. {
  221. if (npc.getSpawn() != null)
  222. {
  223. npc.getSpawn().stopRespawn();
  224. }
  225. _npcs.remove(npc);
  226. }
  227. /**
  228. * Adds a door into the instance
  229. * @param doorId - from doors.xml
  230. * @param set - StatsSet for initializing door
  231. */
  232. public void addDoor(int doorId, StatsSet set)
  233. {
  234. if (_doors.containsKey(doorId))
  235. {
  236. _log.warning("Door ID " + doorId + " already exists in instance " + getId());
  237. return;
  238. }
  239. final L2DoorInstance newdoor = new L2DoorInstance(IdFactory.getInstance().getNextId(), new L2DoorTemplate(set));
  240. newdoor.setInstanceId(getId());
  241. newdoor.setCurrentHp(newdoor.getMaxHp());
  242. newdoor.spawnMe(newdoor.getTemplate().getX(), newdoor.getTemplate().getY(), newdoor.getTemplate().getZ());
  243. _doors.put(doorId, newdoor);
  244. }
  245. public List<Integer> getPlayers()
  246. {
  247. return _players;
  248. }
  249. public List<L2Npc> getNpcs()
  250. {
  251. return _npcs;
  252. }
  253. public Collection<L2DoorInstance> getDoors()
  254. {
  255. return _doors.values();
  256. }
  257. public L2DoorInstance getDoor(int id)
  258. {
  259. return _doors.get(id);
  260. }
  261. public long getInstanceEndTime()
  262. {
  263. return _instanceEndTime;
  264. }
  265. public long getInstanceStartTime()
  266. {
  267. return _instanceStartTime;
  268. }
  269. public boolean isShowTimer()
  270. {
  271. return _showTimer;
  272. }
  273. public boolean isTimerIncrease()
  274. {
  275. return _isTimerIncrease;
  276. }
  277. public String getTimerText()
  278. {
  279. return _timerText;
  280. }
  281. /**
  282. * @return the spawn location for this instance to be used when leaving the instance
  283. */
  284. public Location getSpawnLoc()
  285. {
  286. return _spawnLoc;
  287. }
  288. /**
  289. * Sets the spawn location for this instance to be used when leaving the instance
  290. * @param loc
  291. */
  292. public void setSpawnLoc(Location loc)
  293. {
  294. _spawnLoc = loc;
  295. }
  296. public void removePlayers()
  297. {
  298. for (Integer objectId : _players)
  299. {
  300. final L2PcInstance player = L2World.getInstance().getPlayer(objectId);
  301. if ((player != null) && (player.getInstanceId() == getId()))
  302. {
  303. player.setInstanceId(0);
  304. if (getSpawnLoc() != null)
  305. {
  306. player.teleToLocation(getSpawnLoc(), true);
  307. }
  308. else
  309. {
  310. player.teleToLocation(TeleportWhereType.TOWN);
  311. }
  312. }
  313. }
  314. _players.clear();
  315. }
  316. public void removeNpcs()
  317. {
  318. for (L2Npc mob : _npcs)
  319. {
  320. if (mob != null)
  321. {
  322. if (mob.getSpawn() != null)
  323. {
  324. mob.getSpawn().stopRespawn();
  325. }
  326. mob.deleteMe();
  327. }
  328. }
  329. _npcs.clear();
  330. _manualSpawn.clear();
  331. }
  332. public void removeDoors()
  333. {
  334. for (L2DoorInstance door : _doors.values())
  335. {
  336. if (door != null)
  337. {
  338. L2WorldRegion region = door.getWorldRegion();
  339. door.decayMe();
  340. if (region != null)
  341. {
  342. region.removeVisibleObject(door);
  343. }
  344. door.getKnownList().removeAllKnownObjects();
  345. L2World.getInstance().removeObject(door);
  346. }
  347. }
  348. _doors.clear();
  349. }
  350. /**
  351. * Spawns group of instance NPC's
  352. * @param groupName - name of group from XML definition to spawn
  353. * @return list of spawned NPC's
  354. */
  355. public List<L2Npc> spawnGroup(String groupName)
  356. {
  357. List<L2Npc> ret = null;
  358. if (_manualSpawn.containsKey(groupName))
  359. {
  360. final List<L2Spawn> manualSpawn = _manualSpawn.get(groupName);
  361. ret = new ArrayList<>(manualSpawn.size());
  362. for (L2Spawn spawnDat : manualSpawn)
  363. {
  364. ret.add(spawnDat.doSpawn());
  365. }
  366. }
  367. else
  368. {
  369. _log.warning(getName() + " instance: cannot spawn NPC's, wrong group name: " + groupName);
  370. }
  371. return ret;
  372. }
  373. public void loadInstanceTemplate(String filename)
  374. {
  375. Document doc = null;
  376. File xml = new File(Config.DATAPACK_ROOT, "data/instances/" + filename);
  377. try
  378. {
  379. DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
  380. factory.setValidating(false);
  381. factory.setIgnoringComments(true);
  382. doc = factory.newDocumentBuilder().parse(xml);
  383. for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
  384. {
  385. if ("instance".equalsIgnoreCase(n.getNodeName()))
  386. {
  387. parseInstance(n);
  388. }
  389. }
  390. }
  391. catch (IOException e)
  392. {
  393. _log.log(Level.WARNING, "Instance: can not find " + xml.getAbsolutePath() + " ! " + e.getMessage(), e);
  394. }
  395. catch (Exception e)
  396. {
  397. _log.log(Level.WARNING, "Instance: error while loading " + xml.getAbsolutePath() + " ! " + e.getMessage(), e);
  398. }
  399. }
  400. private void parseInstance(Node n) throws Exception
  401. {
  402. L2Spawn spawnDat;
  403. L2NpcTemplate npcTemplate;
  404. _name = n.getAttributes().getNamedItem("name").getNodeValue();
  405. Node a = n.getAttributes().getNamedItem("ejectTime");
  406. if (a != null)
  407. {
  408. _ejectTime = 1000 * Integer.parseInt(a.getNodeValue());
  409. }
  410. a = n.getAttributes().getNamedItem("allowRandomWalk");
  411. if (a != null)
  412. {
  413. _allowRandomWalk = Boolean.parseBoolean(a.getNodeValue());
  414. }
  415. Node first = n.getFirstChild();
  416. for (n = first; n != null; n = n.getNextSibling())
  417. {
  418. if ("activityTime".equalsIgnoreCase(n.getNodeName()))
  419. {
  420. a = n.getAttributes().getNamedItem("val");
  421. if (a != null)
  422. {
  423. _checkTimeUpTask = ThreadPoolManager.getInstance().scheduleGeneral(new CheckTimeUp(Integer.parseInt(a.getNodeValue()) * 60000), 15000);
  424. _instanceEndTime = System.currentTimeMillis() + (Long.parseLong(a.getNodeValue()) * 60000) + 15000;
  425. }
  426. }
  427. // @formatter:off
  428. /*
  429. else if ("timeDelay".equalsIgnoreCase(n.getNodeName()))
  430. {
  431. a = n.getAttributes().getNamedItem("val");
  432. if (a != null)
  433. {
  434. instance.setTimeDelay(Integer.parseInt(a.getNodeValue()));
  435. }
  436. }
  437. */
  438. // @formatter:on
  439. else if ("allowSummon".equalsIgnoreCase(n.getNodeName()))
  440. {
  441. a = n.getAttributes().getNamedItem("val");
  442. if (a != null)
  443. {
  444. setAllowSummon(Boolean.parseBoolean(a.getNodeValue()));
  445. }
  446. }
  447. else if ("emptyDestroyTime".equalsIgnoreCase(n.getNodeName()))
  448. {
  449. a = n.getAttributes().getNamedItem("val");
  450. if (a != null)
  451. {
  452. _emptyDestroyTime = Long.parseLong(a.getNodeValue()) * 1000;
  453. }
  454. }
  455. else if ("showTimer".equalsIgnoreCase(n.getNodeName()))
  456. {
  457. a = n.getAttributes().getNamedItem("val");
  458. if (a != null)
  459. {
  460. _showTimer = Boolean.parseBoolean(a.getNodeValue());
  461. }
  462. a = n.getAttributes().getNamedItem("increase");
  463. if (a != null)
  464. {
  465. _isTimerIncrease = Boolean.parseBoolean(a.getNodeValue());
  466. }
  467. a = n.getAttributes().getNamedItem("text");
  468. if (a != null)
  469. {
  470. _timerText = a.getNodeValue();
  471. }
  472. }
  473. else if ("PvPInstance".equalsIgnoreCase(n.getNodeName()))
  474. {
  475. a = n.getAttributes().getNamedItem("val");
  476. if (a != null)
  477. {
  478. setPvPInstance(Boolean.parseBoolean(a.getNodeValue()));
  479. }
  480. }
  481. else if ("doorlist".equalsIgnoreCase(n.getNodeName()))
  482. {
  483. for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
  484. {
  485. int doorId = 0;
  486. if ("door".equalsIgnoreCase(d.getNodeName()))
  487. {
  488. doorId = Integer.parseInt(d.getAttributes().getNamedItem("doorId").getNodeValue());
  489. StatsSet set = new StatsSet();
  490. set.add(DoorTable.getInstance().getDoorTemplate(doorId));
  491. for (Node bean = d.getFirstChild(); bean != null; bean = bean.getNextSibling())
  492. {
  493. if ("set".equalsIgnoreCase(bean.getNodeName()))
  494. {
  495. NamedNodeMap attrs = bean.getAttributes();
  496. String setname = attrs.getNamedItem("name").getNodeValue();
  497. String value = attrs.getNamedItem("val").getNodeValue();
  498. set.set(setname, value);
  499. }
  500. }
  501. addDoor(doorId, set);
  502. }
  503. }
  504. }
  505. else if ("spawnlist".equalsIgnoreCase(n.getNodeName()))
  506. {
  507. for (Node group = n.getFirstChild(); group != null; group = group.getNextSibling())
  508. {
  509. if ("group".equalsIgnoreCase(group.getNodeName()))
  510. {
  511. String spawnGroup = group.getAttributes().getNamedItem("name").getNodeValue();
  512. List<L2Spawn> manualSpawn = new ArrayList<>();
  513. for (Node d = group.getFirstChild(); d != null; d = d.getNextSibling())
  514. {
  515. int npcId = 0, x = 0, y = 0, z = 0, heading = 0, respawn = 0, respawnRandom = 0, delay = -1;
  516. Boolean allowRandomWalk = null;
  517. if ("spawn".equalsIgnoreCase(d.getNodeName()))
  518. {
  519. npcId = Integer.parseInt(d.getAttributes().getNamedItem("npcId").getNodeValue());
  520. x = Integer.parseInt(d.getAttributes().getNamedItem("x").getNodeValue());
  521. y = Integer.parseInt(d.getAttributes().getNamedItem("y").getNodeValue());
  522. z = Integer.parseInt(d.getAttributes().getNamedItem("z").getNodeValue());
  523. heading = Integer.parseInt(d.getAttributes().getNamedItem("heading").getNodeValue());
  524. respawn = Integer.parseInt(d.getAttributes().getNamedItem("respawn").getNodeValue());
  525. if (d.getAttributes().getNamedItem("onKillDelay") != null)
  526. {
  527. delay = Integer.parseInt(d.getAttributes().getNamedItem("onKillDelay").getNodeValue());
  528. }
  529. if (d.getAttributes().getNamedItem("respawnRandom") != null)
  530. {
  531. respawnRandom = Integer.parseInt(d.getAttributes().getNamedItem("respawnRandom").getNodeValue());
  532. }
  533. if (d.getAttributes().getNamedItem("allowRandomWalk") != null)
  534. {
  535. allowRandomWalk = Boolean.valueOf(d.getAttributes().getNamedItem("allowRandomWalk").getNodeValue());
  536. }
  537. npcTemplate = NpcData.getInstance().getTemplate(npcId);
  538. if (npcTemplate != null)
  539. {
  540. spawnDat = new L2Spawn(npcTemplate);
  541. spawnDat.setX(x);
  542. spawnDat.setY(y);
  543. spawnDat.setZ(z);
  544. spawnDat.setAmount(1);
  545. spawnDat.setHeading(heading);
  546. spawnDat.setRespawnDelay(respawn, respawnRandom);
  547. if (respawn == 0)
  548. {
  549. spawnDat.stopRespawn();
  550. }
  551. else
  552. {
  553. spawnDat.startRespawn();
  554. }
  555. spawnDat.setInstanceId(getId());
  556. if (allowRandomWalk == null)
  557. {
  558. spawnDat.setIsNoRndWalk(!_allowRandomWalk);
  559. }
  560. else
  561. {
  562. spawnDat.setIsNoRndWalk(!allowRandomWalk);
  563. }
  564. if (spawnGroup.equals("general"))
  565. {
  566. L2Npc spawned = spawnDat.doSpawn();
  567. if ((delay >= 0) && (spawned instanceof L2Attackable))
  568. {
  569. ((L2Attackable) spawned).setOnKillDelay(delay);
  570. }
  571. }
  572. else
  573. {
  574. manualSpawn.add(spawnDat);
  575. }
  576. }
  577. else
  578. {
  579. _log.warning("Instance: Data missing in NPC table for ID: " + npcId + " in Instance " + getId());
  580. }
  581. }
  582. }
  583. if (!manualSpawn.isEmpty())
  584. {
  585. _manualSpawn.put(spawnGroup, manualSpawn);
  586. }
  587. }
  588. }
  589. }
  590. else if ("spawnpoint".equalsIgnoreCase(n.getNodeName()))
  591. {
  592. try
  593. {
  594. int x = Integer.parseInt(n.getAttributes().getNamedItem("spawnX").getNodeValue());
  595. int y = Integer.parseInt(n.getAttributes().getNamedItem("spawnY").getNodeValue());
  596. int z = Integer.parseInt(n.getAttributes().getNamedItem("spawnZ").getNodeValue());
  597. _spawnLoc = new Location(x, y, z);
  598. }
  599. catch (Exception e)
  600. {
  601. _log.log(Level.WARNING, "Error parsing instance xml: " + e.getMessage(), e);
  602. _spawnLoc = null;
  603. }
  604. }
  605. }
  606. }
  607. protected void doCheckTimeUp(int remaining)
  608. {
  609. CreatureSay cs = null;
  610. int timeLeft;
  611. int interval;
  612. if (_players.isEmpty() && (_emptyDestroyTime == 0))
  613. {
  614. remaining = 0;
  615. interval = 500;
  616. }
  617. else if (_players.isEmpty() && (_emptyDestroyTime > 0))
  618. {
  619. Long emptyTimeLeft = (_lastLeft + _emptyDestroyTime) - System.currentTimeMillis();
  620. if (emptyTimeLeft <= 0)
  621. {
  622. interval = 0;
  623. remaining = 0;
  624. }
  625. else if ((remaining > 300000) && (emptyTimeLeft > 300000))
  626. {
  627. interval = 300000;
  628. remaining = remaining - 300000;
  629. }
  630. else if ((remaining > 60000) && (emptyTimeLeft > 60000))
  631. {
  632. interval = 60000;
  633. remaining = remaining - 60000;
  634. }
  635. else if ((remaining > 30000) && (emptyTimeLeft > 30000))
  636. {
  637. interval = 30000;
  638. remaining = remaining - 30000;
  639. }
  640. else
  641. {
  642. interval = 10000;
  643. remaining = remaining - 10000;
  644. }
  645. }
  646. else if (remaining > 300000)
  647. {
  648. timeLeft = remaining / 60000;
  649. interval = 300000;
  650. SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.DUNGEON_EXPIRES_IN_S1_MINUTES);
  651. sm.addString(Integer.toString(timeLeft));
  652. Announcements.getInstance().announceToInstance(sm, getId());
  653. remaining = remaining - 300000;
  654. }
  655. else if (remaining > 60000)
  656. {
  657. timeLeft = remaining / 60000;
  658. interval = 60000;
  659. SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.DUNGEON_EXPIRES_IN_S1_MINUTES);
  660. sm.addString(Integer.toString(timeLeft));
  661. Announcements.getInstance().announceToInstance(sm, getId());
  662. remaining = remaining - 60000;
  663. }
  664. else if (remaining > 30000)
  665. {
  666. timeLeft = remaining / 1000;
  667. interval = 30000;
  668. cs = new CreatureSay(0, Say2.ALLIANCE, "Notice", timeLeft + " seconds left.");
  669. remaining = remaining - 30000;
  670. }
  671. else
  672. {
  673. timeLeft = remaining / 1000;
  674. interval = 10000;
  675. cs = new CreatureSay(0, Say2.ALLIANCE, "Notice", timeLeft + " seconds left.");
  676. remaining = remaining - 10000;
  677. }
  678. if (cs != null)
  679. {
  680. for (Integer objectId : _players)
  681. {
  682. final L2PcInstance player = L2World.getInstance().getPlayer(objectId);
  683. if ((player != null) && (player.getInstanceId() == getId()))
  684. {
  685. player.sendPacket(cs);
  686. }
  687. }
  688. }
  689. cancelTimer();
  690. if (remaining >= 10000)
  691. {
  692. _checkTimeUpTask = ThreadPoolManager.getInstance().scheduleGeneral(new CheckTimeUp(remaining), interval);
  693. }
  694. else
  695. {
  696. _checkTimeUpTask = ThreadPoolManager.getInstance().scheduleGeneral(new TimeUp(), interval);
  697. }
  698. }
  699. public void cancelTimer()
  700. {
  701. if (_checkTimeUpTask != null)
  702. {
  703. _checkTimeUpTask.cancel(true);
  704. }
  705. }
  706. public void cancelEjectDeadPlayer(L2PcInstance player)
  707. {
  708. if (_ejectDeadTasks.containsKey(player.getObjectId()))
  709. {
  710. final ScheduledFuture<?> task = _ejectDeadTasks.remove(player.getObjectId());
  711. if (task != null)
  712. {
  713. task.cancel(true);
  714. }
  715. }
  716. }
  717. public void addEjectDeadTask(L2PcInstance player)
  718. {
  719. if ((player != null))
  720. {
  721. _ejectDeadTasks.put(player.getObjectId(), ThreadPoolManager.getInstance().scheduleGeneral(() ->
  722. {
  723. if (player.isDead() && (player.getInstanceId() == getId()))
  724. {
  725. player.setInstanceId(0);
  726. if (getSpawnLoc() != null)
  727. {
  728. player.teleToLocation(getSpawnLoc(), true);
  729. }
  730. else
  731. {
  732. player.teleToLocation(TeleportWhereType.TOWN);
  733. }
  734. }
  735. }, _ejectTime));
  736. }
  737. }
  738. /**
  739. * @param killer the character that killed the {@code victim}
  740. * @param victim the character that was killed by the {@code killer}
  741. */
  742. public final void notifyDeath(L2Character killer, L2Character victim)
  743. {
  744. final InstanceWorld instance = InstanceManager.getInstance().getPlayerWorld(victim.getActingPlayer());
  745. if (instance != null)
  746. {
  747. instance.onDeath(killer, victim);
  748. }
  749. }
  750. public class CheckTimeUp implements Runnable
  751. {
  752. private final int _remaining;
  753. public CheckTimeUp(int remaining)
  754. {
  755. _remaining = remaining;
  756. }
  757. @Override
  758. public void run()
  759. {
  760. doCheckTimeUp(_remaining);
  761. }
  762. }
  763. public class TimeUp implements Runnable
  764. {
  765. @Override
  766. public void run()
  767. {
  768. InstanceManager.getInstance().destroyInstance(getId());
  769. }
  770. }
  771. }