HandysBlockCheckerManager.java 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534
  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.instancemanager;
  20. import java.util.ArrayList;
  21. import java.util.HashMap;
  22. import java.util.List;
  23. import java.util.Map;
  24. import com.l2jserver.Config;
  25. import com.l2jserver.gameserver.ThreadPoolManager;
  26. import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
  27. import com.l2jserver.gameserver.model.entity.BlockCheckerEngine;
  28. import com.l2jserver.gameserver.model.itemcontainer.PcInventory;
  29. import com.l2jserver.gameserver.model.olympiad.OlympiadManager;
  30. import com.l2jserver.gameserver.model.zone.ZoneId;
  31. import com.l2jserver.gameserver.network.SystemMessageId;
  32. import com.l2jserver.gameserver.network.serverpackets.ExCubeGameAddPlayer;
  33. import com.l2jserver.gameserver.network.serverpackets.ExCubeGameChangeTeam;
  34. import com.l2jserver.gameserver.network.serverpackets.ExCubeGameRemovePlayer;
  35. import com.l2jserver.gameserver.network.serverpackets.L2GameServerPacket;
  36. import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
  37. /**
  38. * This class manage the player add/remove, team change and event arena status,<br>
  39. * as the clearance of the participants list or liberate the arena.
  40. * @author BiggBoss
  41. */
  42. public final class HandysBlockCheckerManager
  43. {
  44. // All the participants and their team classified by arena
  45. private static final ArenaParticipantsHolder[] _arenaPlayers = new ArenaParticipantsHolder[4];
  46. // Arena votes to start the game
  47. private static final Map<Integer, Integer> _arenaVotes = new HashMap<>();
  48. // Arena Status, True = is being used, otherwise, False
  49. private static final Map<Integer, Boolean> _arenaStatus = new HashMap<>();
  50. // Registration request penalty (10 seconds)
  51. protected static List<Integer> _registrationPenalty = new ArrayList<>();
  52. /**
  53. * Return the number of event-start votes for the specified arena id
  54. * @param arenaId
  55. * @return int (number of votes)
  56. */
  57. public synchronized int getArenaVotes(int arenaId)
  58. {
  59. return _arenaVotes.get(arenaId);
  60. }
  61. /**
  62. * Add a new vote to start the event for the specified arena id
  63. * @param arena
  64. */
  65. public synchronized void increaseArenaVotes(int arena)
  66. {
  67. int newVotes = _arenaVotes.get(arena) + 1;
  68. ArenaParticipantsHolder holder = _arenaPlayers[arena];
  69. if ((newVotes > (holder.getAllPlayers().size() / 2)) && !holder.getEvent().isStarted())
  70. {
  71. clearArenaVotes(arena);
  72. if ((holder.getBlueTeamSize() == 0) || (holder.getRedTeamSize() == 0))
  73. {
  74. return;
  75. }
  76. if (Config.HBCE_FAIR_PLAY)
  77. {
  78. holder.checkAndShuffle();
  79. }
  80. ThreadPoolManager.getInstance().executeTask(holder.getEvent().new StartEvent());
  81. }
  82. else
  83. {
  84. _arenaVotes.put(arena, newVotes);
  85. }
  86. }
  87. /**
  88. * Will clear the votes queue (of event start) for the specified arena id
  89. * @param arena
  90. */
  91. public synchronized void clearArenaVotes(int arena)
  92. {
  93. _arenaVotes.put(arena, 0);
  94. }
  95. protected HandysBlockCheckerManager()
  96. {
  97. // Initialize arena status
  98. _arenaStatus.put(0, false);
  99. _arenaStatus.put(1, false);
  100. _arenaStatus.put(2, false);
  101. _arenaStatus.put(3, false);
  102. }
  103. /**
  104. * Returns the players holder
  105. * @param arena
  106. * @return ArenaParticipantsHolder
  107. */
  108. public ArenaParticipantsHolder getHolder(int arena)
  109. {
  110. return _arenaPlayers[arena];
  111. }
  112. /**
  113. * Initializes the participants holder
  114. */
  115. public void startUpParticipantsQueue()
  116. {
  117. for (int i = 0; i < 4; ++i)
  118. {
  119. _arenaPlayers[i] = new ArenaParticipantsHolder(i);
  120. }
  121. }
  122. /**
  123. * Add the player to the specified arena (through the specified arena manager) and send the needed server -> client packets
  124. * @param player
  125. * @param arenaId
  126. * @return
  127. */
  128. public boolean addPlayerToArena(L2PcInstance player, int arenaId)
  129. {
  130. ArenaParticipantsHolder holder = _arenaPlayers[arenaId];
  131. synchronized (holder)
  132. {
  133. boolean isRed;
  134. for (int i = 0; i < 4; i++)
  135. {
  136. if (_arenaPlayers[i].getAllPlayers().contains(player))
  137. {
  138. SystemMessage msg = SystemMessage.getSystemMessage(SystemMessageId.C1_IS_ALREADY_REGISTERED_ON_THE_MATCH_WAITING_LIST);
  139. msg.addCharName(player);
  140. player.sendPacket(msg);
  141. return false;
  142. }
  143. }
  144. if (player.isCursedWeaponEquipped())
  145. {
  146. player.sendPacket(SystemMessageId.CANNOT_REGISTER_PROCESSING_CURSED_WEAPON);
  147. return false;
  148. }
  149. if (player.isOnEvent() || player.isInOlympiadMode())
  150. {
  151. player.sendMessage("Couldnt register you due other event participation");
  152. return false;
  153. }
  154. if (OlympiadManager.getInstance().isRegistered(player))
  155. {
  156. OlympiadManager.getInstance().unRegisterNoble(player);
  157. player.sendPacket(SystemMessageId.COLISEUM_OLYMPIAD_KRATEIS_APPLICANTS_CANNOT_PARTICIPATE);
  158. }
  159. // if(UnderGroundColiseum.getInstance().isRegisteredPlayer(player))
  160. // {
  161. // UngerGroundColiseum.getInstance().removeParticipant(player);
  162. // player.sendPacket(SystemMessageId.COLISEUM_OLYMPIAD_KRATEIS_APPLICANTS_CANNOT_PARTICIPATE));
  163. // }
  164. // if(KrateiCubeManager.getInstance().isRegisteredPlayer(player))
  165. // {
  166. // KrateiCubeManager.getInstance().removeParticipant(player);
  167. // player.sendPacket(SystemMessageId.COLISEUM_OLYMPIAD_KRATEIS_APPLICANTS_CANNOT_PARTICIPATE));
  168. // }
  169. if (_registrationPenalty.contains(player.getObjectId()))
  170. {
  171. player.sendPacket(SystemMessageId.CANNOT_REQUEST_REGISTRATION_10_SECS_AFTER);
  172. return false;
  173. }
  174. if (holder.getBlueTeamSize() < holder.getRedTeamSize())
  175. {
  176. holder.addPlayer(player, 1);
  177. isRed = false;
  178. }
  179. else
  180. {
  181. holder.addPlayer(player, 0);
  182. isRed = true;
  183. }
  184. holder.broadCastPacketToTeam(new ExCubeGameAddPlayer(player, isRed));
  185. return true;
  186. }
  187. }
  188. /**
  189. * Will remove the specified player from the specified team and arena and will send the needed packet to all his team mates / enemy team mates
  190. * @param player
  191. * @param arenaId
  192. * @param team
  193. */
  194. public void removePlayer(L2PcInstance player, int arenaId, int team)
  195. {
  196. ArenaParticipantsHolder holder = _arenaPlayers[arenaId];
  197. synchronized (holder)
  198. {
  199. boolean isRed = team == 0 ? true : false;
  200. holder.removePlayer(player, team);
  201. holder.broadCastPacketToTeam(new ExCubeGameRemovePlayer(player, isRed));
  202. // End event if theres an empty team
  203. int teamSize = isRed ? holder.getRedTeamSize() : holder.getBlueTeamSize();
  204. if (teamSize == 0)
  205. {
  206. holder.getEvent().endEventAbnormally();
  207. }
  208. Integer objId = player.getObjectId();
  209. if (!_registrationPenalty.contains(objId))
  210. {
  211. _registrationPenalty.add(objId);
  212. }
  213. schedulePenaltyRemoval(objId);
  214. }
  215. }
  216. /**
  217. * Will change the player from one team to other (if possible) and will send the needed packets
  218. * @param player
  219. * @param arena
  220. * @param team
  221. */
  222. public void changePlayerToTeam(L2PcInstance player, int arena, int team)
  223. {
  224. ArenaParticipantsHolder holder = _arenaPlayers[arena];
  225. synchronized (holder)
  226. {
  227. boolean isFromRed = holder._redPlayers.contains(player);
  228. if (isFromRed && (holder.getBlueTeamSize() == 6))
  229. {
  230. player.sendMessage("The team is full");
  231. return;
  232. }
  233. else if (!isFromRed && (holder.getRedTeamSize() == 6))
  234. {
  235. player.sendMessage("The team is full");
  236. return;
  237. }
  238. int futureTeam = isFromRed ? 1 : 0;
  239. holder.addPlayer(player, futureTeam);
  240. if (isFromRed)
  241. {
  242. holder.removePlayer(player, 0);
  243. }
  244. else
  245. {
  246. holder.removePlayer(player, 1);
  247. }
  248. holder.broadCastPacketToTeam(new ExCubeGameChangeTeam(player, isFromRed));
  249. }
  250. }
  251. /**
  252. * Will erase all participants from the specified holder
  253. * @param arenaId
  254. */
  255. public synchronized void clearPaticipantQueueByArenaId(int arenaId)
  256. {
  257. _arenaPlayers[arenaId].clearPlayers();
  258. }
  259. /**
  260. * Returns true if arena is holding an event at this momment
  261. * @param arenaId
  262. * @return boolean
  263. */
  264. public boolean arenaIsBeingUsed(int arenaId)
  265. {
  266. if ((arenaId < 0) || (arenaId > 3))
  267. {
  268. return false;
  269. }
  270. return _arenaStatus.get(arenaId);
  271. }
  272. /**
  273. * Set the specified arena as being used
  274. * @param arenaId
  275. */
  276. public void setArenaBeingUsed(int arenaId)
  277. {
  278. _arenaStatus.put(arenaId, true);
  279. }
  280. /**
  281. * Set as free the specified arena for future events
  282. * @param arenaId
  283. */
  284. public void setArenaFree(int arenaId)
  285. {
  286. _arenaStatus.put(arenaId, false);
  287. }
  288. /**
  289. * Called when played logs out while participating in Block Checker Event
  290. * @param player
  291. */
  292. public void onDisconnect(L2PcInstance player)
  293. {
  294. int arena = player.getBlockCheckerArena();
  295. int team = getHolder(arena).getPlayerTeam(player);
  296. HandysBlockCheckerManager.getInstance().removePlayer(player, arena, team);
  297. if (player.getTeam() > 0)
  298. {
  299. player.stopAllEffects();
  300. // Remove team aura
  301. player.setTeam(0);
  302. // Remove the event items
  303. PcInventory inv = player.getInventory();
  304. if (inv.getItemByItemId(13787) != null)
  305. {
  306. long count = inv.getInventoryItemCount(13787, 0);
  307. inv.destroyItemByItemId("Handys Block Checker", 13787, count, player, player);
  308. }
  309. if (inv.getItemByItemId(13788) != null)
  310. {
  311. long count = inv.getInventoryItemCount(13788, 0);
  312. inv.destroyItemByItemId("Handys Block Checker", 13788, count, player, player);
  313. }
  314. player.setInsideZone(ZoneId.PVP, false);
  315. // Teleport Back
  316. player.teleToLocation(-57478, -60367, -2370);
  317. }
  318. }
  319. public class ArenaParticipantsHolder
  320. {
  321. int _arena;
  322. List<L2PcInstance> _redPlayers;
  323. List<L2PcInstance> _bluePlayers;
  324. BlockCheckerEngine _engine;
  325. public ArenaParticipantsHolder(int arena)
  326. {
  327. _arena = arena;
  328. _redPlayers = new ArrayList<>(6);
  329. _bluePlayers = new ArrayList<>(6);
  330. _engine = new BlockCheckerEngine(this, _arena);
  331. }
  332. public List<L2PcInstance> getRedPlayers()
  333. {
  334. return _redPlayers;
  335. }
  336. public List<L2PcInstance> getBluePlayers()
  337. {
  338. return _bluePlayers;
  339. }
  340. public ArrayList<L2PcInstance> getAllPlayers()
  341. {
  342. ArrayList<L2PcInstance> all = new ArrayList<>(12);
  343. all.addAll(_redPlayers);
  344. all.addAll(_bluePlayers);
  345. return all;
  346. }
  347. public void addPlayer(L2PcInstance player, int team)
  348. {
  349. if (team == 0)
  350. {
  351. _redPlayers.add(player);
  352. }
  353. else
  354. {
  355. _bluePlayers.add(player);
  356. }
  357. }
  358. public void removePlayer(L2PcInstance player, int team)
  359. {
  360. if (team == 0)
  361. {
  362. _redPlayers.remove(player);
  363. }
  364. else
  365. {
  366. _bluePlayers.remove(player);
  367. }
  368. }
  369. public int getPlayerTeam(L2PcInstance player)
  370. {
  371. if (_redPlayers.contains(player))
  372. {
  373. return 0;
  374. }
  375. else if (_bluePlayers.contains(player))
  376. {
  377. return 1;
  378. }
  379. else
  380. {
  381. return -1;
  382. }
  383. }
  384. public int getRedTeamSize()
  385. {
  386. return _redPlayers.size();
  387. }
  388. public int getBlueTeamSize()
  389. {
  390. return _bluePlayers.size();
  391. }
  392. public void broadCastPacketToTeam(L2GameServerPacket packet)
  393. {
  394. for (L2PcInstance p : _redPlayers)
  395. {
  396. p.sendPacket(packet);
  397. }
  398. for (L2PcInstance p : _bluePlayers)
  399. {
  400. p.sendPacket(packet);
  401. }
  402. }
  403. public void clearPlayers()
  404. {
  405. _redPlayers.clear();
  406. _bluePlayers.clear();
  407. }
  408. public BlockCheckerEngine getEvent()
  409. {
  410. return _engine;
  411. }
  412. public void updateEvent()
  413. {
  414. _engine.updatePlayersOnStart(this);
  415. }
  416. protected void checkAndShuffle()
  417. {
  418. int redSize = _redPlayers.size();
  419. int blueSize = _bluePlayers.size();
  420. if (redSize > (blueSize + 1))
  421. {
  422. broadCastPacketToTeam(SystemMessage.getSystemMessage(SystemMessageId.TEAM_ADJUSTED_BECAUSE_WRONG_POPULATION_RATIO));
  423. int needed = redSize - (blueSize + 1);
  424. for (int i = 0; i < (needed + 1); i++)
  425. {
  426. L2PcInstance plr = _redPlayers.get(i);
  427. if (plr == null)
  428. {
  429. continue;
  430. }
  431. changePlayerToTeam(plr, _arena, 1);
  432. }
  433. }
  434. else if (blueSize > (redSize + 1))
  435. {
  436. broadCastPacketToTeam(SystemMessage.getSystemMessage(SystemMessageId.TEAM_ADJUSTED_BECAUSE_WRONG_POPULATION_RATIO));
  437. int needed = blueSize - (redSize + 1);
  438. for (int i = 0; i < (needed + 1); i++)
  439. {
  440. L2PcInstance plr = _bluePlayers.get(i);
  441. if (plr == null)
  442. {
  443. continue;
  444. }
  445. changePlayerToTeam(plr, _arena, 0);
  446. }
  447. }
  448. }
  449. }
  450. private void schedulePenaltyRemoval(int objId)
  451. {
  452. ThreadPoolManager.getInstance().scheduleGeneral(new PenaltyRemove(objId), 10000);
  453. }
  454. private class PenaltyRemove implements Runnable
  455. {
  456. private final Integer objectId;
  457. public PenaltyRemove(Integer id)
  458. {
  459. objectId = id;
  460. }
  461. @Override
  462. public void run()
  463. {
  464. _registrationPenalty.remove(objectId);
  465. }
  466. }
  467. public static HandysBlockCheckerManager getInstance()
  468. {
  469. return SingletonHolder._instance;
  470. }
  471. private static class SingletonHolder
  472. {
  473. protected static final HandysBlockCheckerManager _instance = new HandysBlockCheckerManager();
  474. }
  475. }