ItemsOnGroundManager.java 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  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.instancemanager;
  16. import java.sql.Connection;
  17. import java.sql.PreparedStatement;
  18. import java.sql.ResultSet;
  19. import java.sql.SQLException;
  20. import java.util.List;
  21. import java.util.logging.Level;
  22. import java.util.logging.Logger;
  23. import javolution.util.FastList;
  24. import com.l2jserver.Config;
  25. import com.l2jserver.L2DatabaseFactory;
  26. import com.l2jserver.gameserver.ItemsAutoDestroy;
  27. import com.l2jserver.gameserver.ThreadPoolManager;
  28. import com.l2jserver.gameserver.model.L2World;
  29. import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
  30. import com.l2jserver.gameserver.model.items.type.L2EtcItemType;
  31. /**
  32. * This class manage all items on ground.
  33. * @author DiezelMax, original idea.
  34. * @author Enforcer, actual build.
  35. */
  36. public class ItemsOnGroundManager
  37. {
  38. static final Logger _log = Logger.getLogger(ItemsOnGroundManager.class.getName());
  39. protected List<L2ItemInstance> _items = null;
  40. private final StoreInDb _task = new StoreInDb();
  41. protected ItemsOnGroundManager()
  42. {
  43. if (Config.SAVE_DROPPED_ITEM)
  44. {
  45. _items = new FastList<>();
  46. }
  47. if (Config.SAVE_DROPPED_ITEM_INTERVAL > 0)
  48. {
  49. ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(_task, Config.SAVE_DROPPED_ITEM_INTERVAL, Config.SAVE_DROPPED_ITEM_INTERVAL);
  50. }
  51. load();
  52. }
  53. public static final ItemsOnGroundManager getInstance()
  54. {
  55. return SingletonHolder._instance;
  56. }
  57. private void load()
  58. {
  59. // If SaveDroppedItem is false, may want to delete all items previously stored to avoid add old items on reactivate
  60. if (!Config.SAVE_DROPPED_ITEM && Config.CLEAR_DROPPED_ITEM_TABLE)
  61. {
  62. emptyTable();
  63. }
  64. if (!Config.SAVE_DROPPED_ITEM)
  65. {
  66. return;
  67. }
  68. // if DestroyPlayerDroppedItem was previously false, items currently protected will be added to ItemsAutoDestroy
  69. if (Config.DESTROY_DROPPED_PLAYER_ITEM)
  70. {
  71. try (Connection con = L2DatabaseFactory.getInstance().getConnection())
  72. {
  73. String str = null;
  74. if (!Config.DESTROY_EQUIPABLE_PLAYER_ITEM)
  75. {
  76. // Recycle misc. items only
  77. str = "update itemsonground set drop_time=? where drop_time=-1 and equipable=0";
  78. }
  79. else if (Config.DESTROY_EQUIPABLE_PLAYER_ITEM)
  80. {
  81. // Recycle all items including equip-able
  82. str = "update itemsonground set drop_time=? where drop_time=-1";
  83. }
  84. PreparedStatement statement = con.prepareStatement(str);
  85. statement.setLong(1, System.currentTimeMillis());
  86. statement.execute();
  87. statement.close();
  88. }
  89. catch (Exception e)
  90. {
  91. _log.log(Level.SEVERE, "Error while updating table ItemsOnGround " + e.getMessage(), e);
  92. }
  93. }
  94. // Add items to world
  95. L2ItemInstance item;
  96. try (Connection con = L2DatabaseFactory.getInstance().getConnection())
  97. {
  98. PreparedStatement statement = con.prepareStatement("SELECT object_id,item_id,count,enchant_level,x,y,z,drop_time,equipable FROM itemsonground");
  99. ResultSet rset;
  100. int count = 0;
  101. rset = statement.executeQuery();
  102. while (rset.next())
  103. {
  104. item = new L2ItemInstance(rset.getInt(1), rset.getInt(2));
  105. L2World.getInstance().storeObject(item);
  106. // this check and..
  107. if (item.isStackable() && (rset.getInt(3) > 1))
  108. {
  109. item.setCount(rset.getInt(3));
  110. }
  111. // this, are really necessary?
  112. if (rset.getInt(4) > 0)
  113. {
  114. item.setEnchantLevel(rset.getInt(4));
  115. }
  116. item.getPosition().setWorldPosition(rset.getInt(5), rset.getInt(6), rset.getInt(7));
  117. item.getPosition().setWorldRegion(L2World.getInstance().getRegion(item.getPosition().getWorldPosition()));
  118. item.getPosition().getWorldRegion().addVisibleObject(item);
  119. final long dropTime = rset.getLong(8);
  120. item.setDropTime(dropTime);
  121. item.setProtected(dropTime == -1);
  122. item.setIsVisible(true);
  123. L2World.getInstance().addVisibleObject(item, item.getPosition().getWorldRegion());
  124. _items.add(item);
  125. count++;
  126. // add to ItemsAutoDestroy only items not protected
  127. if (!Config.LIST_PROTECTED_ITEMS.contains(item.getItemId()))
  128. {
  129. if (dropTime > -1)
  130. {
  131. if (((Config.AUTODESTROY_ITEM_AFTER > 0) && (item.getItemType() != L2EtcItemType.HERB)) || ((Config.HERB_AUTO_DESTROY_TIME > 0) && (item.getItemType() == L2EtcItemType.HERB)))
  132. {
  133. ItemsAutoDestroy.getInstance().addItem(item);
  134. }
  135. }
  136. }
  137. }
  138. rset.close();
  139. statement.close();
  140. _log.info("ItemsOnGroundManager: Loaded " + count + " items.");
  141. }
  142. catch (Exception e)
  143. {
  144. _log.log(Level.SEVERE, "Error while loading ItemsOnGround " + e.getMessage(), e);
  145. }
  146. if (Config.EMPTY_DROPPED_ITEM_TABLE_AFTER_LOAD)
  147. {
  148. emptyTable();
  149. }
  150. }
  151. public void save(L2ItemInstance item)
  152. {
  153. if (!Config.SAVE_DROPPED_ITEM)
  154. {
  155. return;
  156. }
  157. _items.add(item);
  158. }
  159. public void removeObject(L2ItemInstance item)
  160. {
  161. if (Config.SAVE_DROPPED_ITEM && (_items != null))
  162. {
  163. _items.remove(item);
  164. }
  165. }
  166. public void saveInDb()
  167. {
  168. _task.run();
  169. }
  170. public void cleanUp()
  171. {
  172. _items.clear();
  173. }
  174. public void emptyTable()
  175. {
  176. try (Connection con = L2DatabaseFactory.getInstance().getConnection())
  177. {
  178. PreparedStatement statement = con.prepareStatement("DELETE FROM itemsonground");
  179. statement.execute();
  180. statement.close();
  181. }
  182. catch (Exception e1)
  183. {
  184. _log.log(Level.SEVERE, "Error while cleaning table ItemsOnGround " + e1.getMessage(), e1);
  185. }
  186. }
  187. protected class StoreInDb extends Thread
  188. {
  189. @Override
  190. public synchronized void run()
  191. {
  192. if (!Config.SAVE_DROPPED_ITEM)
  193. {
  194. return;
  195. }
  196. emptyTable();
  197. if (_items.isEmpty())
  198. {
  199. if (Config.DEBUG)
  200. {
  201. _log.warning("ItemsOnGroundManager: nothing to save...");
  202. }
  203. return;
  204. }
  205. try (Connection con = L2DatabaseFactory.getInstance().getConnection())
  206. {
  207. PreparedStatement statement = con.prepareStatement("INSERT INTO itemsonground(object_id,item_id,count,enchant_level,x,y,z,drop_time,equipable) VALUES(?,?,?,?,?,?,?,?,?)");
  208. for (L2ItemInstance item : _items)
  209. {
  210. if (item == null)
  211. {
  212. continue;
  213. }
  214. if (CursedWeaponsManager.getInstance().isCursed(item.getItemId()))
  215. {
  216. continue; // Cursed Items not saved to ground, prevent double save
  217. }
  218. try
  219. {
  220. statement.setInt(1, item.getObjectId());
  221. statement.setInt(2, item.getItemId());
  222. statement.setLong(3, item.getCount());
  223. statement.setInt(4, item.getEnchantLevel());
  224. statement.setInt(5, item.getX());
  225. statement.setInt(6, item.getY());
  226. statement.setInt(7, item.getZ());
  227. statement.setLong(8, (item.isProtected() ? -1 : item.getDropTime())); // item is protected or AutoDestroyed
  228. statement.setLong(9, (item.isEquipable() ? 1 : 0)); // set equip-able
  229. statement.execute();
  230. statement.clearParameters();
  231. }
  232. catch (Exception e)
  233. {
  234. _log.log(Level.SEVERE, "Error while inserting into table ItemsOnGround: " + e.getMessage(), e);
  235. }
  236. }
  237. statement.close();
  238. }
  239. catch (SQLException e)
  240. {
  241. _log.log(Level.SEVERE, "SQL error while storing items on ground: " + e.getMessage(), e);
  242. }
  243. if (Config.DEBUG)
  244. {
  245. _log.info(getClass().getSimpleName() + ": Saved " + _items.size() + " items on ground.");
  246. }
  247. }
  248. }
  249. private static class SingletonHolder
  250. {
  251. protected static final ItemsOnGroundManager _instance = new ItemsOnGroundManager();
  252. }
  253. }