OlympiadGameTask.java 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  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.olympiad;
  16. import java.util.logging.Level;
  17. import java.util.logging.Logger;
  18. import com.l2jserver.Config;
  19. import com.l2jserver.gameserver.ThreadPoolManager;
  20. import com.l2jserver.gameserver.model.zone.type.L2OlympiadStadiumZone;
  21. import com.l2jserver.gameserver.network.SystemMessageId;
  22. import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
  23. /**
  24. * @author DS
  25. */
  26. public final class OlympiadGameTask implements Runnable
  27. {
  28. protected static final Logger _log = Logger.getLogger(OlympiadGameTask.class.getName());
  29. protected static final long BATTLE_PERIOD = Config.ALT_OLY_BATTLE; // 6 mins
  30. public static final int[] TELEPORT_TO_ARENA = { 120, 60, 30, 15, 10, 5, 4, 3, 2, 1, 0 };
  31. public static final int[] BATTLE_START_TIME_FIRST = { 60, 50, 40, 30, 20, 10, 0 };
  32. public static final int[] BATTLE_START_TIME_SECOND = { 10, 5, 4, 3, 2, 1, 0 };
  33. public static final int[] TELEPORT_TO_TOWN = { 40, 30, 20, 10, 5, 4, 3, 2, 1, 0 };
  34. private final L2OlympiadStadiumZone _zone;
  35. private AbstractOlympiadGame _game;
  36. private GameState _state = GameState.IDLE;
  37. private boolean _needAnnounce = false;
  38. private int _countDown = 0;
  39. private static enum GameState
  40. {
  41. BEGIN,
  42. TELEPORT_TO_ARENA,
  43. GAME_STARTED,
  44. BATTLE_COUNTDOWN_FIRST,
  45. BATTLE_COUNTDOWN_SECOND,
  46. BATTLE_STARTED,
  47. BATTLE_IN_PROGRESS,
  48. GAME_STOPPED,
  49. TELEPORT_TO_TOWN,
  50. CLEANUP,
  51. IDLE
  52. }
  53. public OlympiadGameTask(L2OlympiadStadiumZone zone)
  54. {
  55. _zone = zone;
  56. zone.registerTask(this);
  57. }
  58. public final boolean isRunning()
  59. {
  60. return _state != GameState.IDLE;
  61. }
  62. public final boolean isGameStarted()
  63. {
  64. return _state.ordinal() >= GameState.GAME_STARTED.ordinal() && _state.ordinal() <= GameState.CLEANUP.ordinal();
  65. }
  66. public final boolean isBattleStarted()
  67. {
  68. return _state == GameState.BATTLE_IN_PROGRESS;
  69. }
  70. public final boolean isBattleFinished()
  71. {
  72. return _state == GameState.TELEPORT_TO_TOWN;
  73. }
  74. public final boolean needAnnounce()
  75. {
  76. if (_needAnnounce)
  77. {
  78. _needAnnounce = false;
  79. return true;
  80. }
  81. return false;
  82. }
  83. public final L2OlympiadStadiumZone getZone()
  84. {
  85. return _zone;
  86. }
  87. public final AbstractOlympiadGame getGame()
  88. {
  89. return _game;
  90. }
  91. public final void attachGame(AbstractOlympiadGame game)
  92. {
  93. if (game!= null && _state != GameState.IDLE)
  94. {
  95. _log.log(Level.WARNING, "Attempt to overwrite non-finished game in state " + _state);
  96. return;
  97. }
  98. _game = game;
  99. _state = GameState.BEGIN;
  100. _needAnnounce = false;
  101. ThreadPoolManager.getInstance().executeTask(this);
  102. }
  103. public final void run()
  104. {
  105. try
  106. {
  107. int delay = 1; // schedule next call after 1s
  108. switch (_state)
  109. {
  110. // Game created
  111. case BEGIN:
  112. {
  113. _state = GameState.TELEPORT_TO_ARENA;
  114. _countDown = Config.ALT_OLY_WAIT_TIME;
  115. break;
  116. }
  117. // Teleport to arena countdown
  118. case TELEPORT_TO_ARENA:
  119. {
  120. if (_countDown > 0)
  121. {
  122. SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_WILL_ENTER_THE_OLYMPIAD_STADIUM_IN_S1_SECOND_S);
  123. sm.addNumber(_countDown);
  124. _game.broadcastPacket(sm);
  125. }
  126. delay = getDelay(TELEPORT_TO_ARENA);
  127. if (_countDown <= 0)
  128. _state = GameState.GAME_STARTED;
  129. break;
  130. }
  131. // Game start, port players to arena
  132. case GAME_STARTED:
  133. {
  134. if (!startGame())
  135. {
  136. _state = GameState.GAME_STOPPED;
  137. break;
  138. }
  139. _state = GameState.BATTLE_COUNTDOWN_FIRST;
  140. _countDown = BATTLE_START_TIME_FIRST[0];
  141. delay = 5;
  142. break;
  143. }
  144. // Battle start countdown, first part (60-10)
  145. case BATTLE_COUNTDOWN_FIRST:
  146. {
  147. if (_countDown > 0)
  148. {
  149. SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.THE_GAME_WILL_START_IN_S1_SECOND_S);
  150. sm.addNumber(_countDown);
  151. _zone.broadcastPacket(sm);
  152. }
  153. delay = getDelay(BATTLE_START_TIME_FIRST);
  154. if (_countDown <= 0)
  155. {
  156. openDoors();
  157. _state = GameState.BATTLE_COUNTDOWN_SECOND;
  158. _countDown = BATTLE_START_TIME_SECOND[0];
  159. delay = getDelay(BATTLE_START_TIME_SECOND);
  160. }
  161. break;
  162. }
  163. // Battle start countdown, second part (10-0)
  164. case BATTLE_COUNTDOWN_SECOND:
  165. {
  166. if (_countDown > 0)
  167. {
  168. SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.THE_GAME_WILL_START_IN_S1_SECOND_S);
  169. sm.addNumber(_countDown);
  170. _zone.broadcastPacket(sm);
  171. }
  172. delay = getDelay(BATTLE_START_TIME_SECOND);
  173. if (_countDown <= 0)
  174. _state = GameState.BATTLE_STARTED;
  175. break;
  176. }
  177. // Beginning of the battle
  178. case BATTLE_STARTED:
  179. {
  180. _countDown = 0;
  181. _state = GameState.BATTLE_IN_PROGRESS; // set state first, used in zone update
  182. if (!startBattle())
  183. _state = GameState.GAME_STOPPED;
  184. break;
  185. }
  186. // Checks during battle
  187. case BATTLE_IN_PROGRESS:
  188. {
  189. _countDown += 1000;
  190. if (checkBattle() || _countDown > Config.ALT_OLY_BATTLE)
  191. _state = GameState.GAME_STOPPED;
  192. break;
  193. }
  194. // End of the battle
  195. case GAME_STOPPED:
  196. {
  197. _state = GameState.TELEPORT_TO_TOWN;
  198. _countDown = TELEPORT_TO_TOWN[0];
  199. stopGame();
  200. delay = getDelay(TELEPORT_TO_TOWN);
  201. break;
  202. }
  203. // Teleport to town countdown
  204. case TELEPORT_TO_TOWN:
  205. {
  206. if (_countDown > 0)
  207. {
  208. SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_WILL_BE_MOVED_TO_TOWN_IN_S1_SECONDS);
  209. sm.addNumber(_countDown);
  210. _game.broadcastPacket(sm);
  211. }
  212. delay = getDelay(TELEPORT_TO_TOWN);
  213. if (_countDown <= 0)
  214. _state = GameState.CLEANUP;
  215. break;
  216. }
  217. // Removals
  218. case CLEANUP:
  219. {
  220. cleanupGame();
  221. _state = GameState.IDLE;
  222. _game = null;
  223. return;
  224. }
  225. }
  226. ThreadPoolManager.getInstance().scheduleGeneral(this, delay * 1000);
  227. }
  228. catch (Exception e)
  229. {
  230. switch (_state)
  231. {
  232. case GAME_STOPPED:
  233. case TELEPORT_TO_TOWN:
  234. case CLEANUP:
  235. case IDLE:
  236. {
  237. _log.log(Level.WARNING, "Unable to return players back in town, exception: " + e.getMessage());
  238. _state = GameState.IDLE;
  239. _game = null;
  240. return;
  241. }
  242. }
  243. _log.log(Level.WARNING, "Exception in " + _state + ", trying to port players back: " + e.getMessage(), e);
  244. _state = GameState.GAME_STOPPED;
  245. ThreadPoolManager.getInstance().scheduleGeneral(this, 1000);
  246. }
  247. }
  248. private final int getDelay(int[] times)
  249. {
  250. int time;
  251. for (int i = 0; i < times.length - 1; i++)
  252. {
  253. time = times[i];
  254. if (time >= _countDown)
  255. continue;
  256. final int delay = _countDown - time;
  257. _countDown = time;
  258. return delay;
  259. }
  260. // should not happens
  261. _countDown = -1;
  262. return 1;
  263. }
  264. /**
  265. * Second stage: check for defaulted, port players to arena, announce game.
  266. * Returns true if no participants defaulted.
  267. */
  268. private final boolean startGame()
  269. {
  270. try
  271. {
  272. // Checking for opponents and teleporting to arena
  273. if (_game.checkDefaulted())
  274. return false;
  275. _zone.closeDoors();
  276. if (_game.needBuffers())
  277. _zone.spawnBuffers();
  278. if (!_game.portPlayersToArena(_zone.getSpawns()))
  279. return false;
  280. _game.removals();
  281. _needAnnounce = true;
  282. OlympiadGameManager.getInstance().startBattle(); // inform manager
  283. return true;
  284. }
  285. catch (Exception e)
  286. {
  287. _log.log(Level.WARNING, e.getMessage(), e);
  288. }
  289. return false;
  290. }
  291. /**
  292. * Third stage: open doors.
  293. */
  294. private final void openDoors()
  295. {
  296. try
  297. {
  298. _game.resetDamage();
  299. _zone.openDoors();
  300. }
  301. catch (Exception e)
  302. {
  303. _log.log(Level.WARNING, e.getMessage(), e);
  304. }
  305. }
  306. /**
  307. * Fourth stage: last checks, remove buffers, start competition itself.
  308. * Returns true if all participants online and ready on the stadium.
  309. */
  310. private final boolean startBattle()
  311. {
  312. try
  313. {
  314. if (_game.needBuffers())
  315. _zone.deleteBuffers();
  316. if (_game.checkBattleStatus() && _game.makeCompetitionStart())
  317. {
  318. // game successfully started
  319. _game.broadcastOlympiadInfo(_zone);
  320. _zone.broadcastPacket(SystemMessage.getSystemMessage(SystemMessageId.STARTS_THE_GAME));
  321. _zone.updateZoneStatusForCharactersInside();
  322. return true;
  323. }
  324. }
  325. catch (Exception e)
  326. {
  327. _log.log(Level.WARNING, e.getMessage(), e);
  328. }
  329. return false;
  330. }
  331. /**
  332. * Fifth stage: battle is running, returns true if winner found.
  333. */
  334. private final boolean checkBattle()
  335. {
  336. try
  337. {
  338. return _game.haveWinner();
  339. }
  340. catch (Exception e)
  341. {
  342. _log.log(Level.WARNING, e.getMessage(), e);
  343. }
  344. return true;
  345. }
  346. /**
  347. * Sixth stage: winner's validations
  348. */
  349. private final void stopGame()
  350. {
  351. try
  352. {
  353. _game.validateWinner(_zone);
  354. }
  355. catch (Exception e)
  356. {
  357. _log.log(Level.WARNING, e.getMessage(), e);
  358. }
  359. try
  360. {
  361. _zone.updateZoneStatusForCharactersInside();
  362. }
  363. catch (Exception e)
  364. {
  365. _log.log(Level.WARNING, e.getMessage(), e);
  366. }
  367. try
  368. {
  369. _game.cleanEffects();
  370. }
  371. catch (Exception e)
  372. {
  373. _log.log(Level.WARNING, e.getMessage(), e);
  374. }
  375. }
  376. /**
  377. * Seventh stage: game cleanup (port players back, closing doors, etc)
  378. */
  379. private final void cleanupGame()
  380. {
  381. try
  382. {
  383. _game.playersStatusBack();
  384. }
  385. catch (Exception e)
  386. {
  387. _log.log(Level.WARNING, e.getMessage(), e);
  388. }
  389. try
  390. {
  391. _game.portPlayersBack();
  392. }
  393. catch (Exception e)
  394. {
  395. _log.log(Level.WARNING, e.getMessage(), e);
  396. }
  397. try
  398. {
  399. _game.clearPlayers();
  400. }
  401. catch (Exception e)
  402. {
  403. _log.log(Level.WARNING, e.getMessage(), e);
  404. }
  405. try
  406. {
  407. _zone.closeDoors();
  408. }
  409. catch (Exception e)
  410. {
  411. _log.log(Level.WARNING, e.getMessage(), e);
  412. }
  413. }
  414. }