CastleManorManager.java 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821
  1. /*
  2. * Copyright (C) 2004-2015 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.sql.Connection;
  21. import java.sql.PreparedStatement;
  22. import java.sql.ResultSet;
  23. import java.text.SimpleDateFormat;
  24. import java.util.ArrayList;
  25. import java.util.Calendar;
  26. import java.util.Collection;
  27. import java.util.Collections;
  28. import java.util.HashMap;
  29. import java.util.List;
  30. import java.util.Map;
  31. import java.util.Set;
  32. import java.util.concurrent.TimeUnit;
  33. import java.util.stream.Collectors;
  34. import org.w3c.dom.Document;
  35. import org.w3c.dom.NamedNodeMap;
  36. import org.w3c.dom.Node;
  37. import com.l2jserver.Config;
  38. import com.l2jserver.commons.database.pool.impl.ConnectionFactory;
  39. import com.l2jserver.gameserver.ThreadPoolManager;
  40. import com.l2jserver.gameserver.enums.ManorMode;
  41. import com.l2jserver.gameserver.model.CropProcure;
  42. import com.l2jserver.gameserver.model.L2Clan;
  43. import com.l2jserver.gameserver.model.L2ClanMember;
  44. import com.l2jserver.gameserver.model.L2Seed;
  45. import com.l2jserver.gameserver.model.SeedProduction;
  46. import com.l2jserver.gameserver.model.StatsSet;
  47. import com.l2jserver.gameserver.model.entity.Castle;
  48. import com.l2jserver.gameserver.model.interfaces.IStorable;
  49. import com.l2jserver.gameserver.model.itemcontainer.ItemContainer;
  50. import com.l2jserver.gameserver.network.SystemMessageId;
  51. import com.l2jserver.util.Rnd;
  52. import com.l2jserver.util.data.xml.IXmlReader;
  53. /**
  54. * Castle manor system.
  55. * @author malyelfik
  56. */
  57. public final class CastleManorManager implements IXmlReader, IStorable
  58. {
  59. // SQL queries
  60. private static final String INSERT_PRODUCT = "INSERT INTO castle_manor_production VALUES (?, ?, ?, ?, ?, ?)";
  61. private static final String INSERT_CROP = "INSERT INTO castle_manor_procure VALUES (?, ?, ?, ?, ?, ?, ?)";
  62. // Current manor status
  63. private ManorMode _mode = ManorMode.APPROVED;
  64. // Temporary date
  65. private Calendar _nextModeChange = null;
  66. // Seeds holder
  67. private static final Map<Integer, L2Seed> _seeds = new HashMap<>();
  68. // Manor period settings
  69. private final Map<Integer, List<CropProcure>> _procure = new HashMap<>();
  70. private final Map<Integer, List<CropProcure>> _procureNext = new HashMap<>();
  71. private final Map<Integer, List<SeedProduction>> _production = new HashMap<>();
  72. private final Map<Integer, List<SeedProduction>> _productionNext = new HashMap<>();
  73. public CastleManorManager()
  74. {
  75. if (Config.ALLOW_MANOR)
  76. {
  77. load(); // Load seed data (XML)
  78. loadDb(); // Load castle manor data (DB)
  79. // Set mode and start timer
  80. final Calendar currentTime = Calendar.getInstance();
  81. final int hour = currentTime.get(Calendar.HOUR_OF_DAY);
  82. final int min = currentTime.get(Calendar.MINUTE);
  83. final int maintenanceMin = Config.ALT_MANOR_REFRESH_MIN + Config.ALT_MANOR_MAINTENANCE_MIN;
  84. if (((hour >= Config.ALT_MANOR_REFRESH_TIME) && (min >= maintenanceMin)) || (hour < Config.ALT_MANOR_APPROVE_TIME) || ((hour == Config.ALT_MANOR_APPROVE_TIME) && (min <= Config.ALT_MANOR_APPROVE_MIN)))
  85. {
  86. _mode = ManorMode.MODIFIABLE;
  87. }
  88. else if ((hour == Config.ALT_MANOR_REFRESH_TIME) && ((min >= Config.ALT_MANOR_REFRESH_MIN) && (min < maintenanceMin)))
  89. {
  90. _mode = ManorMode.MAINTENANCE;
  91. }
  92. // Schedule mode change
  93. scheduleModeChange();
  94. // Schedule autosave
  95. if (!Config.ALT_MANOR_SAVE_ALL_ACTIONS)
  96. {
  97. ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(this::storeMe, Config.ALT_MANOR_SAVE_PERIOD_RATE, Config.ALT_MANOR_SAVE_PERIOD_RATE, TimeUnit.HOURS);
  98. }
  99. // Send debug message
  100. if (Config.DEBUG)
  101. {
  102. LOGGER.info(getClass().getSimpleName() + ": Current mode " + _mode.toString());
  103. }
  104. }
  105. else
  106. {
  107. _mode = ManorMode.DISABLED;
  108. LOGGER.info(getClass().getSimpleName() + ": Manor system is deactivated.");
  109. }
  110. }
  111. @Override
  112. public final void load()
  113. {
  114. parseDatapackFile("data/seeds.xml");
  115. LOGGER.info(getClass().getSimpleName() + ": Loaded " + _seeds.size() + " seeds.");
  116. }
  117. @Override
  118. public final void parseDocument(Document doc)
  119. {
  120. StatsSet set;
  121. NamedNodeMap attrs;
  122. Node att;
  123. for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
  124. {
  125. if ("list".equalsIgnoreCase(n.getNodeName()))
  126. {
  127. for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
  128. {
  129. if ("castle".equalsIgnoreCase(d.getNodeName()))
  130. {
  131. final int castleId = parseInteger(d.getAttributes(), "id");
  132. for (Node c = d.getFirstChild(); c != null; c = c.getNextSibling())
  133. {
  134. if ("crop".equalsIgnoreCase(c.getNodeName()))
  135. {
  136. set = new StatsSet();
  137. set.set("castleId", castleId);
  138. attrs = c.getAttributes();
  139. for (int i = 0; i < attrs.getLength(); i++)
  140. {
  141. att = attrs.item(i);
  142. set.set(att.getNodeName(), att.getNodeValue());
  143. }
  144. _seeds.put(set.getInt("seedId"), new L2Seed(set));
  145. }
  146. }
  147. }
  148. }
  149. }
  150. }
  151. }
  152. private final void loadDb()
  153. {
  154. try (Connection con = ConnectionFactory.getInstance().getConnection();
  155. PreparedStatement stProduction = con.prepareStatement("SELECT * FROM castle_manor_production WHERE castle_id=?");
  156. PreparedStatement stProcure = con.prepareStatement("SELECT * FROM castle_manor_procure WHERE castle_id=?"))
  157. {
  158. for (Castle castle : CastleManager.getInstance().getCastles())
  159. {
  160. final int castleId = castle.getResidenceId();
  161. // Clear params
  162. stProduction.clearParameters();
  163. stProcure.clearParameters();
  164. // Seed production
  165. final List<SeedProduction> pCurrent = new ArrayList<>();
  166. final List<SeedProduction> pNext = new ArrayList<>();
  167. stProduction.setInt(1, castleId);
  168. try (ResultSet rs = stProduction.executeQuery())
  169. {
  170. while (rs.next())
  171. {
  172. final int seedId = rs.getInt("seed_id");
  173. if (_seeds.containsKey(seedId)) // Don't load unknown seeds
  174. {
  175. final SeedProduction sp = new SeedProduction(seedId, rs.getLong("amount"), rs.getLong("price"), rs.getInt("start_amount"));
  176. if (rs.getBoolean("next_period"))
  177. {
  178. pNext.add(sp);
  179. }
  180. else
  181. {
  182. pCurrent.add(sp);
  183. }
  184. }
  185. else
  186. {
  187. LOGGER.warning(getClass().getSimpleName() + ": Unknown seed id: " + seedId + "!");
  188. }
  189. }
  190. }
  191. _production.put(castleId, pCurrent);
  192. _productionNext.put(castleId, pNext);
  193. // Seed procure
  194. final List<CropProcure> current = new ArrayList<>();
  195. final List<CropProcure> next = new ArrayList<>();
  196. stProcure.setInt(1, castleId);
  197. try (ResultSet rs = stProcure.executeQuery())
  198. {
  199. final Set<Integer> cropIds = getCropIds();
  200. while (rs.next())
  201. {
  202. final int cropId = rs.getInt("crop_id");
  203. if (cropIds.contains(cropId)) // Don't load unknown crops
  204. {
  205. final CropProcure cp = new CropProcure(cropId, rs.getLong("amount"), rs.getInt("reward_type"), rs.getLong("start_amount"), rs.getLong("price"));
  206. if (rs.getBoolean("next_period"))
  207. {
  208. next.add(cp);
  209. }
  210. else
  211. {
  212. current.add(cp);
  213. }
  214. }
  215. else
  216. {
  217. LOGGER.warning(getClass().getSimpleName() + ": Unknown crop id: " + cropId + "!");
  218. }
  219. }
  220. }
  221. _procure.put(castleId, current);
  222. _procureNext.put(castleId, next);
  223. }
  224. LOGGER.info(getClass().getSimpleName() + ": Manor data loaded.");
  225. }
  226. catch (Exception e)
  227. {
  228. LOGGER.warning(getClass().getSimpleName() + ": Unable to load manor data! " + e.getMessage());
  229. }
  230. }
  231. // -------------------------------------------------------
  232. // Manor methods
  233. // -------------------------------------------------------
  234. private final void scheduleModeChange()
  235. {
  236. // Calculate next mode change
  237. _nextModeChange = Calendar.getInstance();
  238. _nextModeChange.set(Calendar.SECOND, 0);
  239. switch (_mode)
  240. {
  241. case MODIFIABLE:
  242. _nextModeChange.set(Calendar.HOUR_OF_DAY, Config.ALT_MANOR_APPROVE_TIME);
  243. _nextModeChange.set(Calendar.MINUTE, Config.ALT_MANOR_APPROVE_MIN);
  244. if (_nextModeChange.before(Calendar.getInstance()))
  245. {
  246. _nextModeChange.add(Calendar.DATE, 1);
  247. }
  248. break;
  249. case MAINTENANCE:
  250. _nextModeChange.set(Calendar.HOUR_OF_DAY, Config.ALT_MANOR_REFRESH_TIME);
  251. _nextModeChange.set(Calendar.MINUTE, Config.ALT_MANOR_REFRESH_MIN + Config.ALT_MANOR_MAINTENANCE_MIN);
  252. break;
  253. case APPROVED:
  254. _nextModeChange.set(Calendar.HOUR_OF_DAY, Config.ALT_MANOR_REFRESH_TIME);
  255. _nextModeChange.set(Calendar.MINUTE, Config.ALT_MANOR_REFRESH_MIN);
  256. break;
  257. }
  258. // Schedule mode change
  259. ThreadPoolManager.getInstance().scheduleGeneral(this::changeMode, (_nextModeChange.getTimeInMillis() - System.currentTimeMillis()));
  260. }
  261. public final void changeMode()
  262. {
  263. switch (_mode)
  264. {
  265. case APPROVED:
  266. {
  267. // Change mode
  268. _mode = ManorMode.MAINTENANCE;
  269. // Update manor period
  270. for (Castle castle : CastleManager.getInstance().getCastles())
  271. {
  272. final L2Clan owner = castle.getOwner();
  273. if (owner == null)
  274. {
  275. continue;
  276. }
  277. final int castleId = castle.getResidenceId();
  278. final ItemContainer cwh = owner.getWarehouse();
  279. for (CropProcure crop : _procure.get(castleId))
  280. {
  281. if (crop.getStartAmount() > 0)
  282. {
  283. // Adding bought crops to clan warehouse
  284. if (crop.getStartAmount() != crop.getAmount())
  285. {
  286. long count = (long) ((crop.getStartAmount() - crop.getAmount()) * 0.9);
  287. if ((count < 1) && (Rnd.nextInt(99) < 90))
  288. {
  289. count = 1;
  290. }
  291. if (count > 0)
  292. {
  293. cwh.addItem("Manor", getSeedByCrop(crop.getId()).getMatureId(), count, null, null);
  294. }
  295. }
  296. // Reserved and not used money giving back to treasury
  297. if (crop.getAmount() > 0)
  298. {
  299. castle.addToTreasuryNoTax(crop.getAmount() * crop.getPrice());
  300. }
  301. }
  302. }
  303. // Change next period to current and prepare next period data
  304. final List<SeedProduction> _nextProduction = _productionNext.get(castleId);
  305. final List<CropProcure> _nextProcure = _procureNext.get(castleId);
  306. _production.put(castleId, _nextProduction);
  307. _procure.put(castleId, _nextProcure);
  308. if (castle.getTreasury() < getManorCost(castleId, false))
  309. {
  310. _productionNext.put(castleId, Collections.emptyList());
  311. _procureNext.put(castleId, Collections.emptyList());
  312. }
  313. else
  314. {
  315. final List<SeedProduction> production = new ArrayList<>(_nextProduction);
  316. for (SeedProduction s : production)
  317. {
  318. s.setAmount(s.getStartAmount());
  319. }
  320. _productionNext.put(castleId, production);
  321. final List<CropProcure> procure = new ArrayList<>(_nextProcure);
  322. for (CropProcure cr : procure)
  323. {
  324. cr.setAmount(cr.getStartAmount());
  325. }
  326. _procureNext.put(castleId, procure);
  327. }
  328. }
  329. // Save changes
  330. storeMe();
  331. break;
  332. }
  333. case MAINTENANCE:
  334. {
  335. // Notify clan leader about manor mode change
  336. for (Castle castle : CastleManager.getInstance().getCastles())
  337. {
  338. final L2Clan owner = castle.getOwner();
  339. if (owner != null)
  340. {
  341. final L2ClanMember clanLeader = owner.getLeader();
  342. if ((clanLeader != null) && clanLeader.isOnline())
  343. {
  344. clanLeader.getPlayerInstance().sendPacket(SystemMessageId.THE_MANOR_INFORMATION_HAS_BEEN_UPDATED);
  345. }
  346. }
  347. }
  348. _mode = ManorMode.MODIFIABLE;
  349. break;
  350. }
  351. case MODIFIABLE:
  352. {
  353. _mode = ManorMode.APPROVED;
  354. for (Castle castle : CastleManager.getInstance().getCastles())
  355. {
  356. final L2Clan owner = castle.getOwner();
  357. if (owner == null)
  358. {
  359. continue;
  360. }
  361. int slots = 0;
  362. final int castleId = castle.getResidenceId();
  363. final ItemContainer cwh = owner.getWarehouse();
  364. for (CropProcure crop : _procureNext.get(castleId))
  365. {
  366. if ((crop.getStartAmount() > 0) && (cwh.getItemsByItemId(getSeedByCrop(crop.getId()).getMatureId()) == null))
  367. {
  368. slots++;
  369. }
  370. }
  371. final long manorCost = getManorCost(castleId, true);
  372. if (!cwh.validateCapacity(slots) && (castle.getTreasury() < manorCost))
  373. {
  374. _productionNext.get(castleId).clear();
  375. _procureNext.get(castleId).clear();
  376. // Notify clan leader
  377. final L2ClanMember clanLeader = owner.getLeader();
  378. if ((clanLeader != null) && clanLeader.isOnline())
  379. {
  380. clanLeader.getPlayerInstance().sendPacket(SystemMessageId.THE_AMOUNT_IS_NOT_SUFFICIENT_AND_SO_THE_MANOR_IS_NOT_IN_OPERATION);
  381. }
  382. }
  383. else
  384. {
  385. castle.addToTreasuryNoTax(-manorCost);
  386. }
  387. }
  388. // Store changes
  389. if (Config.ALT_MANOR_SAVE_ALL_ACTIONS)
  390. {
  391. storeMe();
  392. }
  393. break;
  394. }
  395. }
  396. scheduleModeChange();
  397. if (Config.DEBUG)
  398. {
  399. LOGGER.info(getClass().getName() + ": Manor mode changed to " + _mode.toString() + "!");
  400. }
  401. }
  402. public final void setNextSeedProduction(List<SeedProduction> list, int castleId)
  403. {
  404. _productionNext.put(castleId, list);
  405. if (Config.ALT_MANOR_SAVE_ALL_ACTIONS)
  406. {
  407. try (Connection con = ConnectionFactory.getInstance().getConnection();
  408. PreparedStatement dps = con.prepareStatement("DELETE FROM castle_manor_production WHERE castle_id = ? AND next_period = 1");
  409. PreparedStatement ips = con.prepareStatement(INSERT_PRODUCT))
  410. {
  411. // Delete old data
  412. dps.setInt(1, castleId);
  413. dps.executeUpdate();
  414. // Insert new data
  415. if (!list.isEmpty())
  416. {
  417. for (SeedProduction sp : list)
  418. {
  419. ips.setInt(1, castleId);
  420. ips.setInt(2, sp.getId());
  421. ips.setLong(3, sp.getAmount());
  422. ips.setLong(4, sp.getStartAmount());
  423. ips.setLong(5, sp.getPrice());
  424. ips.setBoolean(6, true);
  425. ips.addBatch();
  426. }
  427. ips.executeBatch();
  428. }
  429. }
  430. catch (Exception e)
  431. {
  432. LOGGER.severe(getClass().getSimpleName() + ": Unable to store manor data! " + e.getMessage());
  433. }
  434. }
  435. }
  436. public final void setNextCropProcure(List<CropProcure> list, int castleId)
  437. {
  438. _procureNext.put(castleId, list);
  439. if (Config.ALT_MANOR_SAVE_ALL_ACTIONS)
  440. {
  441. try (Connection con = ConnectionFactory.getInstance().getConnection();
  442. PreparedStatement dps = con.prepareStatement("DELETE FROM castle_manor_procure WHERE castle_id = ? AND next_period = 1");
  443. PreparedStatement ips = con.prepareStatement(INSERT_CROP))
  444. {
  445. // Delete old data
  446. dps.setInt(1, castleId);
  447. dps.executeUpdate();
  448. // Insert new data
  449. if (!list.isEmpty())
  450. {
  451. for (CropProcure cp : list)
  452. {
  453. ips.setInt(1, castleId);
  454. ips.setInt(2, cp.getId());
  455. ips.setLong(3, cp.getAmount());
  456. ips.setLong(4, cp.getStartAmount());
  457. ips.setLong(5, cp.getPrice());
  458. ips.setInt(6, cp.getReward());
  459. ips.setBoolean(7, true);
  460. ips.addBatch();
  461. }
  462. ips.executeBatch();
  463. }
  464. }
  465. catch (Exception e)
  466. {
  467. LOGGER.severe(getClass().getSimpleName() + ": Unable to store manor data! " + e.getMessage());
  468. }
  469. }
  470. }
  471. public final void updateCurrentProduction(int castleId, Collection<SeedProduction> items)
  472. {
  473. try (Connection con = ConnectionFactory.getInstance().getConnection();
  474. PreparedStatement ps = con.prepareStatement("UPDATE castle_manor_production SET amount = ? WHERE castle_id = ? AND seed_id = ? AND next_period = 0"))
  475. {
  476. for (SeedProduction sp : items)
  477. {
  478. ps.setLong(1, sp.getAmount());
  479. ps.setInt(2, castleId);
  480. ps.setInt(3, sp.getId());
  481. ps.addBatch();
  482. }
  483. ps.executeBatch();
  484. }
  485. catch (Exception e)
  486. {
  487. LOGGER.info(getClass().getSimpleName() + ": Unable to store manor data! " + e.getMessage());
  488. }
  489. }
  490. public final void updateCurrentProcure(int castleId, Collection<CropProcure> items)
  491. {
  492. try (Connection con = ConnectionFactory.getInstance().getConnection();
  493. PreparedStatement ps = con.prepareStatement("UPDATE castle_manor_procure SET amount = ? WHERE castle_id = ? AND crop_id = ? AND next_period = 0"))
  494. {
  495. for (CropProcure sp : items)
  496. {
  497. ps.setLong(1, sp.getAmount());
  498. ps.setInt(2, castleId);
  499. ps.setInt(3, sp.getId());
  500. ps.addBatch();
  501. }
  502. ps.executeBatch();
  503. }
  504. catch (Exception e)
  505. {
  506. LOGGER.info(getClass().getSimpleName() + ": Unable to store manor data! " + e.getMessage());
  507. }
  508. }
  509. public final List<SeedProduction> getSeedProduction(int castleId, boolean nextPeriod)
  510. {
  511. return (nextPeriod) ? _productionNext.get(castleId) : _production.get(castleId);
  512. }
  513. public final SeedProduction getSeedProduct(int castleId, int seedId, boolean nextPeriod)
  514. {
  515. for (SeedProduction sp : getSeedProduction(castleId, nextPeriod))
  516. {
  517. if (sp.getId() == seedId)
  518. {
  519. return sp;
  520. }
  521. }
  522. return null;
  523. }
  524. public final List<CropProcure> getCropProcure(int castleId, boolean nextPeriod)
  525. {
  526. return (nextPeriod) ? _procureNext.get(castleId) : _procure.get(castleId);
  527. }
  528. public final CropProcure getCropProcure(int castleId, int cropId, boolean nextPeriod)
  529. {
  530. for (CropProcure cp : getCropProcure(castleId, nextPeriod))
  531. {
  532. if (cp.getId() == cropId)
  533. {
  534. return cp;
  535. }
  536. }
  537. return null;
  538. }
  539. public final long getManorCost(int castleId, boolean nextPeriod)
  540. {
  541. final List<CropProcure> procure = getCropProcure(castleId, nextPeriod);
  542. final List<SeedProduction> production = getSeedProduction(castleId, nextPeriod);
  543. long total = 0;
  544. for (SeedProduction seed : production)
  545. {
  546. final L2Seed s = getSeed(seed.getId());
  547. total += (s == null) ? 1 : (s.getSeedReferencePrice() * seed.getStartAmount());
  548. }
  549. for (CropProcure crop : procure)
  550. {
  551. total += (crop.getPrice() * crop.getStartAmount());
  552. }
  553. return total;
  554. }
  555. @Override
  556. public final boolean storeMe()
  557. {
  558. try (Connection con = ConnectionFactory.getInstance().getConnection();
  559. PreparedStatement ds = con.prepareStatement("DELETE FROM castle_manor_production");
  560. PreparedStatement is = con.prepareStatement(INSERT_PRODUCT);
  561. PreparedStatement dp = con.prepareStatement("DELETE FROM castle_manor_procure");
  562. PreparedStatement ip = con.prepareStatement(INSERT_CROP))
  563. {
  564. // Delete old seeds
  565. ds.executeUpdate();
  566. // Current production
  567. for (Map.Entry<Integer, List<SeedProduction>> entry : _production.entrySet())
  568. {
  569. for (SeedProduction sp : entry.getValue())
  570. {
  571. is.setInt(1, entry.getKey());
  572. is.setInt(2, sp.getId());
  573. is.setLong(3, sp.getAmount());
  574. is.setLong(4, sp.getStartAmount());
  575. is.setLong(5, sp.getPrice());
  576. is.setBoolean(6, false);
  577. is.addBatch();
  578. }
  579. }
  580. // Next production
  581. for (Map.Entry<Integer, List<SeedProduction>> entry : _productionNext.entrySet())
  582. {
  583. for (SeedProduction sp : entry.getValue())
  584. {
  585. is.setInt(1, entry.getKey());
  586. is.setInt(2, sp.getId());
  587. is.setLong(3, sp.getAmount());
  588. is.setLong(4, sp.getStartAmount());
  589. is.setLong(5, sp.getPrice());
  590. is.setBoolean(6, true);
  591. is.addBatch();
  592. }
  593. }
  594. // Execute production batch
  595. is.executeBatch();
  596. // Delete old procure
  597. dp.executeUpdate();
  598. // Current procure
  599. for (Map.Entry<Integer, List<CropProcure>> entry : _procure.entrySet())
  600. {
  601. for (CropProcure cp : entry.getValue())
  602. {
  603. ip.setInt(1, entry.getKey());
  604. ip.setInt(2, cp.getId());
  605. ip.setLong(3, cp.getAmount());
  606. ip.setLong(4, cp.getStartAmount());
  607. ip.setLong(5, cp.getPrice());
  608. ip.setInt(6, cp.getReward());
  609. ip.setBoolean(7, false);
  610. ip.addBatch();
  611. }
  612. }
  613. // Next procure
  614. for (Map.Entry<Integer, List<CropProcure>> entry : _procureNext.entrySet())
  615. {
  616. for (CropProcure cp : entry.getValue())
  617. {
  618. ip.setInt(1, entry.getKey());
  619. ip.setInt(2, cp.getId());
  620. ip.setLong(3, cp.getAmount());
  621. ip.setLong(4, cp.getStartAmount());
  622. ip.setLong(5, cp.getPrice());
  623. ip.setInt(6, cp.getReward());
  624. ip.setBoolean(7, true);
  625. ip.addBatch();
  626. }
  627. }
  628. // Execute procure batch
  629. ip.executeBatch();
  630. return true;
  631. }
  632. catch (Exception e)
  633. {
  634. LOGGER.severe(getClass().getSimpleName() + ": Unable to store manor data! " + e.getMessage());
  635. return false;
  636. }
  637. }
  638. public final void resetManorData(int castleId)
  639. {
  640. _procure.get(castleId).clear();
  641. _procureNext.get(castleId).clear();
  642. _production.get(castleId).clear();
  643. _productionNext.get(castleId).clear();
  644. if (Config.ALT_MANOR_SAVE_ALL_ACTIONS)
  645. {
  646. try (Connection con = ConnectionFactory.getInstance().getConnection();
  647. PreparedStatement ds = con.prepareStatement("DELETE FROM castle_manor_production WHERE castle_id = ?");
  648. PreparedStatement dc = con.prepareStatement("DELETE FROM castle_manor_procure WHERE castle_id = ?"))
  649. {
  650. // Delete seeds
  651. ds.setInt(1, castleId);
  652. ds.executeUpdate();
  653. // Delete procure
  654. dc.setInt(1, castleId);
  655. dc.executeUpdate();
  656. }
  657. catch (Exception e)
  658. {
  659. LOGGER.severe(getClass().getSimpleName() + ": Unable to store manor data! " + e.getMessage());
  660. }
  661. }
  662. }
  663. public final boolean isUnderMaintenance()
  664. {
  665. return _mode.equals(ManorMode.MAINTENANCE);
  666. }
  667. public final boolean isManorApproved()
  668. {
  669. return _mode.equals(ManorMode.APPROVED);
  670. }
  671. public final boolean isModifiablePeriod()
  672. {
  673. return _mode.equals(ManorMode.MODIFIABLE);
  674. }
  675. public final String getCurrentModeName()
  676. {
  677. return _mode.toString();
  678. }
  679. public final String getNextModeChange()
  680. {
  681. return new SimpleDateFormat("dd/MM HH:mm:ss").format(_nextModeChange.getTime());
  682. }
  683. // -------------------------------------------------------
  684. // Seed methods
  685. // -------------------------------------------------------
  686. public final List<L2Seed> getCrops()
  687. {
  688. final List<L2Seed> seeds = new ArrayList<>();
  689. final List<Integer> cropIds = new ArrayList<>();
  690. for (L2Seed seed : _seeds.values())
  691. {
  692. if (!cropIds.contains(seed.getCropId()))
  693. {
  694. seeds.add(seed);
  695. cropIds.add(seed.getCropId());
  696. }
  697. }
  698. cropIds.clear();
  699. return seeds;
  700. }
  701. public final Set<L2Seed> getSeedsForCastle(int castleId)
  702. {
  703. return _seeds.values().stream().filter(s -> s.getCastleId() == castleId).collect(Collectors.toSet());
  704. }
  705. public final Set<Integer> getSeedIds()
  706. {
  707. return _seeds.keySet();
  708. }
  709. public final Set<Integer> getCropIds()
  710. {
  711. return _seeds.values().stream().map(L2Seed::getCropId).collect(Collectors.toSet());
  712. }
  713. public final L2Seed getSeed(int seedId)
  714. {
  715. return _seeds.get(seedId);
  716. }
  717. public final L2Seed getSeedByCrop(int cropId, int castleId)
  718. {
  719. for (L2Seed s : getSeedsForCastle(castleId))
  720. {
  721. if (s.getCropId() == cropId)
  722. {
  723. return s;
  724. }
  725. }
  726. return null;
  727. }
  728. public final L2Seed getSeedByCrop(int cropId)
  729. {
  730. for (L2Seed s : _seeds.values())
  731. {
  732. if (s.getCropId() == cropId)
  733. {
  734. return s;
  735. }
  736. }
  737. return null;
  738. }
  739. // -------------------------------------------------------
  740. // Static methods
  741. // -------------------------------------------------------
  742. public static final CastleManorManager getInstance()
  743. {
  744. return SingletonHolder._instance;
  745. }
  746. private static class SingletonHolder
  747. {
  748. protected static final CastleManorManager _instance = new CastleManorManager();
  749. }
  750. }