PcInventory.java 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023
  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.model.itemcontainer;
  20. import java.sql.Connection;
  21. import java.sql.PreparedStatement;
  22. import java.sql.ResultSet;
  23. import java.util.LinkedList;
  24. import java.util.List;
  25. import java.util.logging.Level;
  26. import java.util.logging.Logger;
  27. import com.l2jserver.Config;
  28. import com.l2jserver.L2DatabaseFactory;
  29. import com.l2jserver.gameserver.datatables.ItemTable;
  30. import com.l2jserver.gameserver.enums.ItemLocation;
  31. import com.l2jserver.gameserver.model.TradeItem;
  32. import com.l2jserver.gameserver.model.TradeList;
  33. import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
  34. import com.l2jserver.gameserver.model.events.EventDispatcher;
  35. import com.l2jserver.gameserver.model.events.impl.character.player.inventory.OnPlayerItemAdd;
  36. import com.l2jserver.gameserver.model.events.impl.character.player.inventory.OnPlayerItemDestroy;
  37. import com.l2jserver.gameserver.model.events.impl.character.player.inventory.OnPlayerItemDrop;
  38. import com.l2jserver.gameserver.model.events.impl.character.player.inventory.OnPlayerItemTransfer;
  39. import com.l2jserver.gameserver.model.items.L2Item;
  40. import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
  41. import com.l2jserver.gameserver.network.SystemMessageId;
  42. import com.l2jserver.gameserver.network.serverpackets.InventoryUpdate;
  43. import com.l2jserver.gameserver.network.serverpackets.ItemList;
  44. import com.l2jserver.gameserver.network.serverpackets.StatusUpdate;
  45. import com.l2jserver.gameserver.util.Util;
  46. public class PcInventory extends Inventory
  47. {
  48. private static final Logger _log = Logger.getLogger(PcInventory.class.getName());
  49. private final L2PcInstance _owner;
  50. private L2ItemInstance _adena;
  51. private L2ItemInstance _ancientAdena;
  52. private int[] _blockItems = null;
  53. private int _questSlots;
  54. private final Object _lock;
  55. /**
  56. * Block modes:
  57. * <UL>
  58. * <LI>-1 - no block
  59. * <LI>0 - block items from _invItems, allow usage of other items
  60. * <LI>1 - allow usage of items from _invItems, block other items
  61. * </UL>
  62. */
  63. private int _blockMode = -1;
  64. public PcInventory(L2PcInstance owner)
  65. {
  66. _owner = owner;
  67. _lock = new Object();
  68. }
  69. @Override
  70. public L2PcInstance getOwner()
  71. {
  72. return _owner;
  73. }
  74. @Override
  75. protected ItemLocation getBaseLocation()
  76. {
  77. return ItemLocation.INVENTORY;
  78. }
  79. @Override
  80. protected ItemLocation getEquipLocation()
  81. {
  82. return ItemLocation.PAPERDOLL;
  83. }
  84. public L2ItemInstance getAdenaInstance()
  85. {
  86. return _adena;
  87. }
  88. @Override
  89. public long getAdena()
  90. {
  91. return _adena != null ? _adena.getCount() : 0;
  92. }
  93. public L2ItemInstance getAncientAdenaInstance()
  94. {
  95. return _ancientAdena;
  96. }
  97. public long getAncientAdena()
  98. {
  99. return (_ancientAdena != null) ? _ancientAdena.getCount() : 0;
  100. }
  101. /**
  102. * Returns the list of items in inventory available for transaction
  103. * @param allowAdena
  104. * @param allowAncientAdena
  105. * @return L2ItemInstance : items in inventory
  106. */
  107. public L2ItemInstance[] getUniqueItems(boolean allowAdena, boolean allowAncientAdena)
  108. {
  109. return getUniqueItems(allowAdena, allowAncientAdena, true);
  110. }
  111. public L2ItemInstance[] getUniqueItems(boolean allowAdena, boolean allowAncientAdena, boolean onlyAvailable)
  112. {
  113. List<L2ItemInstance> list = new LinkedList<>();
  114. for (L2ItemInstance item : _items)
  115. {
  116. if (item == null)
  117. {
  118. continue;
  119. }
  120. if ((!allowAdena && (item.getId() == ADENA_ID)))
  121. {
  122. continue;
  123. }
  124. if ((!allowAncientAdena && (item.getId() == ANCIENT_ADENA_ID)))
  125. {
  126. continue;
  127. }
  128. boolean isDuplicate = false;
  129. for (L2ItemInstance litem : list)
  130. {
  131. if (litem.getId() == item.getId())
  132. {
  133. isDuplicate = true;
  134. break;
  135. }
  136. }
  137. if (!isDuplicate && (!onlyAvailable || (item.isSellable() && item.isAvailable(getOwner(), false, false))))
  138. {
  139. list.add(item);
  140. }
  141. }
  142. return list.toArray(new L2ItemInstance[list.size()]);
  143. }
  144. /**
  145. * Returns the list of items in inventory available for transaction Allows an item to appear twice if and only if there is a difference in enchantment level.
  146. * @param allowAdena
  147. * @param allowAncientAdena
  148. * @return L2ItemInstance : items in inventory
  149. */
  150. public L2ItemInstance[] getUniqueItemsByEnchantLevel(boolean allowAdena, boolean allowAncientAdena)
  151. {
  152. return getUniqueItemsByEnchantLevel(allowAdena, allowAncientAdena, true);
  153. }
  154. public L2ItemInstance[] getUniqueItemsByEnchantLevel(boolean allowAdena, boolean allowAncientAdena, boolean onlyAvailable)
  155. {
  156. List<L2ItemInstance> list = new LinkedList<>();
  157. for (L2ItemInstance item : _items)
  158. {
  159. if (item == null)
  160. {
  161. continue;
  162. }
  163. if ((!allowAdena && (item.getId() == ADENA_ID)))
  164. {
  165. continue;
  166. }
  167. if ((!allowAncientAdena && (item.getId() == ANCIENT_ADENA_ID)))
  168. {
  169. continue;
  170. }
  171. boolean isDuplicate = false;
  172. for (L2ItemInstance litem : list)
  173. {
  174. if ((litem.getId() == item.getId()) && (litem.getEnchantLevel() == item.getEnchantLevel()))
  175. {
  176. isDuplicate = true;
  177. break;
  178. }
  179. }
  180. if (!isDuplicate && (!onlyAvailable || (item.isSellable() && item.isAvailable(getOwner(), false, false))))
  181. {
  182. list.add(item);
  183. }
  184. }
  185. return list.toArray(new L2ItemInstance[list.size()]);
  186. }
  187. /**
  188. * @param itemId
  189. * @return
  190. */
  191. public L2ItemInstance[] getAllItemsByItemId(int itemId)
  192. {
  193. return getAllItemsByItemId(itemId, true);
  194. }
  195. /**
  196. * Returns the list of all items in inventory that have a given item id.
  197. * @param itemId : ID of item
  198. * @param includeEquipped : include equipped items
  199. * @return L2ItemInstance[] : matching items from inventory
  200. */
  201. public L2ItemInstance[] getAllItemsByItemId(int itemId, boolean includeEquipped)
  202. {
  203. List<L2ItemInstance> list = new LinkedList<>();
  204. for (L2ItemInstance item : _items)
  205. {
  206. if (item == null)
  207. {
  208. continue;
  209. }
  210. if ((item.getId() == itemId) && (includeEquipped || !item.isEquipped()))
  211. {
  212. list.add(item);
  213. }
  214. }
  215. return list.toArray(new L2ItemInstance[list.size()]);
  216. }
  217. /**
  218. * @param itemId
  219. * @param enchantment
  220. * @return
  221. */
  222. public L2ItemInstance[] getAllItemsByItemId(int itemId, int enchantment)
  223. {
  224. return getAllItemsByItemId(itemId, enchantment, true);
  225. }
  226. /**
  227. * Returns the list of all items in inventory that have a given item id AND a given enchantment level.
  228. * @param itemId : ID of item
  229. * @param enchantment : enchant level of item
  230. * @param includeEquipped : include equipped items
  231. * @return L2ItemInstance[] : matching items from inventory
  232. */
  233. public L2ItemInstance[] getAllItemsByItemId(int itemId, int enchantment, boolean includeEquipped)
  234. {
  235. List<L2ItemInstance> list = new LinkedList<>();
  236. for (L2ItemInstance item : _items)
  237. {
  238. if (item == null)
  239. {
  240. continue;
  241. }
  242. if ((item.getId() == itemId) && (item.getEnchantLevel() == enchantment) && (includeEquipped || !item.isEquipped()))
  243. {
  244. list.add(item);
  245. }
  246. }
  247. return list.toArray(new L2ItemInstance[list.size()]);
  248. }
  249. /**
  250. * @param allowAdena
  251. * @param allowNonTradeable
  252. * @param feightable
  253. * @return the list of items in inventory available for transaction
  254. */
  255. public L2ItemInstance[] getAvailableItems(boolean allowAdena, boolean allowNonTradeable, boolean feightable)
  256. {
  257. List<L2ItemInstance> list = new LinkedList<>();
  258. for (L2ItemInstance item : _items)
  259. {
  260. if ((item == null) || !item.isAvailable(getOwner(), allowAdena, allowNonTradeable) || !canManipulateWithItemId(item.getId()))
  261. {
  262. continue;
  263. }
  264. else if (feightable)
  265. {
  266. if ((item.getItemLocation() == ItemLocation.INVENTORY) && item.isFreightable())
  267. {
  268. list.add(item);
  269. }
  270. }
  271. else
  272. {
  273. list.add(item);
  274. }
  275. }
  276. return list.toArray(new L2ItemInstance[list.size()]);
  277. }
  278. /**
  279. * Get all augmented items
  280. * @return
  281. */
  282. public L2ItemInstance[] getAugmentedItems()
  283. {
  284. List<L2ItemInstance> list = new LinkedList<>();
  285. for (L2ItemInstance item : _items)
  286. {
  287. if ((item != null) && item.isAugmented())
  288. {
  289. list.add(item);
  290. }
  291. }
  292. return list.toArray(new L2ItemInstance[list.size()]);
  293. }
  294. /**
  295. * Get all element items
  296. * @return
  297. */
  298. public L2ItemInstance[] getElementItems()
  299. {
  300. List<L2ItemInstance> list = new LinkedList<>();
  301. for (L2ItemInstance item : _items)
  302. {
  303. if ((item != null) && (item.getElementals() != null))
  304. {
  305. list.add(item);
  306. }
  307. }
  308. return list.toArray(new L2ItemInstance[list.size()]);
  309. }
  310. /**
  311. * Returns the list of items in inventory available for transaction adjusted by tradeList
  312. * @param tradeList
  313. * @return L2ItemInstance : items in inventory
  314. */
  315. public TradeItem[] getAvailableItems(TradeList tradeList)
  316. {
  317. List<TradeItem> list = new LinkedList<>();
  318. for (L2ItemInstance item : _items)
  319. {
  320. if ((item != null) && item.isAvailable(getOwner(), false, false))
  321. {
  322. TradeItem adjItem = tradeList.adjustAvailableItem(item);
  323. if (adjItem != null)
  324. {
  325. list.add(adjItem);
  326. }
  327. }
  328. }
  329. return list.toArray(new TradeItem[list.size()]);
  330. }
  331. /**
  332. * Adjust TradeItem according his status in inventory
  333. * @param item : L2ItemInstance to be adjusted
  334. */
  335. public void adjustAvailableItem(TradeItem item)
  336. {
  337. boolean notAllEquipped = false;
  338. for (L2ItemInstance adjItem : getItemsByItemId(item.getItem().getId()))
  339. {
  340. if (adjItem.isEquipable())
  341. {
  342. if (!adjItem.isEquipped())
  343. {
  344. notAllEquipped |= true;
  345. }
  346. }
  347. else
  348. {
  349. notAllEquipped |= true;
  350. break;
  351. }
  352. }
  353. if (notAllEquipped)
  354. {
  355. L2ItemInstance adjItem = getItemByItemId(item.getItem().getId());
  356. item.setObjectId(adjItem.getObjectId());
  357. item.setEnchant(adjItem.getEnchantLevel());
  358. if (adjItem.getCount() < item.getCount())
  359. {
  360. item.setCount(adjItem.getCount());
  361. }
  362. return;
  363. }
  364. item.setCount(0);
  365. }
  366. /**
  367. * Adds adena to PCInventory
  368. * @param process : String Identifier of process triggering this action
  369. * @param count : int Quantity of adena to be added
  370. * @param actor : L2PcInstance Player requesting the item add
  371. * @param reference : Object Object referencing current action like NPC selling item or previous item in transformation
  372. */
  373. public void addAdena(String process, long count, L2PcInstance actor, Object reference)
  374. {
  375. if (count > 0)
  376. {
  377. addItem(process, ADENA_ID, count, actor, reference);
  378. }
  379. }
  380. /**
  381. * Removes adena to PCInventory
  382. * @param process : String Identifier of process triggering this action
  383. * @param count : int Quantity of adena to be removed
  384. * @param actor : L2PcInstance Player requesting the item add
  385. * @param reference : Object Object referencing current action like NPC selling item or previous item in transformation
  386. * @return boolean : true if adena was reduced
  387. */
  388. public boolean reduceAdena(String process, long count, L2PcInstance actor, Object reference)
  389. {
  390. if (count > 0)
  391. {
  392. return destroyItemByItemId(process, ADENA_ID, count, actor, reference) != null;
  393. }
  394. return false;
  395. }
  396. /**
  397. * Adds specified amount of ancient adena to player inventory.
  398. * @param process : String Identifier of process triggering this action
  399. * @param count : int Quantity of adena to be added
  400. * @param actor : L2PcInstance Player requesting the item add
  401. * @param reference : Object Object referencing current action like NPC selling item or previous item in transformation
  402. */
  403. public void addAncientAdena(String process, long count, L2PcInstance actor, Object reference)
  404. {
  405. if (count > 0)
  406. {
  407. addItem(process, ANCIENT_ADENA_ID, count, actor, reference);
  408. }
  409. }
  410. /**
  411. * Removes specified amount of ancient adena from player inventory.
  412. * @param process : String Identifier of process triggering this action
  413. * @param count : int Quantity of adena to be removed
  414. * @param actor : L2PcInstance Player requesting the item add
  415. * @param reference : Object Object referencing current action like NPC selling item or previous item in transformation
  416. * @return boolean : true if adena was reduced
  417. */
  418. public boolean reduceAncientAdena(String process, long count, L2PcInstance actor, Object reference)
  419. {
  420. if (count > 0)
  421. {
  422. return destroyItemByItemId(process, ANCIENT_ADENA_ID, count, actor, reference) != null;
  423. }
  424. return false;
  425. }
  426. /**
  427. * Adds item in inventory and checks _adena and _ancientAdena
  428. * @param process : String Identifier of process triggering this action
  429. * @param item : L2ItemInstance to be added
  430. * @param actor : L2PcInstance Player requesting the item add
  431. * @param reference : Object Object referencing current action like NPC selling item or previous item in transformation
  432. * @return L2ItemInstance corresponding to the new item or the updated item in inventory
  433. */
  434. @Override
  435. public L2ItemInstance addItem(String process, L2ItemInstance item, L2PcInstance actor, Object reference)
  436. {
  437. item = super.addItem(process, item, actor, reference);
  438. if ((item != null) && (item.getId() == ADENA_ID) && !item.equals(_adena))
  439. {
  440. _adena = item;
  441. }
  442. if ((item != null) && (item.getId() == ANCIENT_ADENA_ID) && !item.equals(_ancientAdena))
  443. {
  444. _ancientAdena = item;
  445. }
  446. if (item != null)
  447. {
  448. // Notify to scripts
  449. EventDispatcher.getInstance().notifyEventAsync(new OnPlayerItemAdd(actor, item), item.getItem());
  450. }
  451. return item;
  452. }
  453. /**
  454. * Adds item in inventory and checks _adena and _ancientAdena
  455. * @param process : String Identifier of process triggering this action
  456. * @param itemId : int Item Identifier of the item to be added
  457. * @param count : int Quantity of items to be added
  458. * @param actor : L2PcInstance Player requesting the item creation
  459. * @param reference : Object Object referencing current action like NPC selling item or previous item in transformation
  460. * @return L2ItemInstance corresponding to the new item or the updated item in inventory
  461. */
  462. @Override
  463. public L2ItemInstance addItem(String process, int itemId, long count, L2PcInstance actor, Object reference)
  464. {
  465. final L2ItemInstance item = super.addItem(process, itemId, count, actor, reference);
  466. if (item != null)
  467. {
  468. if ((item.getId() == ADENA_ID) && !item.equals(_adena))
  469. {
  470. _adena = item;
  471. }
  472. if ((item.getId() == ANCIENT_ADENA_ID) && !item.equals(_ancientAdena))
  473. {
  474. _ancientAdena = item;
  475. }
  476. if (actor != null)
  477. {
  478. // Send inventory update packet
  479. if (!Config.FORCE_INVENTORY_UPDATE)
  480. {
  481. InventoryUpdate playerIU = new InventoryUpdate();
  482. playerIU.addItem(item);
  483. actor.sendPacket(playerIU);
  484. }
  485. else
  486. {
  487. actor.sendPacket(new ItemList(actor, false));
  488. }
  489. // Update current load as well
  490. StatusUpdate su = new StatusUpdate(actor);
  491. su.addAttribute(StatusUpdate.CUR_LOAD, actor.getCurrentLoad());
  492. actor.sendPacket(su);
  493. // Notify to scripts
  494. EventDispatcher.getInstance().notifyEventAsync(new OnPlayerItemAdd(actor, item), item.getItem());
  495. }
  496. }
  497. return item;
  498. }
  499. /**
  500. * Transfers item to another inventory and checks _adena and _ancientAdena
  501. * @param process string Identifier of process triggering this action
  502. * @param objectId Item Identifier of the item to be transfered
  503. * @param count Quantity of items to be transfered
  504. * @param target the item container for the item to be transfered.
  505. * @param actor the player requesting the item transfer
  506. * @param reference : Object Object referencing current action like NPC selling item or previous item in transformation
  507. * @return L2ItemInstance corresponding to the new item or the updated item in inventory
  508. */
  509. @Override
  510. public L2ItemInstance transferItem(String process, int objectId, long count, ItemContainer target, L2PcInstance actor, Object reference)
  511. {
  512. L2ItemInstance item = super.transferItem(process, objectId, count, target, actor, reference);
  513. if ((_adena != null) && ((_adena.getCount() <= 0) || (_adena.getOwnerId() != getOwnerId())))
  514. {
  515. _adena = null;
  516. }
  517. if ((_ancientAdena != null) && ((_ancientAdena.getCount() <= 0) || (_ancientAdena.getOwnerId() != getOwnerId())))
  518. {
  519. _ancientAdena = null;
  520. }
  521. // Notify to scripts
  522. EventDispatcher.getInstance().notifyEventAsync(new OnPlayerItemTransfer(actor, item, target), item.getItem());
  523. return item;
  524. }
  525. /**
  526. * Destroy item from inventory and checks _adena and _ancientAdena
  527. * @param process : String Identifier of process triggering this action
  528. * @param item : L2ItemInstance to be destroyed
  529. * @param actor : L2PcInstance Player requesting the item destroy
  530. * @param reference : Object Object referencing current action like NPC selling item or previous item in transformation
  531. * @return L2ItemInstance corresponding to the destroyed item or the updated item in inventory
  532. */
  533. @Override
  534. public L2ItemInstance destroyItem(String process, L2ItemInstance item, L2PcInstance actor, Object reference)
  535. {
  536. return destroyItem(process, item, item.getCount(), actor, reference);
  537. }
  538. /**
  539. * Destroy item from inventory and checks _adena and _ancientAdena
  540. * @param process : String Identifier of process triggering this action
  541. * @param item : L2ItemInstance to be destroyed
  542. * @param actor : L2PcInstance Player requesting the item destroy
  543. * @param reference : Object Object referencing current action like NPC selling item or previous item in transformation
  544. * @return L2ItemInstance corresponding to the destroyed item or the updated item in inventory
  545. */
  546. @Override
  547. public L2ItemInstance destroyItem(String process, L2ItemInstance item, long count, L2PcInstance actor, Object reference)
  548. {
  549. item = super.destroyItem(process, item, count, actor, reference);
  550. if ((_adena != null) && (_adena.getCount() <= 0))
  551. {
  552. _adena = null;
  553. }
  554. if ((_ancientAdena != null) && (_ancientAdena.getCount() <= 0))
  555. {
  556. _ancientAdena = null;
  557. }
  558. // Notify to scripts
  559. if (item != null)
  560. {
  561. EventDispatcher.getInstance().notifyEventAsync(new OnPlayerItemDestroy(actor, item), item.getItem());
  562. }
  563. return item;
  564. }
  565. /**
  566. * Destroys item from inventory and checks _adena and _ancientAdena
  567. * @param process : String Identifier of process triggering this action
  568. * @param objectId : int Item Instance identifier of the item to be destroyed
  569. * @param count : int Quantity of items to be destroyed
  570. * @param actor : L2PcInstance Player requesting the item destroy
  571. * @param reference : Object Object referencing current action like NPC selling item or previous item in transformation
  572. * @return L2ItemInstance corresponding to the destroyed item or the updated item in inventory
  573. */
  574. @Override
  575. public L2ItemInstance destroyItem(String process, int objectId, long count, L2PcInstance actor, Object reference)
  576. {
  577. L2ItemInstance item = getItemByObjectId(objectId);
  578. if (item == null)
  579. {
  580. return null;
  581. }
  582. return this.destroyItem(process, item, count, actor, reference);
  583. }
  584. /**
  585. * Destroy item from inventory by using its <B>itemId</B> and checks _adena and _ancientAdena
  586. * @param process : String Identifier of process triggering this action
  587. * @param itemId : int Item identifier of the item to be destroyed
  588. * @param count : int Quantity of items to be destroyed
  589. * @param actor : L2PcInstance Player requesting the item destroy
  590. * @param reference : Object Object referencing current action like NPC selling item or previous item in transformation
  591. * @return L2ItemInstance corresponding to the destroyed item or the updated item in inventory
  592. */
  593. @Override
  594. public L2ItemInstance destroyItemByItemId(String process, int itemId, long count, L2PcInstance actor, Object reference)
  595. {
  596. L2ItemInstance item = getItemByItemId(itemId);
  597. if (item == null)
  598. {
  599. return null;
  600. }
  601. return this.destroyItem(process, item, count, actor, reference);
  602. }
  603. /**
  604. * Drop item from inventory and checks _adena and _ancientAdena
  605. * @param process : String Identifier of process triggering this action
  606. * @param item : L2ItemInstance to be dropped
  607. * @param actor : L2PcInstance Player requesting the item drop
  608. * @param reference : Object Object referencing current action like NPC selling item or previous item in transformation
  609. * @return L2ItemInstance corresponding to the destroyed item or the updated item in inventory
  610. */
  611. @Override
  612. public L2ItemInstance dropItem(String process, L2ItemInstance item, L2PcInstance actor, Object reference)
  613. {
  614. item = super.dropItem(process, item, actor, reference);
  615. if ((_adena != null) && ((_adena.getCount() <= 0) || (_adena.getOwnerId() != getOwnerId())))
  616. {
  617. _adena = null;
  618. }
  619. if ((_ancientAdena != null) && ((_ancientAdena.getCount() <= 0) || (_ancientAdena.getOwnerId() != getOwnerId())))
  620. {
  621. _ancientAdena = null;
  622. }
  623. // Notify to scripts
  624. if (item != null)
  625. {
  626. EventDispatcher.getInstance().notifyEventAsync(new OnPlayerItemDrop(actor, item, item.getLocation()), item.getItem());
  627. }
  628. return item;
  629. }
  630. /**
  631. * Drop item from inventory by using its <B>objectID</B> and checks _adena and _ancientAdena
  632. * @param process : String Identifier of process triggering this action
  633. * @param objectId : int Item Instance identifier of the item to be dropped
  634. * @param count : int Quantity of items to be dropped
  635. * @param actor : L2PcInstance Player requesting the item drop
  636. * @param reference : Object Object referencing current action like NPC selling item or previous item in transformation
  637. * @return L2ItemInstance corresponding to the destroyed item or the updated item in inventory
  638. */
  639. @Override
  640. public L2ItemInstance dropItem(String process, int objectId, long count, L2PcInstance actor, Object reference)
  641. {
  642. L2ItemInstance item = super.dropItem(process, objectId, count, actor, reference);
  643. if ((_adena != null) && ((_adena.getCount() <= 0) || (_adena.getOwnerId() != getOwnerId())))
  644. {
  645. _adena = null;
  646. }
  647. if ((_ancientAdena != null) && ((_ancientAdena.getCount() <= 0) || (_ancientAdena.getOwnerId() != getOwnerId())))
  648. {
  649. _ancientAdena = null;
  650. }
  651. // Notify to scripts
  652. if (item != null)
  653. {
  654. EventDispatcher.getInstance().notifyEventAsync(new OnPlayerItemDrop(actor, item, item.getLocation()), item.getItem());
  655. }
  656. return item;
  657. }
  658. /**
  659. * <b>Overloaded</b>, when removes item from inventory, remove also owner shortcuts.
  660. * @param item : L2ItemInstance to be removed from inventory
  661. */
  662. @Override
  663. protected boolean removeItem(L2ItemInstance item)
  664. {
  665. // Removes any reference to the item from Shortcut bar
  666. getOwner().removeItemFromShortCut(item.getObjectId());
  667. // Removes active Enchant Scroll
  668. if (item.getObjectId() == getOwner().getActiveEnchantItemId())
  669. {
  670. getOwner().setActiveEnchantItemId(L2PcInstance.ID_NONE);
  671. }
  672. if (item.getId() == ADENA_ID)
  673. {
  674. _adena = null;
  675. }
  676. else if (item.getId() == ANCIENT_ADENA_ID)
  677. {
  678. _ancientAdena = null;
  679. }
  680. if (item.isQuestItem())
  681. {
  682. synchronized (_lock)
  683. {
  684. _questSlots--;
  685. if (_questSlots < 0)
  686. {
  687. _questSlots = 0;
  688. _log.warning(this + ": QuestInventory size < 0!");
  689. }
  690. }
  691. }
  692. return super.removeItem(item);
  693. }
  694. /**
  695. * Refresh the weight of equipment loaded
  696. */
  697. @Override
  698. public void refreshWeight()
  699. {
  700. super.refreshWeight();
  701. getOwner().refreshOverloaded();
  702. }
  703. /**
  704. * Get back items in inventory from database
  705. */
  706. @Override
  707. public void restore()
  708. {
  709. super.restore();
  710. _adena = getItemByItemId(ADENA_ID);
  711. _ancientAdena = getItemByItemId(ANCIENT_ADENA_ID);
  712. }
  713. public static int[][] restoreVisibleInventory(int objectId)
  714. {
  715. int[][] paperdoll = new int[31][3];
  716. try (Connection con = L2DatabaseFactory.getInstance().getConnection();
  717. PreparedStatement statement2 = con.prepareStatement("SELECT object_id,item_id,loc_data,enchant_level FROM items WHERE owner_id=? AND loc='PAPERDOLL'"))
  718. {
  719. statement2.setInt(1, objectId);
  720. try (ResultSet invdata = statement2.executeQuery())
  721. {
  722. while (invdata.next())
  723. {
  724. int slot = invdata.getInt("loc_data");
  725. paperdoll[slot][0] = invdata.getInt("object_id");
  726. paperdoll[slot][1] = invdata.getInt("item_id");
  727. paperdoll[slot][2] = invdata.getInt("enchant_level");
  728. /*
  729. * if (slot == Inventory.PAPERDOLL_RHAND) { paperdoll[Inventory.PAPERDOLL_RHAND][0] = invdata.getInt("object_id"); paperdoll[Inventory.PAPERDOLL_RHAND][1] = invdata.getInt("item_id"); paperdoll[Inventory.PAPERDOLL_RHAND][2] = invdata.getInt("enchant_level"); }
  730. */
  731. }
  732. }
  733. }
  734. catch (Exception e)
  735. {
  736. _log.log(Level.WARNING, "Could not restore inventory: " + e.getMessage(), e);
  737. }
  738. return paperdoll;
  739. }
  740. /**
  741. * @param itemList the items that needs to be validated.
  742. * @param sendMessage if {@code true} will send a message of inventory full.
  743. * @param sendSkillMessage if {@code true} will send a message of skill not available.
  744. * @return {@code true} if the inventory isn't full after taking new items and items weight add to current load doesn't exceed max weight load.
  745. */
  746. public boolean checkInventorySlotsAndWeight(List<L2Item> itemList, boolean sendMessage, boolean sendSkillMessage)
  747. {
  748. int lootWeight = 0;
  749. int requiredSlots = 0;
  750. if (itemList != null)
  751. {
  752. for (L2Item item : itemList)
  753. {
  754. // If the item is not stackable or is stackable and not present in inventory, will need a slot.
  755. if (!item.isStackable() || (getInventoryItemCount(item.getId(), -1) <= 0))
  756. {
  757. requiredSlots++;
  758. }
  759. lootWeight += item.getWeight();
  760. }
  761. }
  762. boolean inventoryStatusOK = validateCapacity(requiredSlots) && validateWeight(lootWeight);
  763. if (!inventoryStatusOK && sendMessage)
  764. {
  765. _owner.sendPacket(SystemMessageId.SLOTS_FULL);
  766. if (sendSkillMessage)
  767. {
  768. _owner.sendPacket(SystemMessageId.WEIGHT_EXCEEDED_SKILL_UNAVAILABLE);
  769. }
  770. }
  771. return inventoryStatusOK;
  772. }
  773. /**
  774. * If the item is not stackable or is stackable and not present in inventory, will need a slot.
  775. * @param item the item to validate.
  776. * @return {@code true} if there is enough room to add the item inventory.
  777. */
  778. public boolean validateCapacity(L2ItemInstance item)
  779. {
  780. int slots = 0;
  781. if (!item.isStackable() || (getInventoryItemCount(item.getId(), -1) <= 0) || !item.getItem().hasExImmediateEffect())
  782. {
  783. slots++;
  784. }
  785. return validateCapacity(slots, item.isQuestItem());
  786. }
  787. /**
  788. * If the item is not stackable or is stackable and not present in inventory, will need a slot.
  789. * @param itemId the item Id for the item to validate.
  790. * @return {@code true} if there is enough room to add the item inventory.
  791. */
  792. public boolean validateCapacityByItemId(int itemId)
  793. {
  794. int slots = 0;
  795. final L2ItemInstance invItem = getItemByItemId(itemId);
  796. if ((invItem == null) || !invItem.isStackable())
  797. {
  798. slots++;
  799. }
  800. return validateCapacity(slots, ItemTable.getInstance().getTemplate(itemId).isQuestItem());
  801. }
  802. @Override
  803. public boolean validateCapacity(long slots)
  804. {
  805. return validateCapacity(slots, false);
  806. }
  807. public boolean validateCapacity(long slots, boolean questItem)
  808. {
  809. if (!questItem)
  810. {
  811. return (((_items.size() - _questSlots) + slots) <= _owner.getInventoryLimit());
  812. }
  813. return (_questSlots + slots) <= _owner.getQuestInventoryLimit();
  814. }
  815. @Override
  816. public boolean validateWeight(long weight)
  817. {
  818. // Disable weight check for GMs.
  819. if (_owner.isGM() && _owner.getDietMode() && _owner.getAccessLevel().allowTransaction())
  820. {
  821. return true;
  822. }
  823. return ((_totalWeight + weight) <= _owner.getMaxLoad());
  824. }
  825. /**
  826. * Set inventory block for specified IDs<br>
  827. * array reference is used for {@link PcInventory#_blockItems}
  828. * @param items array of Ids to block/allow
  829. * @param mode blocking mode {@link PcInventory#_blockMode}
  830. */
  831. public void setInventoryBlock(int[] items, int mode)
  832. {
  833. _blockMode = mode;
  834. _blockItems = items;
  835. _owner.sendPacket(new ItemList(_owner, false));
  836. }
  837. /**
  838. * Unblock blocked itemIds
  839. */
  840. public void unblock()
  841. {
  842. _blockMode = -1;
  843. _blockItems = null;
  844. _owner.sendPacket(new ItemList(_owner, false));
  845. }
  846. /**
  847. * Check if player inventory is in block mode.
  848. * @return true if some itemIds blocked
  849. */
  850. public boolean hasInventoryBlock()
  851. {
  852. return ((_blockMode > -1) && (_blockItems != null) && (_blockItems.length > 0));
  853. }
  854. /**
  855. * Block all player items
  856. */
  857. public void blockAllItems()
  858. {
  859. // temp fix, some id must be sended
  860. setInventoryBlock(new int[]
  861. {
  862. (ItemTable.getInstance().getArraySize() + 2)
  863. }, 1);
  864. }
  865. /**
  866. * Return block mode
  867. * @return int {@link PcInventory#_blockMode}
  868. */
  869. public int getBlockMode()
  870. {
  871. return _blockMode;
  872. }
  873. /**
  874. * Return TIntArrayList with blocked item ids
  875. * @return TIntArrayList
  876. */
  877. public int[] getBlockItems()
  878. {
  879. return _blockItems;
  880. }
  881. /**
  882. * Check if player can use item by itemid
  883. * @param itemId int
  884. * @return true if can use
  885. */
  886. public boolean canManipulateWithItemId(int itemId)
  887. {
  888. if (((_blockMode == 0) && Util.contains(_blockItems, itemId)) || ((_blockMode == 1) && !Util.contains(_blockItems, itemId)))
  889. {
  890. return false;
  891. }
  892. return true;
  893. }
  894. @Override
  895. protected void addItem(L2ItemInstance item)
  896. {
  897. if (item.isQuestItem())
  898. {
  899. synchronized (_lock)
  900. {
  901. _questSlots++;
  902. }
  903. }
  904. super.addItem(item);
  905. }
  906. public int getSize(boolean quest)
  907. {
  908. if (quest)
  909. {
  910. return _questSlots;
  911. }
  912. return getSize() - _questSlots;
  913. }
  914. @Override
  915. public String toString()
  916. {
  917. return getClass().getSimpleName() + "[" + _owner + "]";
  918. }
  919. /**
  920. * Apply skills of inventory items
  921. */
  922. public void applyItemSkills()
  923. {
  924. for (L2ItemInstance item : _items)
  925. {
  926. item.giveSkillsToOwner();
  927. item.applyEnchantStats();
  928. }
  929. }
  930. }