RequestBuyItem.java 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. /*
  2. * This program is free software; you can redistribute it and/or modify
  3. * it under the terms of the GNU General Public License as published by
  4. * the Free Software Foundation; either version 2, or (at your option)
  5. * any later version.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. * You should have received a copy of the GNU General Public License
  13. * along with this program; if not, write to the Free Software
  14. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  15. * 02111-1307, USA.
  16. *
  17. * http://www.gnu.org/copyleft/gpl.html
  18. */
  19. package net.sf.l2j.gameserver.clientpackets;
  20. import java.util.List;
  21. import java.util.logging.Logger;
  22. import net.sf.l2j.Config;
  23. import net.sf.l2j.gameserver.TradeController;
  24. import net.sf.l2j.gameserver.cache.HtmCache;
  25. import net.sf.l2j.gameserver.datatables.ItemTable;
  26. import net.sf.l2j.gameserver.model.L2Object;
  27. import net.sf.l2j.gameserver.model.L2TradeList;
  28. import net.sf.l2j.gameserver.model.actor.instance.L2CastleChamberlainInstance;
  29. import net.sf.l2j.gameserver.model.actor.instance.L2ClanHallManagerInstance;
  30. import net.sf.l2j.gameserver.model.actor.instance.L2FishermanInstance;
  31. import net.sf.l2j.gameserver.model.actor.instance.L2MercManagerInstance;
  32. import net.sf.l2j.gameserver.model.actor.instance.L2MerchantInstance;
  33. import net.sf.l2j.gameserver.model.actor.instance.L2NpcInstance;
  34. import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
  35. import net.sf.l2j.gameserver.network.SystemMessageId;
  36. import net.sf.l2j.gameserver.serverpackets.ActionFailed;
  37. import net.sf.l2j.gameserver.serverpackets.ItemList;
  38. import net.sf.l2j.gameserver.serverpackets.NpcHtmlMessage;
  39. import net.sf.l2j.gameserver.serverpackets.StatusUpdate;
  40. import net.sf.l2j.gameserver.serverpackets.SystemMessage;
  41. import net.sf.l2j.gameserver.templates.L2Item;
  42. import net.sf.l2j.gameserver.util.Util;
  43. /**
  44. * This class ...
  45. *
  46. * @version $Revision: 1.12.4.4 $ $Date: 2005/03/27 15:29:30 $
  47. */
  48. public final class RequestBuyItem extends L2GameClientPacket
  49. {
  50. private static final String _C__1F_REQUESTBUYITEM = "[C] 1F RequestBuyItem";
  51. private static Logger _log = Logger.getLogger(RequestBuyItem.class.getName());
  52. private int _listId;
  53. private int _count;
  54. private int[] _items; // count*2
  55. @Override
  56. protected void readImpl()
  57. {
  58. _listId = readD();
  59. _count = readD();
  60. // count*8 is the size of a for iteration of each item
  61. if(_count * 2 < 0 || _count * 8 > _buf.remaining() || _count > Config.MAX_ITEM_IN_PACKET) _count = 0;
  62. _items = new int[_count * 2];
  63. for (int i = 0; i < _count; i++)
  64. {
  65. int itemId = readD(); _items[i * 2 + 0] = itemId;
  66. long cnt = readD();
  67. if (cnt > Integer.MAX_VALUE || cnt < 0)
  68. {
  69. _count=0; _items = null;
  70. return;
  71. }
  72. _items[i * 2 + 1] = (int)cnt;
  73. }
  74. }
  75. @Override
  76. protected void runImpl()
  77. {
  78. L2PcInstance player = getClient().getActiveChar();
  79. if (player == null) return;
  80. // Alt game - Karma punishment
  81. if (!Config.ALT_GAME_KARMA_PLAYER_CAN_SHOP && player.getKarma() > 0) return;
  82. L2Object target = player.getTarget();
  83. if (!player.isGM() && (target == null // No target (ie GM Shop)
  84. || !(target instanceof L2MerchantInstance || target instanceof L2FishermanInstance || target instanceof L2MercManagerInstance || target instanceof L2ClanHallManagerInstance)|| target instanceof L2CastleChamberlainInstance // Target not a merchant, fisherman or mercmanager
  85. || !player.isInsideRadius(target, L2NpcInstance.INTERACTION_DISTANCE, false, false) // Distance is too far
  86. )) return;
  87. boolean ok = true;
  88. String htmlFolder = "";
  89. if (target != null)
  90. {
  91. if (target instanceof L2MerchantInstance)
  92. htmlFolder = "merchant";
  93. else if (target instanceof L2FishermanInstance)
  94. htmlFolder = "fisherman";
  95. else if (target instanceof L2MercManagerInstance)
  96. ok = true;
  97. else if (target instanceof L2ClanHallManagerInstance)
  98. ok = true;
  99. else if (target instanceof L2CastleChamberlainInstance)
  100. ok = true;
  101. else
  102. ok = false;
  103. }
  104. else
  105. ok = false;
  106. L2NpcInstance merchant = null;
  107. if (ok)
  108. merchant = (L2NpcInstance)target;
  109. else if (!ok && !player.isGM())
  110. {
  111. player.sendMessage("Invalid Target: Seller must be targetted");
  112. return;
  113. }
  114. L2TradeList list = null;
  115. if (merchant != null)
  116. {
  117. List<L2TradeList> lists = TradeController.getInstance().getBuyListByNpcId(merchant.getNpcId());
  118. if(!player.isGM() )
  119. {
  120. if (lists == null)
  121. {
  122. Util.handleIllegalPlayerAction(player,"Warning!! Character "+player.getName()+" of account "+player.getAccountName()+" sent a false BuyList list_id.",Config.DEFAULT_PUNISH);
  123. return;
  124. }
  125. for (L2TradeList tradeList : lists)
  126. {
  127. if (tradeList.getListId() == _listId)
  128. {
  129. list = tradeList;
  130. }
  131. }
  132. }
  133. else
  134. {
  135. list = TradeController.getInstance().getBuyList(_listId);
  136. }
  137. }
  138. else
  139. list = TradeController.getInstance().getBuyList(_listId);
  140. if (list == null)
  141. {
  142. Util.handleIllegalPlayerAction(player,"Warning!! Character "+player.getName()+" of account "+player.getAccountName()+" sent a false BuyList list_id.",Config.DEFAULT_PUNISH);
  143. return;
  144. }
  145. _listId = list.getListId();
  146. if (_listId > 1000000) // lease
  147. {
  148. if (merchant != null && merchant.getTemplate().npcId != _listId-1000000)
  149. {
  150. sendPacket(new ActionFailed());
  151. return;
  152. }
  153. }
  154. if(_count < 1)
  155. {
  156. sendPacket(new ActionFailed());
  157. return;
  158. }
  159. double taxRate = 0;
  160. if (merchant != null && merchant.getIsInTown()) taxRate = merchant.getCastle().getTaxRate();
  161. long subTotal = 0;
  162. int tax = 0;
  163. // Check for buylist validity and calculates summary values
  164. long slots = 0;
  165. long weight = 0;
  166. for (int i = 0; i < _count; i++)
  167. {
  168. int itemId = _items[i * 2 + 0];
  169. int count = _items[i * 2 + 1];
  170. int price = -1;
  171. if (!list.containsItemId(itemId))
  172. {
  173. Util.handleIllegalPlayerAction(player,"Warning!! Character "+player.getName()+" of account "+player.getAccountName()+" sent a false BuyList list_id.",Config.DEFAULT_PUNISH);
  174. return;
  175. }
  176. L2Item template = ItemTable.getInstance().getTemplate(itemId);
  177. if (template == null) continue;
  178. if (count > Integer.MAX_VALUE || (!template.isStackable() && count > 1))
  179. {
  180. Util.handleIllegalPlayerAction(player,"Warning!! Character "+player.getName()+" of account "+player.getAccountName()+" tried to purchase invalid quantity of items at the same time.",Config.DEFAULT_PUNISH);
  181. SystemMessage sm = new SystemMessage(SystemMessageId.YOU_HAVE_EXCEEDED_QUANTITY_THAT_CAN_BE_INPUTTED);
  182. sendPacket(sm);
  183. sm = null;
  184. return;
  185. }
  186. if (_listId < 1000000)
  187. {
  188. //list = TradeController.getInstance().getBuyList(_listId);
  189. price = list.getPriceForItemId(itemId);
  190. if (itemId >= 3960 && itemId <= 4026) price *= Config.RATE_SIEGE_GUARDS_PRICE;
  191. }
  192. /* TODO: Disabled until Leaseholders are rewritten ;-)
  193. } else {
  194. L2ItemInstance li = merchant.findLeaseItem(itemId, 0);
  195. if (li == null || li.getCount() < cnt) {
  196. cnt = li.getCount();
  197. if (cnt <= 0) {
  198. items.remove(i);
  199. continue;
  200. }
  201. items.get(i).setCount((int)cnt);
  202. }
  203. price = li.getPriceToSell(); // lease holder sells the item
  204. weight = li.getItem().getWeight();
  205. }
  206. */
  207. if (price < 0)
  208. {
  209. _log.warning("ERROR, no price found .. wrong buylist ??");
  210. sendPacket(new ActionFailed());
  211. return;
  212. }
  213. if(price == 0 && !player.isGM() && Config.ONLY_GM_ITEMS_FREE)
  214. {
  215. player.sendMessage("Ohh Cheat dont work? You have a problem now!");
  216. Util.handleIllegalPlayerAction(player,"Warning!! Character "+player.getName()+" of account "+player.getAccountName()+" tried buy item for 0 adena.", Config.DEFAULT_PUNISH);
  217. return;
  218. }
  219. subTotal += (long)count * price; // Before tax
  220. tax = (int)(subTotal * taxRate);
  221. if (subTotal + tax > Integer.MAX_VALUE)
  222. {
  223. Util.handleIllegalPlayerAction(player,"Warning!! Character "+player.getName()+" of account "+player.getAccountName()+" tried to purchase over "+Integer.MAX_VALUE+" adena worth of goods.", Config.DEFAULT_PUNISH);
  224. return;
  225. }
  226. weight += (long)count * template.getWeight();
  227. if (!template.isStackable()) slots += count;
  228. else if (player.getInventory().getItemByItemId(itemId) == null) slots++;
  229. }
  230. if (weight > Integer.MAX_VALUE || weight < 0 || !player.getInventory().validateWeight((int)weight))
  231. {
  232. sendPacket(new SystemMessage(SystemMessageId.WEIGHT_LIMIT_EXCEEDED));
  233. return;
  234. }
  235. if (slots > Integer.MAX_VALUE || slots < 0 || !player.getInventory().validateCapacity((int)slots))
  236. {
  237. sendPacket(new SystemMessage(SystemMessageId.SLOTS_FULL));
  238. return;
  239. }
  240. // Charge buyer and add tax to castle treasury if not owned by npc clan
  241. if ((subTotal < 0) || !player.reduceAdena("Buy", (int)(subTotal + tax), player.getLastFolkNPC(), false))
  242. {
  243. sendPacket(new SystemMessage(SystemMessageId.YOU_NOT_ENOUGH_ADENA));
  244. return;
  245. }
  246. if (merchant != null && merchant.getIsInTown() && merchant.getCastle().getOwnerId() > 0)
  247. merchant.getCastle().addToTreasury(tax);
  248. // Proceed the purchase
  249. for (int i=0; i < _count; i++)
  250. {
  251. int itemId = _items[i * 2 + 0];
  252. int count = _items[i * 2 + 1];
  253. if (count < 0) count = 0;
  254. if (!list.containsItemId(itemId))
  255. {
  256. Util.handleIllegalPlayerAction(player,"Warning!! Character "+player.getName()+" of account "+player.getAccountName()+" sent a false BuyList list_id.",Config.DEFAULT_PUNISH);
  257. return;
  258. }
  259. if(list.countDecrease(itemId))
  260. list.decreaseCount(itemId,count);
  261. // Add item to Inventory and adjust update packet
  262. player.getInventory().addItem("Buy", itemId, count, player, merchant);
  263. /* TODO: Disabled until Leaseholders are rewritten ;-)
  264. // Update Leaseholder list
  265. if (_listId >= 1000000)
  266. {
  267. L2ItemInstance li = merchant.findLeaseItem(item.getItemId(), 0);
  268. if (li == null)
  269. continue;
  270. if (li.getCount() < item.getCount())
  271. item.setCount(li.getCount());
  272. li.setCount(li.getCount() - item.getCount());
  273. li.updateDatabase();
  274. price = item.getCount() + li.getPriceToSell();
  275. L2ItemInstance la = merchant.getLeaseAdena();
  276. la.setCount(la.getCount() + price);
  277. la.updateDatabase();
  278. player.getInventory().addItem(item);
  279. item.updateDatabase();
  280. }
  281. */
  282. }
  283. if (merchant != null)
  284. {
  285. String html = HtmCache.getInstance().getHtm("data/html/"+ htmlFolder +"/" + merchant.getNpcId() + "-bought.htm");
  286. if (html != null)
  287. {
  288. NpcHtmlMessage boughtMsg = new NpcHtmlMessage(merchant.getObjectId());
  289. boughtMsg.setHtml(html.replaceAll("%objectId%", String.valueOf(merchant.getObjectId())));
  290. player.sendPacket(boughtMsg);
  291. }
  292. }
  293. StatusUpdate su = new StatusUpdate(player.getObjectId());
  294. su.addAttribute(StatusUpdate.CUR_LOAD, player.getCurrentLoad());
  295. player.sendPacket(su);
  296. player.sendPacket(new ItemList(player, true));
  297. }
  298. /* (non-Javadoc)
  299. * @see net.sf.l2j.gameserver.clientpackets.ClientBasePacket#getType()
  300. */
  301. @Override
  302. public String getType()
  303. {
  304. return _C__1F_REQUESTBUYITEM;
  305. }
  306. }