Advertisement
Guest User

Untitled

a guest
Jun 13th, 2019
163
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 33.47 KB | None | 0 0
  1. package net.sf.l2j.gameserver.model.entity;
  2.  
  3. import java.sql.Connection;
  4. import java.sql.PreparedStatement;
  5. import java.sql.ResultSet;
  6. import java.util.ArrayList;
  7. import java.util.Calendar;
  8. import java.util.Collections;
  9. import java.util.List;
  10. import java.util.Map;
  11. import java.util.concurrent.ConcurrentHashMap;
  12. import java.util.concurrent.ScheduledFuture;
  13. import java.util.logging.Level;
  14. import java.util.logging.Logger;
  15. import java.util.stream.Collectors;
  16.  
  17. import net.sf.l2j.commons.concurrent.ThreadPool;
  18. import net.sf.l2j.commons.util.ArraysUtil;
  19.  
  20. import net.sf.l2j.Config;
  21. import net.sf.l2j.L2DatabaseFactory;
  22. import net.sf.l2j.gameserver.data.manager.CastleManager;
  23. import net.sf.l2j.gameserver.data.sql.ClanTable;
  24. import net.sf.l2j.gameserver.data.xml.NpcData;
  25. import net.sf.l2j.gameserver.model.L2Spawn;
  26. import net.sf.l2j.gameserver.model.WorldObject;
  27. import net.sf.l2j.gameserver.model.actor.Npc;
  28. import net.sf.l2j.gameserver.model.actor.instance.ControlTower;
  29. import net.sf.l2j.gameserver.model.actor.instance.FlameTower;
  30. import net.sf.l2j.gameserver.model.actor.instance.Player;
  31. import net.sf.l2j.gameserver.model.location.TowerSpawnLocation;
  32. import net.sf.l2j.gameserver.model.pledge.Clan;
  33. import net.sf.l2j.gameserver.model.pledge.ClanMember;
  34. import net.sf.l2j.gameserver.network.SystemMessageId;
  35. import net.sf.l2j.gameserver.network.serverpackets.PlaySound;
  36. import net.sf.l2j.gameserver.network.serverpackets.SystemMessage;
  37. import net.sf.l2j.gameserver.network.serverpackets.UserInfo;
  38. import net.sf.l2j.gameserver.scripting.Quest;
  39. import net.sf.l2j.gameserver.util.Broadcast;
  40.  
  41. public class Siege implements Siegable
  42. {
  43. public enum SiegeSide
  44. {
  45. OWNER,
  46. DEFENDER,
  47. ATTACKER,
  48. PENDING
  49. }
  50.  
  51. public enum SiegeStatus
  52. {
  53. REGISTRATION_OPENED, // Equals canceled or end siege event.
  54. REGISTRATION_OVER,
  55. IN_PROGRESS // Equals siege start event.
  56. }
  57.  
  58. protected static final Logger _log = Logger.getLogger(Siege.class.getName());
  59.  
  60. private static final String LOAD_SIEGE_CLAN = "SELECT clan_id,type FROM siege_clans WHERE castle_id=?";
  61.  
  62. private static final String CLEAR_SIEGE_CLANS = "DELETE FROM siege_clans WHERE castle_id=?";
  63. private static final String CLEAR_PENDING_CLANS = "DELETE FROM siege_clans WHERE castle_id=? AND type='PENDING'";
  64.  
  65. private static final String CLEAR_SIEGE_CLAN = "DELETE FROM siege_clans WHERE castle_id=? AND clan_id=?";
  66.  
  67. private static final String UPDATE_SIEGE_INFOS = "UPDATE castle SET siegeDate=?, regTimeOver=? WHERE id=?";
  68.  
  69. private static final String ADD_OR_UPDATE_SIEGE_CLAN = "INSERT INTO siege_clans (clan_id,castle_id,type) VALUES (?,?,?) ON DUPLICATE KEY UPDATE type=VALUES(type)";
  70.  
  71. private final Map<Clan, SiegeSide> _registeredClans = new ConcurrentHashMap<>();
  72.  
  73. private final Castle _castle;
  74.  
  75. private final List<ControlTower> _controlTowers = new ArrayList<>();
  76. private final List<FlameTower> _flameTowers = new ArrayList<>();
  77.  
  78. private final List<Npc> _destroyedTowers = new ArrayList<>();
  79.  
  80. protected Calendar _siegeEndDate;
  81. protected ScheduledFuture<?> _siegeTask;
  82.  
  83. private SiegeStatus _siegeStatus = SiegeStatus.REGISTRATION_OPENED;
  84.  
  85. private List<Quest> _questEvents = Collections.emptyList();
  86.  
  87. public Siege(Castle castle)
  88. {
  89. _castle = castle;
  90.  
  91. // Add castle owner as defender (add owner first so that they are on the top of the defender list)
  92. if (_castle.getOwnerId() > 0)
  93. {
  94. final Clan clan = ClanTable.getInstance().getClan(getCastle().getOwnerId());
  95. if (clan != null)
  96. _registeredClans.put(clan, SiegeSide.OWNER);
  97. }
  98.  
  99. // Feed _registeredClans.
  100. try (Connection con = L2DatabaseFactory.getInstance().getConnection())
  101. {
  102. PreparedStatement ps = con.prepareStatement(LOAD_SIEGE_CLAN);
  103. ps.setInt(1, _castle.getCastleId());
  104.  
  105. ResultSet rs = ps.executeQuery();
  106. while (rs.next())
  107. {
  108. final Clan clan = ClanTable.getInstance().getClan(rs.getInt("clan_id"));
  109. if (clan != null)
  110. _registeredClans.put(clan, Enum.valueOf(SiegeSide.class, rs.getString("type")));
  111. }
  112. rs.close();
  113. ps.close();
  114. }
  115. catch (Exception e)
  116. {
  117. _log.log(Level.WARNING, "Exception: loadSiegeClan(): " + e.getMessage(), e);
  118. }
  119.  
  120. startAutoTask();
  121. }
  122.  
  123. @Override
  124. public void startSiege()
  125. {
  126. if (isInProgress())
  127. return;
  128.  
  129. if (getAttackerClans().isEmpty())
  130. {
  131. final SystemMessage sm = SystemMessage.getSystemMessage((getCastle().getOwnerId() <= 0) ? SystemMessageId.SIEGE_OF_S1_HAS_BEEN_CANCELED_DUE_TO_LACK_OF_INTEREST : SystemMessageId.S1_SIEGE_WAS_CANCELED_BECAUSE_NO_CLANS_PARTICIPATED);
  132. sm.addString(getCastle().getName());
  133.  
  134. Broadcast.toAllOnlinePlayers(sm);
  135. saveCastleSiege(true);
  136. return;
  137. }
  138.  
  139. changeStatus(SiegeStatus.IN_PROGRESS); // Flag so that same siege instance cannot be started again
  140.  
  141. updatePlayerSiegeStateFlags(false);
  142. getCastle().getSiegeZone().banishForeigners(getCastle().getOwnerId());
  143.  
  144. spawnControlTowers(); // Spawn control towers
  145. spawnFlameTowers(); // Spawn flame towers
  146. getCastle().closeDoors(); // Close doors
  147.  
  148. getCastle().spawnSiegeGuardsOrMercenaries();
  149.  
  150. getCastle().getSiegeZone().setIsActive(true);
  151. getCastle().getSiegeZone().updateZoneStatusForCharactersInside();
  152.  
  153. _siegeEndDate = Calendar.getInstance();
  154. _siegeEndDate.add(Calendar.MINUTE, Config.SIEGE_LENGTH);
  155.  
  156. // Schedule a task to prepare auto siege end
  157. ThreadPool.schedule(new EndSiegeTask(getCastle()), 1000);
  158.  
  159. Broadcast.toAllOnlinePlayers(SystemMessage.getSystemMessage(SystemMessageId.SIEGE_OF_S1_HAS_STARTED).addString(getCastle().getName()));
  160. Broadcast.toAllOnlinePlayers(new PlaySound("systemmsg_e.17"));
  161. }
  162.  
  163. @Override
  164. public void endSiege()
  165. {
  166. if (!isInProgress())
  167. return;
  168.  
  169. Broadcast.toAllOnlinePlayers(SystemMessage.getSystemMessage(SystemMessageId.SIEGE_OF_S1_HAS_ENDED).addString(getCastle().getName()));
  170. Broadcast.toAllOnlinePlayers(new PlaySound("systemmsg_e.18"));
  171.  
  172. if (getCastle().getOwnerId() > 0)
  173. {
  174. Clan clan = ClanTable.getInstance().getClan(getCastle().getOwnerId());
  175. Broadcast.announceToOnlinePlayers("Clan " + clan.getName() + " has take the " + getCastle().getName() + " castle!", true);
  176. Broadcast.toAllOnlinePlayers(SystemMessage.getSystemMessage(SystemMessageId.CLAN_S1_VICTORIOUS_OVER_S2_S_SIEGE).addString(clan.getName()).addString(getCastle().getName()));
  177.  
  178. // An initial clan was holding the castle and is different of current owner.
  179. final Clan formerClan = getCastle().getInitialCastleOwner();
  180. if (formerClan != null && clan != formerClan)
  181. {
  182. // Delete circlets and crown's leader for initial castle's owner (if one was existing)
  183. getCastle().checkItemsForClan(formerClan);
  184.  
  185. // Refresh hero diaries.
  186. for (ClanMember member : clan.getMembers())
  187. {
  188. final Player player = member.getPlayerInstance();
  189. if (player != null && player.isNoble())
  190. Hero.getInstance().setCastleTaken(player.getObjectId(), getCastle().getCastleId());
  191. }
  192. }
  193. }
  194. else
  195. Broadcast.toAllOnlinePlayers(SystemMessage.getSystemMessage(SystemMessageId.SIEGE_S1_DRAW).addString(getCastle().getName()));
  196.  
  197. // Cleanup clans kills/deaths counters, cleanup flag.
  198. for (Clan clan : _registeredClans.keySet())
  199. {
  200. clan.setSiegeKills(0);
  201. clan.setSiegeDeaths(0);
  202. clan.setFlag(null);
  203. }
  204.  
  205. // Refresh reputation points towards siege end.
  206. getCastle().updateClansReputation();
  207.  
  208. // Teleport all non-owning castle players on second closest town.
  209. getCastle().getSiegeZone().banishForeigners(getCastle().getOwnerId());
  210.  
  211. // Clear all flags.
  212. updatePlayerSiegeStateFlags(true);
  213.  
  214. // Save castle specific data.
  215. saveCastleSiege(true);
  216.  
  217. // Clear registered clans.
  218. clearAllClans();
  219.  
  220. // Remove all towers from this castle.
  221. removeTowers();
  222.  
  223. // Despawn guards or mercenaries.
  224. getCastle().despawnSiegeGuardsOrMercenaries();
  225.  
  226. // Respawn/repair castle doors.
  227. getCastle().spawnDoors(false);
  228.  
  229. getCastle().getSiegeZone().setIsActive(false);
  230. getCastle().getSiegeZone().updateZoneStatusForCharactersInside();
  231. }
  232.  
  233. @Override
  234. public final List<Clan> getAttackerClans()
  235. {
  236. return _registeredClans.entrySet().stream().filter(e -> e.getValue() == SiegeSide.ATTACKER).map(Map.Entry::getKey).collect(Collectors.toList());
  237. }
  238.  
  239. @Override
  240. public final List<Clan> getDefenderClans()
  241. {
  242. return _registeredClans.entrySet().stream().filter(e -> e.getValue() == SiegeSide.DEFENDER || e.getValue() == SiegeSide.OWNER).map(Map.Entry::getKey).collect(Collectors.toList());
  243. }
  244.  
  245. @Override
  246. public boolean checkSide(Clan clan, SiegeSide type)
  247. {
  248. return clan != null && _registeredClans.get(clan) == type;
  249. }
  250.  
  251. @Override
  252. public boolean checkSides(Clan clan, SiegeSide... types)
  253. {
  254. return clan != null && ArraysUtil.contains(types, _registeredClans.get(clan));
  255. }
  256.  
  257. @Override
  258. public boolean checkSides(Clan clan)
  259. {
  260. return clan != null && _registeredClans.containsKey(clan);
  261. }
  262.  
  263. @Override
  264. public Npc getFlag(Clan clan)
  265. {
  266. return (checkSide(clan, SiegeSide.ATTACKER)) ? clan.getFlag() : null;
  267. }
  268.  
  269. @Override
  270. public final Calendar getSiegeDate()
  271. {
  272. return getCastle().getSiegeDate();
  273. }
  274.  
  275. public Map<Clan, SiegeSide> getRegisteredClans()
  276. {
  277. return _registeredClans;
  278. }
  279.  
  280. public final List<Clan> getPendingClans()
  281. {
  282. return _registeredClans.entrySet().stream().filter(e -> e.getValue() == SiegeSide.PENDING).map(Map.Entry::getKey).collect(Collectors.toList());
  283. }
  284.  
  285. /**
  286. * This method is used to switch all SiegeClanType from one type to another.
  287. * @param clan
  288. * @param newState
  289. */
  290. private void switchSide(Clan clan, SiegeSide newState)
  291. {
  292. _registeredClans.put(clan, newState);
  293. }
  294.  
  295. /**
  296. * This method is used to switch all SiegeClanType from one type to another.
  297. * @param previousStates
  298. * @param newState
  299. */
  300. private void switchSides(SiegeSide newState, SiegeSide... previousStates)
  301. {
  302. for (Map.Entry<Clan, SiegeSide> entry : _registeredClans.entrySet())
  303. {
  304. if (ArraysUtil.contains(previousStates, entry.getValue()))
  305. entry.setValue(newState);
  306. }
  307. }
  308.  
  309. public SiegeSide getSide(Clan clan)
  310. {
  311. return _registeredClans.get(clan);
  312. }
  313.  
  314. /**
  315. * Check if both clans are registered as opponent.
  316. * @param formerClan : The first clan to check.
  317. * @param targetClan : The second clan to check.
  318. * @return true if one side is attacker/defender and other side is defender/attacker and false if one of clan isn't registered or previous statement didn't match.
  319. */
  320. public boolean isOnOppositeSide(Clan formerClan, Clan targetClan)
  321. {
  322. final SiegeSide formerSide = _registeredClans.get(formerClan);
  323. final SiegeSide targetSide = _registeredClans.get(targetClan);
  324.  
  325. // Clan isn't even registered ; return false.
  326. if (formerSide == null || targetSide == null)
  327. return false;
  328.  
  329. // One side is owner, pending or defender and the other is attacker ; or vice-versa.
  330. return (targetSide == SiegeSide.ATTACKER && (formerSide == SiegeSide.OWNER || formerSide == SiegeSide.DEFENDER || formerSide == SiegeSide.PENDING)) || (formerSide == SiegeSide.ATTACKER && (targetSide == SiegeSide.OWNER || targetSide == SiegeSide.DEFENDER || targetSide == SiegeSide.PENDING));
  331. }
  332.  
  333. /**
  334. * When control of castle changed during siege.
  335. */
  336. public void midVictory()
  337. {
  338. if (!isInProgress())
  339. return;
  340.  
  341. getCastle().despawnSiegeGuardsOrMercenaries();
  342.  
  343. if (getCastle().getOwnerId() <= 0)
  344. return;
  345.  
  346. final List<Clan> attackers = getAttackerClans();
  347. final List<Clan> defenders = getDefenderClans();
  348.  
  349. final Clan castleOwner = ClanTable.getInstance().getClan(getCastle().getOwnerId());
  350.  
  351. // No defending clans and only one attacker, end siege.
  352. if (defenders.isEmpty() && attackers.size() == 1)
  353. {
  354. switchSide(castleOwner, SiegeSide.OWNER);
  355. endSiege();
  356. return;
  357. }
  358.  
  359. final int allyId = castleOwner.getAllyId();
  360.  
  361. // No defending clans and all attackers are part of the newly named castle owner alliance.
  362. if (defenders.isEmpty() && allyId != 0)
  363. {
  364. boolean allInSameAlliance = true;
  365. for (Clan clan : attackers)
  366. {
  367. if (clan.getAllyId() != allyId)
  368. {
  369. allInSameAlliance = false;
  370. break;
  371. }
  372. }
  373.  
  374. if (allInSameAlliance)
  375. {
  376. switchSide(castleOwner, SiegeSide.OWNER);
  377. endSiege();
  378. return;
  379. }
  380. }
  381.  
  382. // All defenders and owner become attackers.
  383. switchSides(SiegeSide.ATTACKER, SiegeSide.DEFENDER, SiegeSide.OWNER);
  384.  
  385. // Newly named castle owner is setted.
  386. switchSide(castleOwner, SiegeSide.OWNER);
  387.  
  388. // Define newly named castle owner registered allies as defenders.
  389. if (allyId != 0)
  390. {
  391. for (Clan clan : attackers)
  392. {
  393. if (clan.getAllyId() == allyId)
  394. switchSide(clan, SiegeSide.DEFENDER);
  395. }
  396. }
  397. getCastle().getSiegeZone().banishForeigners(getCastle().getOwnerId());
  398.  
  399. // Removes defenders' flags.
  400. for (Clan clan : defenders)
  401. clan.setFlag(null);
  402.  
  403. getCastle().removeDoorUpgrade(); // Remove all castle doors upgrades.
  404. getCastle().removeTrapUpgrade(); // Remove all castle traps upgrades.
  405. getCastle().spawnDoors(true); // Respawn door to castle but make them weaker (50% hp).
  406.  
  407. removeTowers(); // Remove all towers from this castle.
  408.  
  409. spawnControlTowers(); // Each new siege midvictory CT are completely respawned.
  410. spawnFlameTowers();
  411.  
  412. updatePlayerSiegeStateFlags(false);
  413. }
  414.  
  415. /**
  416. * Broadcast a {@link SystemMessage} to defenders (or attackers if parameter is set).
  417. * @param message : The SystemMessage of the message to send to player
  418. * @param bothSides : If true, broadcast it too to attackers clans.
  419. */
  420. public void announceToPlayers(SystemMessage message, boolean bothSides)
  421. {
  422. for (Clan clan : getDefenderClans())
  423. clan.broadcastToOnlineMembers(message);
  424.  
  425. if (bothSides)
  426. {
  427. for (Clan clan : getAttackerClans())
  428. clan.broadcastToOnlineMembers(message);
  429. }
  430. }
  431.  
  432. public void updatePlayerSiegeStateFlags(boolean clear)
  433. {
  434. for (Clan clan : getAttackerClans())
  435. {
  436. for (Player member : clan.getOnlineMembers())
  437. {
  438. if (clear)
  439. {
  440. member.setSiegeState((byte) 0);
  441. member.setIsInSiege(false);
  442. }
  443. else
  444. {
  445. member.setSiegeState((byte) 1);
  446. if (checkIfInZone(member))
  447. member.setIsInSiege(true);
  448. }
  449. member.sendPacket(new UserInfo(member));
  450. member.broadcastRelationsChanges();
  451. }
  452. }
  453.  
  454. for (Clan clan : getDefenderClans())
  455. {
  456. for (Player member : clan.getOnlineMembers())
  457. {
  458. if (clear)
  459. {
  460. member.setSiegeState((byte) 0);
  461. member.setIsInSiege(false);
  462. }
  463. else
  464. {
  465. member.setSiegeState((byte) 2);
  466. if (checkIfInZone(member))
  467. member.setIsInSiege(true);
  468. }
  469. member.sendPacket(new UserInfo(member));
  470. member.broadcastRelationsChanges();
  471. }
  472. }
  473. }
  474.  
  475. /**
  476. * Check if an object is inside an area using his location.
  477. * @param object The Object to use positions.
  478. * @return true if object is inside the zone
  479. */
  480. public boolean checkIfInZone(WorldObject object)
  481. {
  482. return checkIfInZone(object.getX(), object.getY(), object.getZ());
  483. }
  484.  
  485. /**
  486. * @param x
  487. * @param y
  488. * @param z
  489. * @return true if object is inside the zone
  490. */
  491. public boolean checkIfInZone(int x, int y, int z)
  492. {
  493. return isInProgress() && getCastle().checkIfInZone(x, y, z); // Castle zone during siege
  494. }
  495.  
  496. /** Clear all registered siege clans from database for castle */
  497. public void clearAllClans()
  498. {
  499. try (Connection con = L2DatabaseFactory.getInstance().getConnection();
  500. PreparedStatement ps = con.prepareStatement(CLEAR_SIEGE_CLANS))
  501. {
  502. ps.setInt(1, getCastle().getCastleId());
  503. ps.executeUpdate();
  504. }
  505. catch (Exception e)
  506. {
  507. _log.log(Level.SEVERE, "Error clearing registered clans.", e);
  508. }
  509.  
  510. _registeredClans.clear();
  511.  
  512. // Add back the owner after cleaning the map.
  513. if (getCastle().getOwnerId() > 0)
  514. {
  515. final Clan clan = ClanTable.getInstance().getClan(getCastle().getOwnerId());
  516. if (clan != null)
  517. _registeredClans.put(clan, SiegeSide.OWNER);
  518. }
  519. }
  520.  
  521. /** Clear all siege clans waiting for approval from database for castle */
  522. protected void clearPendingClans()
  523. {
  524. try (Connection con = L2DatabaseFactory.getInstance().getConnection();
  525. PreparedStatement ps = con.prepareStatement(CLEAR_PENDING_CLANS))
  526. {
  527. ps.setInt(1, getCastle().getCastleId());
  528. ps.executeUpdate();
  529. }
  530. catch (Exception e)
  531. {
  532. _log.log(Level.SEVERE, "Error clearing pending clans.", e);
  533. }
  534.  
  535. _registeredClans.entrySet().removeIf(e -> e.getValue() == SiegeSide.PENDING);
  536. }
  537.  
  538. /**
  539. * Register clan as attacker
  540. * @param player : The player trying to register
  541. */
  542. public void registerAttacker(Player player)
  543. {
  544. if (player.getClan() == null)
  545. return;
  546.  
  547. int allyId = 0;
  548. if (getCastle().getOwnerId() != 0)
  549. allyId = ClanTable.getInstance().getClan(getCastle().getOwnerId()).getAllyId();
  550.  
  551. // If the castle owning clan got an alliance
  552. if (allyId != 0)
  553. {
  554. // Same alliance can't be attacked
  555. if (player.getClan().getAllyId() == allyId)
  556. {
  557. player.sendPacket(SystemMessageId.CANNOT_ATTACK_ALLIANCE_CASTLE);
  558. return;
  559. }
  560. }
  561.  
  562. // Can't register as attacker if at least one allied clan is registered as defender
  563. if (allyIsRegisteredOnOppositeSide(player.getClan(), true))
  564. player.sendPacket(SystemMessageId.CANT_ACCEPT_ALLY_ENEMY_FOR_SIEGE);
  565. // Save to database
  566. else if (checkIfCanRegister(player, SiegeSide.ATTACKER))
  567. registerClan(player.getClan(), SiegeSide.ATTACKER);
  568. }
  569.  
  570. /**
  571. * Register clan as defender.
  572. * @param player : The player trying to register
  573. */
  574. public void registerDefender(Player player)
  575. {
  576. if (player.getClan() == null)
  577. return;
  578.  
  579. // Castle owned by NPC is considered as full side
  580. if (getCastle().getOwnerId() <= 0)
  581. player.sendPacket(SystemMessageId.DEFENDER_SIDE_FULL);
  582. // Can't register as defender if at least one allied clan is registered as attacker
  583. else if (allyIsRegisteredOnOppositeSide(player.getClan(), false))
  584. player.sendPacket(SystemMessageId.CANT_ACCEPT_ALLY_ENEMY_FOR_SIEGE);
  585. // Save to database
  586. else if (checkIfCanRegister(player, SiegeSide.PENDING))
  587. registerClan(player.getClan(), SiegeSide.PENDING);
  588. }
  589.  
  590. /**
  591. * Verify if allies are registered on different list than the actual player's choice. Let's say clan A and clan B are in same alliance. If clan A wants to attack a castle, clan B mustn't be on defenders' list. The contrary is right too : you can't defend if one ally is on attackers' list.
  592. * @param clan : The clan used for alliance existence checks.
  593. * @param attacker : A boolean used to know if this check is used for attackers or defenders.
  594. * @return true if one clan of the alliance is registered in other side.
  595. */
  596. private boolean allyIsRegisteredOnOppositeSide(Clan clan, boolean attacker)
  597. {
  598. // Check if player's clan got an alliance ; if not, skip the check
  599. final int allyId = clan.getAllyId();
  600. if (allyId != 0)
  601. {
  602. // Verify through the clans list for existing clans
  603. for (Clan alliedClan : ClanTable.getInstance().getClans())
  604. {
  605. // If a clan with same allyId is found (so, same alliance)
  606. if (alliedClan.getAllyId() == allyId)
  607. {
  608. // Skip player's clan from the check
  609. if (alliedClan.getClanId() == clan.getClanId())
  610. continue;
  611.  
  612. // If the check is made for attackers' list
  613. if (attacker)
  614. {
  615. // Check if the allied clan is on defender / defender waiting lists
  616. if (checkSides(alliedClan, SiegeSide.DEFENDER, SiegeSide.OWNER, SiegeSide.PENDING))
  617. return true;
  618. }
  619. else
  620. {
  621. // Check if the allied clan is on attacker list
  622. if (checkSides(alliedClan, SiegeSide.ATTACKER))
  623. return true;
  624. }
  625. }
  626. }
  627. }
  628. return false;
  629. }
  630.  
  631. /**
  632. * Remove clan from siege. Drop it from _registeredClans and database. Castle owner can't be dropped.
  633. * @param clan : The clan to check.
  634. */
  635. public void unregisterClan(Clan clan)
  636. {
  637. // Check if clan parameter is ok, avoid to drop castle owner, then remove if possible. If it couldn't be removed, return.
  638. if (clan == null || clan.getCastleId() == getCastle().getCastleId() || _registeredClans.remove(clan) == null)
  639. return;
  640.  
  641. try (Connection con = L2DatabaseFactory.getInstance().getConnection();
  642. PreparedStatement ps = con.prepareStatement(CLEAR_SIEGE_CLAN))
  643. {
  644. ps.setInt(1, getCastle().getCastleId());
  645. ps.setInt(2, clan.getClanId());
  646. ps.executeUpdate();
  647. }
  648. catch (Exception e)
  649. {
  650. _log.log(Level.SEVERE, "Error unregistering clan.", e);
  651. }
  652. }
  653.  
  654. /**
  655. * This method allows to :
  656. * <ul>
  657. * <li>Check if the siege time is deprecated, and recalculate otherwise.</li>
  658. * <li>Schedule start siege (it's in an else because saveCastleSiege() already affect it).</li>
  659. * </ul>
  660. */
  661. private void startAutoTask()
  662. {
  663. if (getCastle().getSiegeDate().getTimeInMillis() < Calendar.getInstance().getTimeInMillis())
  664. saveCastleSiege(false);
  665. else
  666. {
  667. if (_siegeTask != null)
  668. _siegeTask.cancel(false);
  669.  
  670. _siegeTask = ThreadPool.schedule(new SiegeTask(getCastle()), 1000);
  671. }
  672. }
  673.  
  674. /**
  675. * @param player : The player trying to register.
  676. * @param type : The SiegeSide to test.
  677. * @return true if the player can register.
  678. */
  679. private boolean checkIfCanRegister(Player player, SiegeSide type)
  680. {
  681. SystemMessage sm;
  682.  
  683. if (isRegistrationOver())
  684. sm = SystemMessage.getSystemMessage(SystemMessageId.DEADLINE_FOR_SIEGE_S1_PASSED).addString(getCastle().getName());
  685. else if (isInProgress())
  686. sm = SystemMessage.getSystemMessage(SystemMessageId.NOT_SIEGE_REGISTRATION_TIME2);
  687. else if (player.getClan() == null || player.getClan().getLevel() < Config.MINIMUM_CLAN_LEVEL)
  688. sm = SystemMessage.getSystemMessage(SystemMessageId.ONLY_CLAN_LEVEL_4_ABOVE_MAY_SIEGE);
  689. else if (player.getClan().hasCastle())
  690. sm = (player.getClan().getClanId() == getCastle().getOwnerId()) ? SystemMessage.getSystemMessage(SystemMessageId.CLAN_THAT_OWNS_CASTLE_IS_AUTOMATICALLY_REGISTERED_DEFENDING) : SystemMessage.getSystemMessage(SystemMessageId.CLAN_THAT_OWNS_CASTLE_CANNOT_PARTICIPATE_OTHER_SIEGE);
  691. else if (player.getClan().isRegisteredOnSiege())
  692. sm = SystemMessage.getSystemMessage(SystemMessageId.ALREADY_REQUESTED_SIEGE_BATTLE);
  693. else if (checkIfAlreadyRegisteredForSameDay(player.getClan()))
  694. sm = SystemMessage.getSystemMessage(SystemMessageId.APPLICATION_DENIED_BECAUSE_ALREADY_SUBMITTED_A_REQUEST_FOR_ANOTHER_SIEGE_BATTLE);
  695. else if (type == SiegeSide.ATTACKER && getAttackerClans().size() >= Config.MAX_ATTACKERS_NUMBER)
  696. sm = SystemMessage.getSystemMessage(SystemMessageId.ATTACKER_SIDE_FULL);
  697. else if ((type == SiegeSide.DEFENDER || type == SiegeSide.PENDING || type == SiegeSide.OWNER) && (getDefenderClans().size() + getPendingClans().size() >= Config.MAX_DEFENDERS_NUMBER))
  698. sm = SystemMessage.getSystemMessage(SystemMessageId.DEFENDER_SIDE_FULL);
  699. else
  700. return true;
  701.  
  702. player.sendPacket(sm);
  703. return false;
  704. }
  705.  
  706. /**
  707. * @param clan The L2Clan of the player trying to register
  708. * @return true if the clan has already registered to a siege for the same day.
  709. */
  710. public boolean checkIfAlreadyRegisteredForSameDay(Clan clan)
  711. {
  712. for (Castle castle : CastleManager.getInstance().getCastles())
  713. {
  714. final Siege siege = castle.getSiege();
  715. if (siege == this)
  716. continue;
  717.  
  718. if (siege.getSiegeDate().get(Calendar.DAY_OF_WEEK) == getSiegeDate().get(Calendar.DAY_OF_WEEK) && siege.checkSides(clan))
  719. return true;
  720. }
  721. return false;
  722. }
  723.  
  724. /** Remove all spawned towers. */
  725. private void removeTowers()
  726. {
  727. for (FlameTower ct : _flameTowers)
  728. ct.deleteMe();
  729.  
  730. for (ControlTower ct : _controlTowers)
  731. ct.deleteMe();
  732.  
  733. for (Npc ct : _destroyedTowers)
  734. ct.deleteMe();
  735.  
  736. _flameTowers.clear();
  737. _controlTowers.clear();
  738. _destroyedTowers.clear();
  739. }
  740.  
  741. /**
  742. * Save castle siege related to database.
  743. * @param launchTask : if true, launch the start siege task.
  744. */
  745. private void saveCastleSiege(boolean launchTask)
  746. {
  747. // Set the next siege date in 2 weeks from now.
  748. setNextSiegeDate();
  749.  
  750. // You can edit time anew.
  751. getCastle().setTimeRegistrationOver(false);
  752.  
  753. // Save the new date.
  754. saveSiegeDate();
  755.  
  756. // Prepare start siege task.
  757. if (launchTask)
  758. startAutoTask();
  759.  
  760. _log.info("New date for " + getCastle().getName() + " siege: " + getCastle().getSiegeDate().getTime());
  761. }
  762.  
  763. /**
  764. * Save siege date to database.
  765. */
  766. private void saveSiegeDate()
  767. {
  768. if (_siegeTask != null)
  769. {
  770. _siegeTask.cancel(true);
  771. _siegeTask = ThreadPool.schedule(new SiegeTask(getCastle()), 1000);
  772. }
  773.  
  774. try (Connection con = L2DatabaseFactory.getInstance().getConnection();
  775. PreparedStatement ps = con.prepareStatement(UPDATE_SIEGE_INFOS))
  776. {
  777. ps.setLong(1, getSiegeDate().getTimeInMillis());
  778. ps.setString(2, String.valueOf(isTimeRegistrationOver()));
  779. ps.setInt(3, getCastle().getCastleId());
  780. ps.executeUpdate();
  781. }
  782. catch (Exception e)
  783. {
  784. _log.log(Level.SEVERE, "Error saving siege date.", e);
  785. }
  786. }
  787.  
  788. /**
  789. * Save registration to database.
  790. * @param clan : The L2Clan of player.
  791. * @param type
  792. */
  793. public void registerClan(Clan clan, SiegeSide type)
  794. {
  795. if (clan.hasCastle())
  796. return;
  797.  
  798. switch (type)
  799. {
  800. case DEFENDER:
  801. case PENDING:
  802. case OWNER:
  803. if (getDefenderClans().size() + getPendingClans().size() >= Config.MAX_DEFENDERS_NUMBER)
  804. return;
  805. break;
  806.  
  807. default:
  808. if (getAttackerClans().size() >= Config.MAX_ATTACKERS_NUMBER)
  809. return;
  810. break;
  811. }
  812.  
  813. try (Connection con = L2DatabaseFactory.getInstance().getConnection();
  814. PreparedStatement ps = con.prepareStatement(ADD_OR_UPDATE_SIEGE_CLAN))
  815. {
  816. ps.setInt(1, clan.getClanId());
  817. ps.setInt(2, getCastle().getCastleId());
  818. ps.setString(3, type.toString());
  819. ps.executeUpdate();
  820. }
  821. catch (Exception e)
  822. {
  823. _log.log(Level.SEVERE, "Error registering clan on siege.", e);
  824. }
  825.  
  826. _registeredClans.put(clan, type);
  827. }
  828.  
  829. /**
  830. * Set the date for the next siege.
  831. */
  832. private void setNextSiegeDate()
  833. {
  834. final Calendar siegeDate = getCastle().getSiegeDate();
  835. if (siegeDate.getTimeInMillis() < System.currentTimeMillis())
  836. siegeDate.setTimeInMillis(System.currentTimeMillis());
  837.  
  838. switch (getCastle().getCastleId())
  839. {
  840. case 1:
  841. case 2:
  842. case 3:
  843. case 4:
  844. case 5:
  845. siegeDate.set(Calendar.DAY_OF_WEEK, Calendar.SATURDAY);
  846. break;
  847. case 6:
  848. case 7:
  849. case 8:
  850. case 9:
  851. siegeDate.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
  852. break;
  853.  
  854. default:
  855. siegeDate.set(Calendar.DAY_OF_WEEK, Calendar.SATURDAY);
  856. break;
  857. }
  858.  
  859. // Set next siege date if siege has passed ; add 14 days (2 weeks).
  860. if (siegeDate.getTimeInMillis() <= System.currentTimeMillis())
  861. siegeDate.add(Calendar.WEEK_OF_YEAR, 1);
  862.  
  863. // Set default hour to 18:00. This can be changed - only once - by the castle leader via the chamberlain.
  864. siegeDate.set(Calendar.HOUR_OF_DAY, 19);
  865. siegeDate.set(Calendar.MINUTE, 0);
  866. siegeDate.set(Calendar.SECOND, 0);
  867. siegeDate.set(Calendar.MILLISECOND, 0);
  868.  
  869. // Send message and allow registration for next siege.
  870. Broadcast.toAllOnlinePlayers(SystemMessage.getSystemMessage(SystemMessageId.S1_ANNOUNCED_SIEGE_TIME).addString(getCastle().getName()));
  871. changeStatus(SiegeStatus.REGISTRATION_OPENED);
  872. }
  873.  
  874. /**
  875. * Spawn control towers.
  876. */
  877. private void spawnControlTowers()
  878. {
  879. for (TowerSpawnLocation ts : getCastle().getControlTowers())
  880. {
  881. try
  882. {
  883. final L2Spawn spawn = new L2Spawn(NpcData.getInstance().getTemplate(ts.getId()));
  884. spawn.setLoc(ts);
  885.  
  886. final ControlTower tower = (ControlTower) spawn.doSpawn(false);
  887. tower.setCastle(getCastle());
  888.  
  889. _controlTowers.add(tower);
  890. }
  891. catch (Exception e)
  892. {
  893. _log.warning(getClass().getName() + ": Cannot spawn control tower! " + e);
  894. }
  895. }
  896. }
  897.  
  898. /**
  899. * Spawn flame towers.
  900. */
  901. private void spawnFlameTowers()
  902. {
  903. for (TowerSpawnLocation ts : getCastle().getFlameTowers())
  904. {
  905. try
  906. {
  907. final L2Spawn spawn = new L2Spawn(NpcData.getInstance().getTemplate(ts.getId()));
  908. spawn.setLoc(ts);
  909.  
  910. final FlameTower tower = (FlameTower) spawn.doSpawn(false);
  911. tower.setCastle(getCastle());
  912. tower.setUpgradeLevel(ts.getUpgradeLevel());
  913. tower.setZoneList(ts.getZoneList());
  914.  
  915. _flameTowers.add(tower);
  916. }
  917. catch (Exception e)
  918. {
  919. _log.warning(getClass().getName() + ": Cannot spawn flame tower! " + e);
  920. }
  921. }
  922. }
  923.  
  924. public final Castle getCastle()
  925. {
  926. return _castle;
  927. }
  928.  
  929. public final boolean isInProgress()
  930. {
  931. return _siegeStatus == SiegeStatus.IN_PROGRESS;
  932. }
  933.  
  934. public final boolean isRegistrationOver()
  935. {
  936. return _siegeStatus != SiegeStatus.REGISTRATION_OPENED;
  937. }
  938.  
  939. public final boolean isTimeRegistrationOver()
  940. {
  941. return getCastle().isTimeRegistrationOver();
  942. }
  943.  
  944. /**
  945. * @return siege registration end date, which always equals siege date minus one day.
  946. */
  947. public final long getSiegeRegistrationEndDate()
  948. {
  949. return getCastle().getSiegeDate().getTimeInMillis() - 86400000;
  950. }
  951.  
  952. public void endTimeRegistration(boolean automatic)
  953. {
  954. getCastle().setTimeRegistrationOver(true);
  955. if (!automatic)
  956. saveSiegeDate();
  957. }
  958.  
  959. public int getControlTowerCount()
  960. {
  961. return (int) _controlTowers.stream().filter(lc -> lc.isActive()).count();
  962. }
  963.  
  964. public List<Npc> getDestroyedTowers()
  965. {
  966. return _destroyedTowers;
  967. }
  968.  
  969. public class EndSiegeTask implements Runnable
  970. {
  971. private final Castle _castle;
  972.  
  973. public EndSiegeTask(Castle castle)
  974. {
  975. _castle = castle;
  976. }
  977.  
  978. @Override
  979. public void run()
  980. {
  981. if (!isInProgress())
  982. return;
  983.  
  984. final long timeRemaining = _siegeEndDate.getTimeInMillis() - Calendar.getInstance().getTimeInMillis();
  985. if (timeRemaining > 3600000)
  986. {
  987. announceToPlayers(SystemMessage.getSystemMessage(SystemMessageId.S1_HOURS_UNTIL_SIEGE_CONCLUSION).addNumber(2), true);
  988. ThreadPool.schedule(new EndSiegeTask(_castle), timeRemaining - 3600000);
  989. }
  990. else if (timeRemaining <= 3600000 && timeRemaining > 600000)
  991. {
  992. announceToPlayers(SystemMessage.getSystemMessage(SystemMessageId.S1_MINUTES_UNTIL_SIEGE_CONCLUSION).addNumber(Math.round(timeRemaining / 60000)), true);
  993. ThreadPool.schedule(new EndSiegeTask(_castle), timeRemaining - 600000);
  994. }
  995. else if (timeRemaining <= 600000 && timeRemaining > 300000)
  996. {
  997. announceToPlayers(SystemMessage.getSystemMessage(SystemMessageId.S1_MINUTES_UNTIL_SIEGE_CONCLUSION).addNumber(Math.round(timeRemaining / 60000)), true);
  998. ThreadPool.schedule(new EndSiegeTask(_castle), timeRemaining - 300000);
  999. }
  1000. else if (timeRemaining <= 300000 && timeRemaining > 10000)
  1001. {
  1002. announceToPlayers(SystemMessage.getSystemMessage(SystemMessageId.S1_MINUTES_UNTIL_SIEGE_CONCLUSION).addNumber(Math.round(timeRemaining / 60000)), true);
  1003. ThreadPool.schedule(new EndSiegeTask(_castle), timeRemaining - 10000);
  1004. }
  1005. else if (timeRemaining <= 10000 && timeRemaining > 0)
  1006. {
  1007. announceToPlayers(SystemMessage.getSystemMessage(SystemMessageId.CASTLE_SIEGE_S1_SECONDS_LEFT).addNumber(Math.round(timeRemaining / 1000)), true);
  1008. ThreadPool.schedule(new EndSiegeTask(_castle), timeRemaining);
  1009. }
  1010. else
  1011. _castle.getSiege().endSiege();
  1012. }
  1013. }
  1014.  
  1015. private class SiegeTask implements Runnable
  1016. {
  1017. private final Castle _castle;
  1018.  
  1019. public SiegeTask(Castle castle)
  1020. {
  1021. _castle = castle;
  1022. }
  1023.  
  1024. @Override
  1025. public void run()
  1026. {
  1027. _siegeTask.cancel(false);
  1028. if (isInProgress())
  1029. return;
  1030.  
  1031. if (!isTimeRegistrationOver())
  1032. {
  1033. final long regTimeRemaining = getSiegeRegistrationEndDate() - Calendar.getInstance().getTimeInMillis();
  1034. if (regTimeRemaining > 0)
  1035. {
  1036. _siegeTask = ThreadPool.schedule(new SiegeTask(_castle), regTimeRemaining);
  1037. return;
  1038. }
  1039.  
  1040. endTimeRegistration(true);
  1041. }
  1042.  
  1043. final long timeRemaining = getSiegeDate().getTimeInMillis() - Calendar.getInstance().getTimeInMillis();
  1044.  
  1045. if (timeRemaining > 86400000)
  1046. _siegeTask = ThreadPool.schedule(new SiegeTask(_castle), timeRemaining - 86400000);
  1047. else if (timeRemaining <= 86400000 && timeRemaining > 13600000)
  1048. {
  1049. Broadcast.toAllOnlinePlayers(SystemMessage.getSystemMessage(SystemMessageId.REGISTRATION_TERM_FOR_S1_ENDED).addString(getCastle().getName()));
  1050. changeStatus(SiegeStatus.REGISTRATION_OVER);
  1051. clearPendingClans();
  1052. _siegeTask = ThreadPool.schedule(new SiegeTask(_castle), timeRemaining - 13600000);
  1053. }
  1054. else if (timeRemaining <= 13600000 && timeRemaining > 600000)
  1055. _siegeTask = ThreadPool.schedule(new SiegeTask(_castle), timeRemaining - 600000);
  1056. else if (timeRemaining <= 600000 && timeRemaining > 300000)
  1057. _siegeTask = ThreadPool.schedule(new SiegeTask(_castle), timeRemaining - 300000);
  1058. else if (timeRemaining <= 300000 && timeRemaining > 10000)
  1059. _siegeTask = ThreadPool.schedule(new SiegeTask(_castle), timeRemaining - 10000);
  1060. else if (timeRemaining <= 10000 && timeRemaining > 0)
  1061. _siegeTask = ThreadPool.schedule(new SiegeTask(_castle), timeRemaining);
  1062. else
  1063. _castle.getSiege().startSiege();
  1064. }
  1065. }
  1066.  
  1067. public void addQuestEvent(Quest quest)
  1068. {
  1069. if (_questEvents.isEmpty())
  1070. _questEvents = new ArrayList<>(3);
  1071.  
  1072. _questEvents.add(quest);
  1073. }
  1074.  
  1075. public List<Quest> getQuestEvents()
  1076. {
  1077. return _questEvents;
  1078. }
  1079.  
  1080. public SiegeStatus getStatus()
  1081. {
  1082. return _siegeStatus;
  1083. }
  1084.  
  1085. protected void changeStatus(SiegeStatus status)
  1086. {
  1087. _siegeStatus = status;
  1088.  
  1089. for (Quest quest : _questEvents)
  1090. quest.onSiegeEvent();
  1091. }
  1092. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement