RequestSendPost.java 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  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.network.clientpackets;
  20. import static com.l2jserver.gameserver.model.itemcontainer.Inventory.ADENA_ID;
  21. import static com.l2jserver.gameserver.model.itemcontainer.Inventory.MAX_ADENA;
  22. import com.l2jserver.Config;
  23. import com.l2jserver.gameserver.data.sql.impl.CharNameTable;
  24. import com.l2jserver.gameserver.data.xml.impl.AdminData;
  25. import com.l2jserver.gameserver.enums.PrivateStoreType;
  26. import com.l2jserver.gameserver.instancemanager.MailManager;
  27. import com.l2jserver.gameserver.model.BlockList;
  28. import com.l2jserver.gameserver.model.L2AccessLevel;
  29. import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
  30. import com.l2jserver.gameserver.model.entity.Message;
  31. import com.l2jserver.gameserver.model.itemcontainer.Mail;
  32. import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
  33. import com.l2jserver.gameserver.model.zone.ZoneId;
  34. import com.l2jserver.gameserver.network.SystemMessageId;
  35. import com.l2jserver.gameserver.network.serverpackets.ExNoticePostSent;
  36. import com.l2jserver.gameserver.network.serverpackets.InventoryUpdate;
  37. import com.l2jserver.gameserver.network.serverpackets.ItemList;
  38. import com.l2jserver.gameserver.network.serverpackets.StatusUpdate;
  39. import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
  40. import com.l2jserver.util.StringUtil;
  41. /**
  42. * @author Migi, DS
  43. */
  44. public final class RequestSendPost extends L2GameClientPacket
  45. {
  46. private static final String _C__D0_66_REQUESTSENDPOST = "[C] D0:66 RequestSendPost";
  47. private static final int BATCH_LENGTH = 12; // length of the one item
  48. private static final int MAX_RECV_LENGTH = 16;
  49. private static final int MAX_SUBJ_LENGTH = 128;
  50. private static final int MAX_TEXT_LENGTH = 512;
  51. private static final int MAX_ATTACHMENTS = 8;
  52. private static final int INBOX_SIZE = 240;
  53. private static final int OUTBOX_SIZE = 240;
  54. private static final int MESSAGE_FEE = 100;
  55. private static final int MESSAGE_FEE_PER_SLOT = 1000; // 100 adena message fee + 1000 per each item slot
  56. private String _receiver;
  57. private boolean _isCod;
  58. private String _subject;
  59. private String _text;
  60. private AttachmentItem _items[] = null;
  61. private long _reqAdena;
  62. public RequestSendPost()
  63. {
  64. }
  65. @Override
  66. protected void readImpl()
  67. {
  68. _receiver = readS();
  69. _isCod = readD() == 0 ? false : true;
  70. _subject = readS();
  71. _text = readS();
  72. int attachCount = readD();
  73. if ((attachCount < 0) || (attachCount > Config.MAX_ITEM_IN_PACKET) || (((attachCount * BATCH_LENGTH) + 8) != _buf.remaining()))
  74. {
  75. return;
  76. }
  77. if (attachCount > 0)
  78. {
  79. _items = new AttachmentItem[attachCount];
  80. for (int i = 0; i < attachCount; i++)
  81. {
  82. int objectId = readD();
  83. long count = readQ();
  84. if ((objectId < 1) || (count < 0))
  85. {
  86. _items = null;
  87. return;
  88. }
  89. _items[i] = new AttachmentItem(objectId, count);
  90. }
  91. }
  92. _reqAdena = readQ();
  93. }
  94. @Override
  95. public void runImpl()
  96. {
  97. if (!Config.ALLOW_MAIL)
  98. {
  99. return;
  100. }
  101. final L2PcInstance activeChar = getClient().getActiveChar();
  102. if (activeChar == null)
  103. {
  104. return;
  105. }
  106. if (!Config.ALLOW_ATTACHMENTS)
  107. {
  108. _items = null;
  109. _isCod = false;
  110. _reqAdena = 0;
  111. }
  112. if (!activeChar.getAccessLevel().allowTransaction())
  113. {
  114. activeChar.sendMessage("Transactions are disabled for your Access Level.");
  115. return;
  116. }
  117. if (!activeChar.isInsideZone(ZoneId.PEACE) && (_items != null))
  118. {
  119. activeChar.sendPacket(SystemMessageId.CANT_FORWARD_NOT_IN_PEACE_ZONE);
  120. return;
  121. }
  122. if (activeChar.getActiveTradeList() != null)
  123. {
  124. activeChar.sendPacket(SystemMessageId.CANT_FORWARD_DURING_EXCHANGE);
  125. return;
  126. }
  127. if (activeChar.isEnchanting())
  128. {
  129. activeChar.sendPacket(SystemMessageId.CANT_FORWARD_DURING_ENCHANT);
  130. return;
  131. }
  132. if (activeChar.getPrivateStoreType() != PrivateStoreType.NONE)
  133. {
  134. activeChar.sendPacket(SystemMessageId.CANT_FORWARD_PRIVATE_STORE);
  135. return;
  136. }
  137. if (_receiver.length() > MAX_RECV_LENGTH)
  138. {
  139. activeChar.sendPacket(SystemMessageId.ALLOWED_LENGTH_FOR_RECIPIENT_EXCEEDED);
  140. return;
  141. }
  142. if (_subject.length() > MAX_SUBJ_LENGTH)
  143. {
  144. activeChar.sendPacket(SystemMessageId.ALLOWED_LENGTH_FOR_TITLE_EXCEEDED);
  145. return;
  146. }
  147. if (_text.length() > MAX_TEXT_LENGTH)
  148. {
  149. // not found message for this
  150. activeChar.sendPacket(SystemMessageId.ALLOWED_LENGTH_FOR_TITLE_EXCEEDED);
  151. return;
  152. }
  153. if ((_items != null) && (_items.length > MAX_ATTACHMENTS))
  154. {
  155. activeChar.sendPacket(SystemMessageId.ITEM_SELECTION_POSSIBLE_UP_TO_8);
  156. return;
  157. }
  158. if ((_reqAdena < 0) || (_reqAdena > MAX_ADENA))
  159. {
  160. return;
  161. }
  162. if (_isCod)
  163. {
  164. if (_reqAdena == 0)
  165. {
  166. activeChar.sendPacket(SystemMessageId.PAYMENT_AMOUNT_NOT_ENTERED);
  167. return;
  168. }
  169. if ((_items == null) || (_items.length == 0))
  170. {
  171. activeChar.sendPacket(SystemMessageId.PAYMENT_REQUEST_NO_ITEM);
  172. return;
  173. }
  174. }
  175. final int receiverId = CharNameTable.getInstance().getIdByName(_receiver);
  176. if (receiverId <= 0)
  177. {
  178. activeChar.sendPacket(SystemMessageId.RECIPIENT_NOT_EXIST);
  179. return;
  180. }
  181. if (receiverId == activeChar.getObjectId())
  182. {
  183. activeChar.sendPacket(SystemMessageId.YOU_CANT_SEND_MAIL_TO_YOURSELF);
  184. return;
  185. }
  186. final int level = CharNameTable.getInstance().getAccessLevelById(receiverId);
  187. final L2AccessLevel accessLevel = AdminData.getInstance().getAccessLevel(level);
  188. if (accessLevel.isGm() && !activeChar.getAccessLevel().isGm())
  189. {
  190. SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.CANNOT_MAIL_GM_C1);
  191. sm.addString(_receiver);
  192. activeChar.sendPacket(sm);
  193. return;
  194. }
  195. if (activeChar.isJailed() && ((Config.JAIL_DISABLE_TRANSACTION && (_items != null)) || Config.JAIL_DISABLE_CHAT))
  196. {
  197. activeChar.sendPacket(SystemMessageId.CANT_FORWARD_NOT_IN_PEACE_ZONE);
  198. return;
  199. }
  200. if (BlockList.isInBlockList(receiverId, activeChar.getObjectId()))
  201. {
  202. SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.C1_BLOCKED_YOU_CANNOT_MAIL);
  203. sm.addString(_receiver);
  204. activeChar.sendPacket(sm);
  205. return;
  206. }
  207. if (MailManager.getInstance().getOutboxSize(activeChar.getObjectId()) >= OUTBOX_SIZE)
  208. {
  209. activeChar.sendPacket(SystemMessageId.CANT_FORWARD_MAIL_LIMIT_EXCEEDED);
  210. return;
  211. }
  212. if (MailManager.getInstance().getInboxSize(receiverId) >= INBOX_SIZE)
  213. {
  214. activeChar.sendPacket(SystemMessageId.CANT_FORWARD_MAIL_LIMIT_EXCEEDED);
  215. return;
  216. }
  217. if (!getClient().getFloodProtectors().getSendMail().tryPerformAction("sendmail"))
  218. {
  219. activeChar.sendPacket(SystemMessageId.CANT_FORWARD_LESS_THAN_MINUTE);
  220. return;
  221. }
  222. Message msg = new Message(activeChar.getObjectId(), receiverId, _isCod, _subject, _text, _reqAdena);
  223. if (removeItems(activeChar, msg))
  224. {
  225. MailManager.getInstance().sendMessage(msg);
  226. activeChar.sendPacket(ExNoticePostSent.valueOf(true));
  227. activeChar.sendPacket(SystemMessageId.MAIL_SUCCESSFULLY_SENT);
  228. }
  229. }
  230. private final boolean removeItems(L2PcInstance player, Message msg)
  231. {
  232. long currentAdena = player.getAdena();
  233. long fee = MESSAGE_FEE;
  234. if (_items != null)
  235. {
  236. for (AttachmentItem i : _items)
  237. {
  238. // Check validity of requested item
  239. L2ItemInstance item = player.checkItemManipulation(i.getObjectId(), i.getCount(), "attach");
  240. if ((item == null) || !item.isTradeable() || item.isEquipped())
  241. {
  242. player.sendPacket(SystemMessageId.CANT_FORWARD_BAD_ITEM);
  243. return false;
  244. }
  245. fee += MESSAGE_FEE_PER_SLOT;
  246. if (item.getId() == ADENA_ID)
  247. {
  248. currentAdena -= i.getCount();
  249. }
  250. }
  251. }
  252. // Check if enough adena and charge the fee
  253. if ((currentAdena < fee) || !player.reduceAdena("MailFee", fee, null, false))
  254. {
  255. player.sendPacket(SystemMessageId.CANT_FORWARD_NO_ADENA);
  256. return false;
  257. }
  258. if (_items == null)
  259. {
  260. return true;
  261. }
  262. Mail attachments = msg.createAttachments();
  263. // message already has attachments ? oO
  264. if (attachments == null)
  265. {
  266. return false;
  267. }
  268. final StringBuilder recv = new StringBuilder(32);
  269. StringUtil.append(recv, msg.getReceiverName(), "[", String.valueOf(msg.getReceiverId()), "]");
  270. final String receiver = recv.toString();
  271. // Proceed to the transfer
  272. InventoryUpdate playerIU = Config.FORCE_INVENTORY_UPDATE ? null : new InventoryUpdate();
  273. for (AttachmentItem i : _items)
  274. {
  275. // Check validity of requested item
  276. L2ItemInstance oldItem = player.checkItemManipulation(i.getObjectId(), i.getCount(), "attach");
  277. if ((oldItem == null) || !oldItem.isTradeable() || oldItem.isEquipped())
  278. {
  279. _log.warning("Error adding attachment for char " + player.getName() + " (olditem == null)");
  280. return false;
  281. }
  282. final L2ItemInstance newItem = player.getInventory().transferItem("SendMail", i.getObjectId(), i.getCount(), attachments, player, receiver);
  283. if (newItem == null)
  284. {
  285. _log.warning("Error adding attachment for char " + player.getName() + " (newitem == null)");
  286. continue;
  287. }
  288. newItem.setItemLocation(newItem.getItemLocation(), msg.getId());
  289. if (playerIU != null)
  290. {
  291. if ((oldItem.getCount() > 0) && (oldItem != newItem))
  292. {
  293. playerIU.addModifiedItem(oldItem);
  294. }
  295. else
  296. {
  297. playerIU.addRemovedItem(oldItem);
  298. }
  299. }
  300. }
  301. // Send updated item list to the player
  302. if (playerIU != null)
  303. {
  304. player.sendPacket(playerIU);
  305. }
  306. else
  307. {
  308. player.sendPacket(new ItemList(player, false));
  309. }
  310. // Update current load status on player
  311. StatusUpdate su = new StatusUpdate(player);
  312. su.addAttribute(StatusUpdate.CUR_LOAD, player.getCurrentLoad());
  313. player.sendPacket(su);
  314. return true;
  315. }
  316. private static class AttachmentItem
  317. {
  318. private final int _objectId;
  319. private final long _count;
  320. public AttachmentItem(int id, long num)
  321. {
  322. _objectId = id;
  323. _count = num;
  324. }
  325. public int getObjectId()
  326. {
  327. return _objectId;
  328. }
  329. public long getCount()
  330. {
  331. return _count;
  332. }
  333. }
  334. @Override
  335. public String getType()
  336. {
  337. return _C__D0_66_REQUESTSENDPOST;
  338. }
  339. @Override
  340. protected boolean triggersOnActionRequest()
  341. {
  342. return false;
  343. }
  344. }