OlympiadGameTask.java 10 KB

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