OlympiadGameTask.java 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  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. @Override
  104. public final void run()
  105. {
  106. try
  107. {
  108. int delay = 1; // schedule next call after 1s
  109. switch (_state)
  110. {
  111. // Game created
  112. case BEGIN:
  113. {
  114. _state = GameState.TELEPORT_TO_ARENA;
  115. _countDown = Config.ALT_OLY_WAIT_TIME;
  116. break;
  117. }
  118. // Teleport to arena countdown
  119. case TELEPORT_TO_ARENA:
  120. {
  121. if (_countDown > 0)
  122. {
  123. SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_WILL_ENTER_THE_OLYMPIAD_STADIUM_IN_S1_SECOND_S);
  124. sm.addNumber(_countDown);
  125. _game.broadcastPacket(sm);
  126. }
  127. delay = getDelay(TELEPORT_TO_ARENA);
  128. if (_countDown <= 0)
  129. _state = GameState.GAME_STARTED;
  130. break;
  131. }
  132. // Game start, port players to arena
  133. case GAME_STARTED:
  134. {
  135. if (!startGame())
  136. {
  137. _state = GameState.GAME_STOPPED;
  138. break;
  139. }
  140. _state = GameState.BATTLE_COUNTDOWN_FIRST;
  141. _countDown = BATTLE_START_TIME_FIRST[0];
  142. delay = 5;
  143. break;
  144. }
  145. // Battle start countdown, first part (60-10)
  146. case BATTLE_COUNTDOWN_FIRST:
  147. {
  148. if (_countDown > 0)
  149. {
  150. SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.THE_GAME_WILL_START_IN_S1_SECOND_S);
  151. sm.addNumber(_countDown);
  152. _zone.broadcastPacket(sm);
  153. }
  154. delay = getDelay(BATTLE_START_TIME_FIRST);
  155. if (_countDown <= 0)
  156. {
  157. openDoors();
  158. _state = GameState.BATTLE_COUNTDOWN_SECOND;
  159. _countDown = BATTLE_START_TIME_SECOND[0];
  160. delay = getDelay(BATTLE_START_TIME_SECOND);
  161. }
  162. break;
  163. }
  164. // Battle start countdown, second part (10-0)
  165. case BATTLE_COUNTDOWN_SECOND:
  166. {
  167. if (_countDown > 0)
  168. {
  169. SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.THE_GAME_WILL_START_IN_S1_SECOND_S);
  170. sm.addNumber(_countDown);
  171. _zone.broadcastPacket(sm);
  172. }
  173. delay = getDelay(BATTLE_START_TIME_SECOND);
  174. if (_countDown <= 0)
  175. _state = GameState.BATTLE_STARTED;
  176. break;
  177. }
  178. // Beginning of the battle
  179. case BATTLE_STARTED:
  180. {
  181. _countDown = 0;
  182. _state = GameState.BATTLE_IN_PROGRESS; // set state first, used in zone update
  183. if (!startBattle())
  184. _state = GameState.GAME_STOPPED;
  185. break;
  186. }
  187. // Checks during battle
  188. case BATTLE_IN_PROGRESS:
  189. {
  190. _countDown += 1000;
  191. if (checkBattle() || _countDown > Config.ALT_OLY_BATTLE)
  192. _state = GameState.GAME_STOPPED;
  193. break;
  194. }
  195. // End of the battle
  196. case GAME_STOPPED:
  197. {
  198. _state = GameState.TELEPORT_TO_TOWN;
  199. _countDown = TELEPORT_TO_TOWN[0];
  200. stopGame();
  201. delay = getDelay(TELEPORT_TO_TOWN);
  202. break;
  203. }
  204. // Teleport to town countdown
  205. case TELEPORT_TO_TOWN:
  206. {
  207. if (_countDown > 0)
  208. {
  209. SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_WILL_BE_MOVED_TO_TOWN_IN_S1_SECONDS);
  210. sm.addNumber(_countDown);
  211. _game.broadcastPacket(sm);
  212. }
  213. delay = getDelay(TELEPORT_TO_TOWN);
  214. if (_countDown <= 0)
  215. _state = GameState.CLEANUP;
  216. break;
  217. }
  218. // Removals
  219. case CLEANUP:
  220. {
  221. cleanupGame();
  222. _state = GameState.IDLE;
  223. _game = null;
  224. return;
  225. }
  226. }
  227. ThreadPoolManager.getInstance().scheduleGeneral(this, delay * 1000);
  228. }
  229. catch (Exception e)
  230. {
  231. switch (_state)
  232. {
  233. case GAME_STOPPED:
  234. case TELEPORT_TO_TOWN:
  235. case CLEANUP:
  236. case IDLE:
  237. {
  238. _log.log(Level.WARNING, "Unable to return players back in town, exception: " + e.getMessage());
  239. _state = GameState.IDLE;
  240. _game = null;
  241. return;
  242. }
  243. }
  244. _log.log(Level.WARNING, "Exception in " + _state + ", trying to port players back: " + e.getMessage(), e);
  245. _state = GameState.GAME_STOPPED;
  246. ThreadPoolManager.getInstance().scheduleGeneral(this, 1000);
  247. }
  248. }
  249. private final int getDelay(int[] times)
  250. {
  251. int time;
  252. for (int i = 0; i < times.length - 1; i++)
  253. {
  254. time = times[i];
  255. if (time >= _countDown)
  256. continue;
  257. final int delay = _countDown - time;
  258. _countDown = time;
  259. return delay;
  260. }
  261. // should not happens
  262. _countDown = -1;
  263. return 1;
  264. }
  265. /**
  266. * Second stage: check for defaulted, port players to arena, announce game.
  267. * @return true if no participants defaulted.
  268. */
  269. private final boolean startGame()
  270. {
  271. try
  272. {
  273. // Checking for opponents and teleporting to arena
  274. if (_game.checkDefaulted())
  275. return false;
  276. _zone.closeDoors();
  277. if (_game.needBuffers())
  278. _zone.spawnBuffers();
  279. if (!_game.portPlayersToArena(_zone.getSpawns()))
  280. return false;
  281. _game.removals();
  282. _needAnnounce = true;
  283. OlympiadGameManager.getInstance().startBattle(); // inform manager
  284. return true;
  285. }
  286. catch (Exception e)
  287. {
  288. _log.log(Level.WARNING, e.getMessage(), e);
  289. }
  290. return false;
  291. }
  292. /**
  293. * Third stage: open doors.
  294. */
  295. private final void openDoors()
  296. {
  297. try
  298. {
  299. _game.resetDamage();
  300. _zone.openDoors();
  301. }
  302. catch (Exception e)
  303. {
  304. _log.log(Level.WARNING, e.getMessage(), e);
  305. }
  306. }
  307. /**
  308. * Fourth stage: last checks, remove buffers, start competition itself.
  309. * @return true if all participants online and ready on the stadium.
  310. */
  311. private final boolean startBattle()
  312. {
  313. try
  314. {
  315. if (_game.needBuffers())
  316. _zone.deleteBuffers();
  317. if (_game.checkBattleStatus() && _game.makeCompetitionStart())
  318. {
  319. // game successfully started
  320. _game.broadcastOlympiadInfo(_zone);
  321. _zone.broadcastPacket(SystemMessage.getSystemMessage(SystemMessageId.STARTS_THE_GAME));
  322. _zone.updateZoneStatusForCharactersInside();
  323. return true;
  324. }
  325. }
  326. catch (Exception e)
  327. {
  328. _log.log(Level.WARNING, e.getMessage(), e);
  329. }
  330. return false;
  331. }
  332. /**
  333. * Fifth stage: battle is running, returns true if winner found.
  334. * @return
  335. */
  336. private final boolean checkBattle()
  337. {
  338. try
  339. {
  340. return _game.haveWinner();
  341. }
  342. catch (Exception e)
  343. {
  344. _log.log(Level.WARNING, e.getMessage(), e);
  345. }
  346. return true;
  347. }
  348. /**
  349. * Sixth stage: winner's validations
  350. */
  351. private final void stopGame()
  352. {
  353. try
  354. {
  355. _game.validateWinner(_zone);
  356. }
  357. catch (Exception e)
  358. {
  359. _log.log(Level.WARNING, e.getMessage(), e);
  360. }
  361. try
  362. {
  363. _zone.updateZoneStatusForCharactersInside();
  364. }
  365. catch (Exception e)
  366. {
  367. _log.log(Level.WARNING, e.getMessage(), e);
  368. }
  369. try
  370. {
  371. _game.cleanEffects();
  372. }
  373. catch (Exception e)
  374. {
  375. _log.log(Level.WARNING, e.getMessage(), e);
  376. }
  377. }
  378. /**
  379. * Seventh stage: game cleanup (port players back, closing doors, etc)
  380. */
  381. private final void cleanupGame()
  382. {
  383. try
  384. {
  385. _game.playersStatusBack();
  386. }
  387. catch (Exception e)
  388. {
  389. _log.log(Level.WARNING, e.getMessage(), e);
  390. }
  391. try
  392. {
  393. _game.portPlayersBack();
  394. }
  395. catch (Exception e)
  396. {
  397. _log.log(Level.WARNING, e.getMessage(), e);
  398. }
  399. try
  400. {
  401. _game.clearPlayers();
  402. }
  403. catch (Exception e)
  404. {
  405. _log.log(Level.WARNING, e.getMessage(), e);
  406. }
  407. try
  408. {
  409. _zone.closeDoors();
  410. }
  411. catch (Exception e)
  412. {
  413. _log.log(Level.WARNING, e.getMessage(), e);
  414. }
  415. }
  416. }