Advertisement
Guest User

kapuk99

a guest
Dec 31st, 2009
140
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 173.90 KB | None | 0 0
  1.  
  2. package net.sf.odinms.tools;
  3.  
  4. import java.awt.Point;
  5. import java.net.InetAddress;
  6. import java.util.ArrayList;
  7. import java.util.Collection;
  8. import java.util.Collections;
  9. import java.util.Comparator;
  10. import java.util.LinkedHashMap;
  11. import java.util.List;
  12. import java.util.Map;
  13. import java.util.Random;
  14. import java.util.Set;
  15. import java.util.Map.Entry;
  16. import java.sql.Connection;
  17. import java.sql.PreparedStatement;
  18. import java.sql.ResultSet;
  19. import java.sql.SQLException;
  20.  
  21. import org.slf4j.Logger;
  22. import org.slf4j.LoggerFactory;
  23.  
  24. import net.sf.odinms.client.BuddylistEntry;
  25. import net.sf.odinms.client.IEquip;
  26. import net.sf.odinms.client.IItem;
  27. import net.sf.odinms.client.ISkill;
  28. import net.sf.odinms.client.Item;
  29. import net.sf.odinms.client.MapleBuffStat;
  30. import net.sf.odinms.client.MapleCharacter;
  31. import net.sf.odinms.client.MapleClient;
  32. import net.sf.odinms.client.MapleInventory;
  33. import net.sf.odinms.client.MapleInventoryType;
  34. import net.sf.odinms.client.MapleKeyBinding;
  35. import net.sf.odinms.client.MaplePet;
  36. import net.sf.odinms.client.MapleQuestStatus;
  37. import net.sf.odinms.client.MapleStat;
  38. import net.sf.odinms.client.IEquip.ScrollResult;
  39. import net.sf.odinms.client.MapleDisease;
  40. import net.sf.odinms.client.MapleJob;
  41. import net.sf.odinms.client.SkillFactory;
  42. import net.sf.odinms.client.SkillMacro;
  43. import net.sf.odinms.client.status.MonsterStatus;
  44. import net.sf.odinms.database.DatabaseConnection;
  45. import net.sf.odinms.net.ByteArrayMaplePacket;
  46. import net.sf.odinms.net.MaplePacket;
  47. import net.sf.odinms.net.SendPacketOpcode;
  48. import net.sf.odinms.net.channel.handler.AbstractDealDamageHandler;
  49. import net.sf.odinms.net.channel.handler.SummonDamageHandler.SummonAttackEntry;
  50. import net.sf.odinms.net.world.MapleParty;
  51. import net.sf.odinms.net.world.MaplePartyCharacter;
  52. import net.sf.odinms.net.world.PartyOperation;
  53. import net.sf.odinms.server.constants.Items;
  54. import net.sf.odinms.server.MapleItemInformationProvider;
  55. import net.sf.odinms.server.MaplePlayerShop;
  56. import net.sf.odinms.server.MaplePlayerShopItem;
  57. import net.sf.odinms.server.MapleShopItem;
  58. import net.sf.odinms.server.MapleTrade;
  59. import net.sf.odinms.server.life.MapleMonster;
  60. import net.sf.odinms.server.life.MapleNPC;
  61. import net.sf.odinms.server.maps.MapleMap;
  62. import net.sf.odinms.server.maps.MapleReactor;
  63. import net.sf.odinms.server.movement.LifeMovementFragment;
  64. import net.sf.odinms.tools.data.output.LittleEndianWriter;
  65. import net.sf.odinms.tools.data.output.MaplePacketLittleEndianWriter;
  66. import net.sf.odinms.net.world.guild.*;
  67. import net.sf.odinms.server.life.MobSkill;
  68. import net.sf.odinms.server.CashItemInfo;
  69. import net.sf.odinms.server.maps.MapleMist;
  70. import java.util.Iterator;
  71. import net.sf.odinms.server.maps.MapleSummon;
  72.  
  73. /**
  74.  * Provides all MapleStory packets needed in one place.
  75.  *
  76.  * @author Frz
  77.  * @since Revision 259
  78.  * @version 1.0
  79.  */
  80. public class MaplePacketCreator {
  81.     private static Logger log = LoggerFactory.getLogger(MaplePacketCreator.class);
  82.     private final static byte[] CHAR_INFO_MAGIC = new byte[]{(byte) 0xff, (byte) 0xc9, (byte) 0x9a, 0x3b};
  83.     private final static byte[] ITEM_MAGIC = new byte[]{(byte) 0x80, 5};
  84.     public static final List<Pair<MapleStat, Integer>> EMPTY_STATUPDATE = Collections.emptyList();
  85.     private final static long FT_UT_OFFSET = 116444592000000000L;
  86.     //private final static long NO_EXPIRATION = 150842304000000000L;
  87.  
  88.     private static long getKoreanTimestamp(long realTimestamp) {
  89.         long time = (realTimestamp / 1000 / 60); //convert to minutes
  90.  
  91.         return ((time * 600000000) + FT_UT_OFFSET);
  92.     }
  93.  
  94.     private static long getTime(long realTimestamp) {
  95.         long time = (realTimestamp / 1000); // convert to seconds
  96.  
  97.         return ((time * 10000000) + FT_UT_OFFSET);
  98.     }
  99.  
  100.     /**
  101.      * Sends a hello packet.
  102.      *
  103.      * @param mapleVersion The maple client version.
  104.      * @param sendIv the IV used by the server for sending
  105.      * @param recvIv the IV used by the server for receiving
  106.      */
  107.     public static MaplePacket getHello(short mapleVersion, byte[] sendIv, byte[] recvIv, boolean testServer) {
  108.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(16);
  109.         mplew.writeShort(0x0d);
  110.         mplew.writeShort(mapleVersion);
  111.         mplew.write(new byte[]{0, 0});
  112.         mplew.write(recvIv);
  113.         mplew.write(sendIv);
  114.         mplew.write(testServer ? 5 : 8);
  115.         return mplew.getPacket();
  116.     }
  117.  
  118.     /**
  119.      * Sends a ping packet.
  120.      *
  121.      * @return The packet.
  122.      */
  123.     public static MaplePacket getPing() {
  124.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(16);
  125.         mplew.writeShort(SendPacketOpcode.PING.getValue());
  126.         return mplew.getPacket();
  127.     }
  128.  
  129.     /**
  130.      * Gets a login failed packet.
  131.      *
  132.      * Possible values for <code>reason</code>:<br>
  133.      * 3: ID deleted or blocked<br>
  134.      * 4: Incorrect password<br>
  135.      * 5: Not a registered id<br>
  136.      * 6: System error<br>
  137.      * 7: Already logged in<br>
  138.      * 8: System error<br>
  139.      * 9: System error<br>
  140.      * 10: Cannot process so many connections<br>
  141.      * 11: Only users older than 20 can use this channel
  142.      *
  143.      * @param reason The reason logging in failed.
  144.      * @return The login failed packet.
  145.      */
  146.     public static MaplePacket getLoginFailed(int reason) {
  147.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(16);
  148.         mplew.writeShort(SendPacketOpcode.LOGIN_STATUS.getValue());
  149.         mplew.writeInt(reason);
  150.         mplew.writeShort(0);
  151.  
  152.         return mplew.getPacket();
  153.     }
  154.  
  155.     public static MaplePacket getPermBan(byte reason) {
  156.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(16);
  157.         // Response.WriteHexString("00 00 02 00 01 01 01 01 01 00");
  158.         mplew.writeShort(SendPacketOpcode.LOGIN_STATUS.getValue());
  159.         mplew.writeShort(0x02); // Account is banned
  160.  
  161.         mplew.write(0x0);
  162.         mplew.write(reason);
  163.         mplew.write(HexTool.getByteArrayFromHexString("01 01 01 01 00"));
  164.         return mplew.getPacket();
  165.     }
  166.  
  167.     public static MaplePacket getTempBan(long timestampTill, byte reason) {
  168.  
  169.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(17);
  170.         mplew.writeShort(SendPacketOpcode.LOGIN_STATUS.getValue());
  171.         mplew.write(0x02);
  172.         mplew.write(HexTool.getByteArrayFromHexString("00 00 00 00 00")); // Account is banned
  173.  
  174.         mplew.write(reason);
  175.         mplew.writeLong(timestampTill); // Tempban date is handled as a 64-bit long, number of 100NS intervals since
  176.         // 1/1/1601. Lulz.
  177.  
  178.         return mplew.getPacket();
  179.     }
  180.  
  181.     /**
  182.      * Gets a successful authentication and PIN Request packet.
  183.      *
  184.      * @param account The account name.
  185.      * @return The PIN request packet.
  186.      */
  187.     public static MaplePacket getAuthSuccessRequestPin(String account, boolean gm) {
  188.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  189.  
  190.         mplew.writeShort(SendPacketOpcode.LOGIN_STATUS.getValue());
  191.         mplew.writeInt(0);
  192.         mplew.writeShort(0);
  193.         mplew.writeInt(0); //user id
  194.         mplew.write(0); //gender (0x0a == gender select, 0x0b == pin select)
  195.         mplew.write(gm ? 1 : 0);
  196.         mplew.write(0); //admin, doesn't let them chat
  197.         mplew.write(0);
  198.         mplew.writeMapleAsciiString(account);
  199.         mplew.write(0);
  200.         mplew.write(0);
  201.         mplew.writeLong(0);
  202.         mplew.writeLong(0); //creation time
  203.  
  204.         mplew.writeInt(0);
  205.  
  206.         return mplew.getPacket();
  207.     }
  208.  
  209.     /**
  210.      * Gets a packet detailing a PIN operation.
  211.      *
  212.      * Possible values for <code>mode</code>:<br>
  213.      * 0 - PIN was accepted<br>
  214.      * 1 - Register a new PIN<br>
  215.      * 2 - Invalid pin / Reenter<br>
  216.      * 3 - Connection failed due to system error<br>
  217.      * 4 - Enter the pin
  218.      *
  219.      * @param mode The mode.
  220.      */
  221.     public static MaplePacket pinOperation(byte mode) {
  222.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(3);
  223.         mplew.writeShort(SendPacketOpcode.PIN_OPERATION.getValue());
  224.         mplew.write(mode);
  225.         return mplew.getPacket();
  226.     }
  227.  
  228.     /**
  229.      * Gets a packet requesting the client enter a PIN.
  230.      *
  231.      * @return The request PIN packet.
  232.      */
  233.     public static MaplePacket requestPin() {
  234.         return pinOperation((byte) 4);
  235.     }
  236.  
  237.     /**
  238.      * Gets a packet requesting the PIN after a failed attempt.
  239.      *
  240.      * @return The failed PIN packet.
  241.      */
  242.     public static MaplePacket requestPinAfterFailure() {
  243.         return pinOperation((byte) 2);
  244.     }
  245.  
  246.     /**
  247.      * Gets a packet saying the PIN has been accepted.
  248.      *
  249.      * @return The PIN accepted packet.
  250.      */
  251.     public static MaplePacket pinAccepted() {
  252.         return pinOperation((byte) 0);
  253.     }
  254.  
  255.     /**
  256.      * Gets a packet detailing a server and its channels.
  257.      *
  258.      * @param serverIndex The index of the server to create information about.
  259.      * @param serverName The name of the server.
  260.      * @param channelLoad Load of the channel - 1200 seems to be max.
  261.      * @return The server info packet.
  262.      */
  263.     public static MaplePacket getServerList(int serverIndex, String serverName, Map<Integer, Integer> channelLoad) {
  264.         /*
  265.          * 0B 00 00 06 00 53 63 61 6E 69 61 00 00 00 64 00 64 00 00 13 08 00 53 63 61 6E 69 61 2D 31 5E 04 00 00 00 00
  266.          * 00 08 00 53 63 61 6E 69 61 2D 32 25 01 00 00 00 01 00 08 00 53 63 61 6E 69 61 2D 33 F6 00 00 00 00 02 00 08
  267.          * 00 53 63 61 6E 69 61 2D 34 BC 00 00 00 00 03 00 08 00 53 63 61 6E 69 61 2D 35 E7 00 00 00 00 04 00 08 00 53
  268.          * 63 61 6E 69 61 2D 36 BC 00 00 00 00 05 00 08 00 53 63 61 6E 69 61 2D 37 C2 00 00 00 00 06 00 08 00 53 63 61
  269.          * 6E 69 61 2D 38 BB 00 00 00 00 07 00 08 00 53 63 61 6E 69 61 2D 39 C0 00 00 00 00 08 00 09 00 53 63 61 6E 69
  270.          * 61 2D 31 30 C3 00 00 00 00 09 00 09 00 53 63 61 6E 69 61 2D 31 31 BB 00 00 00 00 0A 00 09 00 53 63 61 6E 69
  271.          * 61 2D 31 32 AB 00 00 00 00 0B 00 09 00 53 63 61 6E 69 61 2D 31 33 C7 00 00 00 00 0C 00 09 00 53 63 61 6E 69
  272.          * 61 2D 31 34 B9 00 00 00 00 0D 00 09 00 53 63 61 6E 69 61 2D 31 35 AE 00 00 00 00 0E 00 09 00 53 63 61 6E 69
  273.          * 61 2D 31 36 B6 00 00 00 00 0F 00 09 00 53 63 61 6E 69 61 2D 31 37 DB 00 00 00 00 10 00 09 00 53 63 61 6E 69
  274.          * 61 2D 31 38 C7 00 00 00 00 11 00 09 00 53 63 61 6E 69 61 2D 31 39 EF 00 00 00 00 12 00
  275.          */
  276.  
  277.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  278.  
  279.         mplew.writeShort(SendPacketOpcode.SERVERLIST.getValue());
  280.         mplew.write(serverIndex);
  281.         mplew.writeMapleAsciiString(serverName);
  282.         mplew.write(3); // 1: E 2: N 3: H
  283.         // mplew.writeShort(0);
  284.  
  285.         mplew.writeMapleAsciiString("");
  286.         mplew.write(0x64); // rate modifier, don't ask O.O!
  287.  
  288.         mplew.write(0x0); // event xp * 2.6 O.O!
  289.  
  290.         mplew.write(0x64); // rate modifier, don't ask O.O!
  291.  
  292.         mplew.write(0x0); // drop rate * 2.6
  293.  
  294.         mplew.write(0x0);
  295.         int lastChannel = 1;
  296.         Set<Integer> channels = channelLoad.keySet();
  297.         for (int i = 30; i > 0; i--) {
  298.             if (channels.contains(i)) {
  299.                 lastChannel = i;
  300.                 break;
  301.             }
  302.         }
  303.         mplew.write(lastChannel);
  304.  
  305.         int load;
  306.         for (int i = 1; i <= lastChannel; i++) {
  307.             if (channels.contains(i)) {
  308.                 load = channelLoad.get(i);
  309.             } else {
  310.                 load = 1200;
  311.             }
  312.             mplew.writeMapleAsciiString(serverName + "-" + i);
  313.             mplew.writeInt(load);
  314.             mplew.write(serverIndex);
  315.             mplew.writeShort(i - 1);
  316.         }
  317.         mplew.writeShort(0); // ver 0.56
  318.  
  319.         return mplew.getPacket();
  320.     }
  321.  
  322.     /**
  323.      * Gets a packet saying that the server list is over.
  324.      *
  325.      * @return The end of server list packet.
  326.      */
  327.     public static MaplePacket getEndOfServerList() {
  328.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  329.         mplew.writeShort(SendPacketOpcode.SERVERLIST.getValue());
  330.         mplew.write(0xFF);
  331.         return mplew.getPacket();
  332.     }
  333.  
  334.     /**
  335.      * Gets a packet detailing a server status message.
  336.      *
  337.      * Possible values for <code>status</code>:<br>
  338.      * 0 - Normal<br>
  339.      * 1 - Highly populated<br>
  340.      * 2 - Full
  341.      *
  342.      * @param status The server status.
  343.      * @return The server status packet.
  344.      */
  345.     public static MaplePacket getServerStatus(int status) {
  346.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  347.         mplew.writeShort(SendPacketOpcode.SERVERSTATUS.getValue());
  348.         mplew.writeShort(status);
  349.         return mplew.getPacket();
  350.     }
  351.  
  352.     /**
  353.      * Gets a packet telling the client the IP of the channel server.
  354.      *
  355.      * @param inetAddr The InetAddress of the requested channel server.
  356.      * @param port The port the channel is on.
  357.      * @param clientId The ID of the client.
  358.      * @return The server IP packet.
  359.      */
  360.     public static MaplePacket getServerIP(InetAddress inetAddr, int port, int clientId) {
  361.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  362.  
  363.         mplew.writeShort(SendPacketOpcode.SERVER_IP.getValue());
  364.         mplew.writeShort(0);
  365.         byte[] addr = inetAddr.getAddress();
  366.         mplew.write(addr);
  367.         mplew.writeShort(port);
  368.         // 0x13 = numchannels?
  369.         mplew.writeInt(clientId); // this gets repeated to the channel server
  370.         // leos.write(new byte[] { (byte) 0x13, (byte) 0x37, 0x42, 1, 0, 0, 0,
  371.         // 0, 0 });
  372.  
  373.         mplew.write(new byte[]{0, 0, 0, 0, 0});
  374.         // 0D 00 00 00 3F FB D9 0D 8A 21 CB A8 13 00 00 00 00 00 00
  375.         // ....?....!.........
  376.         return mplew.getPacket();
  377.     }
  378.  
  379.     /**
  380.      * Gets a packet telling the client the IP of the new channel.
  381.      *
  382.      * @param inetAddr The InetAddress of the requested channel server.
  383.      * @param port The port the channel is on.
  384.      * @return The server IP packet.
  385.      */
  386.     public static MaplePacket getChannelChange(InetAddress inetAddr, int port) {
  387.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  388.         mplew.writeShort(SendPacketOpcode.CHANGE_CHANNEL.getValue());
  389.         mplew.write(1);
  390.         byte[] addr = inetAddr.getAddress();
  391.         mplew.write(addr);
  392.         mplew.writeShort(port);
  393.         return mplew.getPacket();
  394.     }
  395.  
  396.     /**
  397.      * Gets a packet with a list of characters.
  398.      *
  399.      * @param c The MapleClient to load characters of.
  400.      * @param serverId The ID of the server requested.
  401.      * @return The character list packet.
  402.      */
  403.     public static MaplePacket getCharList(MapleClient c, int serverId) {
  404.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  405.  
  406.         mplew.writeShort(SendPacketOpcode.CHARLIST.getValue());
  407.         mplew.write(0);
  408.         List<MapleCharacter> chars = c.loadCharacters(serverId);
  409.         mplew.write((byte) chars.size());
  410.  
  411.         for (MapleCharacter chr : chars) {
  412.             addCharEntry(mplew, chr);
  413.         }
  414.  
  415.         mplew.writeInt(6);
  416.  
  417.         return mplew.getPacket();
  418.     }
  419.  
  420.     /**
  421.      * Adds character stats to an existing MaplePacketLittleEndianWriter.
  422.      *
  423.      * @param mplew The MaplePacketLittleEndianWrite instance to write the stats
  424.      *            to.
  425.      * @param chr The character to add the stats of.
  426.      */
  427.     private static void addCharStats(MaplePacketLittleEndianWriter mplew, MapleCharacter chr) {
  428.         mplew.writeInt(chr.getId()); // character id
  429.         mplew.writeAsciiString(StringUtil.getRightPaddedStr(chr.getName(), '\0', 13));
  430.         mplew.write(chr.getGender()); // gender (0 = male, 1 = female)
  431.         mplew.write(chr.getSkinColor().getId()); // skin color
  432.         mplew.writeInt(chr.getFace()); // face
  433.         mplew.writeInt(chr.getHair()); // hair
  434.         mplew.writeLong(0);
  435.         mplew.writeLong(0);
  436.         mplew.writeLong(0);
  437.         mplew.write(chr.getLevel()); // level
  438.         mplew.writeShort(chr.getJob().getId()); // job
  439.         mplew.writeShort(chr.getStr()); // str
  440.         mplew.writeShort(chr.getDex()); // dex
  441.         mplew.writeShort(chr.getInt()); // int
  442.         mplew.writeShort(chr.getLuk()); // luk
  443.         mplew.writeShort(chr.getHp()); // hp (?)
  444.         mplew.writeShort(chr.getMaxHp()); // maxhp
  445.         mplew.writeShort(chr.getMp()); // mp (?)
  446.         mplew.writeShort(chr.getMaxMp()); // maxmp
  447.         mplew.writeShort(chr.getRemainingAp()); // remaining ap
  448.         mplew.writeShort(chr.getRemainingSp()); // remaining sp
  449.         mplew.writeInt(chr.getExp()); // current exp
  450.         mplew.writeShort(chr.getFame()); // fame
  451.         mplew.writeInt(0); // Gachapon EXP (Vana says this... WTF?)
  452.         mplew.writeInt(chr.getMapId()); // current map id
  453.         mplew.write(chr.getInitialSpawnpoint()); // spawnpoint
  454.         mplew.writeInt(0);
  455.     }
  456.  
  457.     /**
  458.      * Adds the aesthetic aspects of a character to an existing
  459.      * MaplePacketLittleEndianWriter.
  460.      *
  461.      * @param mplew The MaplePacketLittleEndianWrite instance to write the stats
  462.      *            to.
  463.      * @param chr The character to add the looks of.
  464.      * @param mega Unknown
  465.      */
  466.     private static void addCharLook(MaplePacketLittleEndianWriter mplew, MapleCharacter chr, boolean mega) {
  467.         mplew.write(chr.getGender());
  468.         mplew.write(chr.getSkinColor().getId());
  469.         mplew.writeInt(chr.getFace());
  470.         mplew.write(mega ? 0 : 1);
  471.         mplew.writeInt(chr.getHair());
  472.  
  473.         MapleInventory equip = chr.getInventory(MapleInventoryType.EQUIPPED);
  474.         // Map<Integer, Integer> equipped = new LinkedHashMap<Integer,
  475.         // Integer>();
  476.         Map<Byte, Integer> myEquip = new LinkedHashMap<Byte, Integer>();
  477.         Map<Byte, Integer> maskedEquip = new LinkedHashMap<Byte, Integer>();
  478.         for (IItem item : equip.list()) {
  479.             byte pos = (byte) (item.getPosition() * -1);
  480.             if (pos < 100 && myEquip.get(pos) == null) {
  481.                 myEquip.put(pos, item.getItemId());
  482.             } else if (pos > 100 && pos != 111) {
  483.                 pos -= 100;
  484.                 if (myEquip.get(pos) != null) {
  485.                     maskedEquip.put(pos, myEquip.get(pos));
  486.                 }
  487.                 myEquip.put(pos, item.getItemId());
  488.             } else if (myEquip.get(pos) != null) {
  489.                 maskedEquip.put(pos, item.getItemId());
  490.             }
  491.         }
  492.         for (Entry<Byte, Integer> entry : myEquip.entrySet()) {
  493.             mplew.write(entry.getKey());
  494.             mplew.writeInt(entry.getValue());
  495.         }
  496.         mplew.write(0xFF); // end of visible itens
  497.         // masked itens
  498.  
  499.         for (Entry<Byte, Integer> entry : maskedEquip.entrySet()) {
  500.             mplew.write(entry.getKey());
  501.             mplew.writeInt(entry.getValue());
  502.         }
  503.         /*
  504.          * for (IItem item : equip.list()) { byte pos = (byte)(item.getPosition() * -1); if (pos > 100) {
  505.          * mplew.write(pos - 100); mplew.writeInt(item.getItemId()); } }
  506.          */
  507.         // ending markers
  508.         mplew.write(0xFF);
  509.         IItem cWeapon = equip.getItem((byte) -111);
  510.         mplew.writeInt(cWeapon != null ? cWeapon.getItemId() : 0);
  511.         for (int i = 0; i < 3; i++) {
  512.             if (chr.getPet(i) != null) {
  513.                 mplew.writeInt(chr.getPet(i).getItemId());
  514.             } else {
  515.                 mplew.writeInt(0);
  516.             }
  517.         }
  518.     }
  519.  
  520.     /**
  521.      * Adds an entry for a character to an existing
  522.      * MaplePacketLittleEndianWriter.
  523.      *
  524.      * @param mplew The MaplePacketLittleEndianWrite instance to write the stats
  525.      *            to.
  526.      * @param chr The character to add.
  527.      */
  528.     private static void addCharEntry(MaplePacketLittleEndianWriter mplew, MapleCharacter chr) {
  529.         addCharStats(mplew, chr);
  530.         addCharLook(mplew, chr, false);
  531.         if (chr.getJob().isA(MapleJob.GM)) {
  532.             mplew.write(0);
  533.             return;
  534.         }
  535.         mplew.write(1); // world rank enabled
  536.  
  537.         mplew.writeInt(chr.getRank()); // world rank
  538.  
  539.         mplew.writeInt(chr.getRankMove()); // move (negative is downwards)
  540.  
  541.         mplew.writeInt(chr.getJobRank()); // job rank
  542.  
  543.         mplew.writeInt(chr.getJobRankMove()); // move (negative is downwards)
  544.  
  545.     }
  546.  
  547.     /**
  548.      * Adds a quest info entry for a character to an existing
  549.      * MaplePacketLittleEndianWriter.
  550.      *
  551.      * @param mplew The MaplePacketLittleEndianWrite instance to write the stats
  552.      *            to.
  553.      * @param chr The character to add quest info about.
  554.      */
  555.     private static void addQuestInfo(MaplePacketLittleEndianWriter mplew, MapleCharacter chr) {
  556.         List<MapleQuestStatus> started = chr.getStartedQuests();
  557.         mplew.writeShort(started.size());
  558.         for (MapleQuestStatus q : started) {
  559.             mplew.writeShort(q.getQuest().getId());
  560.             String killStr = "";
  561.             for (int kills : q.getMobKills().values()) {
  562.                 killStr += StringUtil.getLeftPaddedStr(String.valueOf(kills), '0', 3);
  563.             }
  564.             mplew.writeMapleAsciiString(killStr);
  565.         }
  566.         List<MapleQuestStatus> completed = chr.getCompletedQuests();
  567.         mplew.writeShort(completed.size());
  568.         for (MapleQuestStatus q : completed) {
  569.             mplew.writeShort(q.getQuest().getId());
  570.             mplew.writeLong(q.getCompletionTime());
  571.         }
  572.     }
  573.  
  574.     /**
  575.      * Gets character info for a character.
  576.      *
  577.      * @param chr The character to get info about.
  578.      * @return The character info packet.
  579.      */
  580.     public static MaplePacket getCharInfo(MapleCharacter chr) {
  581.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  582.  
  583.         mplew.writeShort(SendPacketOpcode.WARP_TO_MAP.getValue()); // 0x49
  584.         mplew.writeInt(chr.getClient().getChannel() - 1);
  585.         mplew.write(1);
  586.         mplew.write(1);
  587.         mplew.writeShort(0);
  588.         Random rand = new Random();
  589.         mplew.writeInt(rand.nextInt());
  590.         mplew.writeInt(rand.nextInt());
  591.         mplew.writeInt(rand.nextInt());
  592.         mplew.writeLong(-1);
  593.         addCharStats(mplew, chr);
  594.         mplew.write(chr.getBuddylist().getCapacity());
  595.         addInventoryInfo(mplew, chr);
  596.         addSkillInfo(mplew, chr);
  597.         addQuestInfo(mplew, chr);
  598.         mplew.writeInt(0);
  599.         mplew.writeInt(0);
  600.         for (int x = 0; x < 15; x++) {
  601.             //TeleportMaps(5)
  602.             //VIPTeleportMaps(10)
  603.             //NoMap->999999999->CHAR_INFO_MAGIC
  604.             mplew.write(CHAR_INFO_MAGIC);
  605.         }
  606.  
  607.         // Monster Book
  608.         mplew.writeInt(0); // Cover
  609.         mplew.write(0);
  610.         mplew.writeShort(0); // Number of cards
  611.         //  for (MonsterBookEntry card : monsterBook) {
  612.         //      mplew.writeShort(card.getId());
  613.         //      mplew.write(card.getLevel);
  614.         // }
  615.  
  616.         mplew.writeShort(0);
  617.         mplew.writeShort(0); // Number of PQs
  618.         mplew.writeShort(0);
  619.  
  620.         mplew.writeLong(getTime((long) System.currentTimeMillis()));
  621.  
  622.         return mplew.getPacket();
  623.     }
  624.  
  625.     /**
  626.      * Gets an empty stat update.
  627.      *
  628.      * @return The empy stat update packet.
  629.      */
  630.     public static MaplePacket enableActions() {
  631.         return updatePlayerStats(EMPTY_STATUPDATE, true);
  632.     }
  633.  
  634.     /**
  635.      * Gets an update for specified stats.
  636.      *
  637.      * @param stats The stats to update.
  638.      * @return The stat update packet.
  639.      */
  640.     public static MaplePacket updatePlayerStats(List<Pair<MapleStat, Integer>> stats) {
  641.         return updatePlayerStats(stats, false);
  642.     }
  643.  
  644.     /**
  645.      * Gets an update for specified stats.
  646.      *
  647.      * @param stats The list of stats to update.
  648.      * @param itemReaction Result of an item reaction(?)
  649.      * @param pet Result of spawning a pet(?)
  650.      * @return The stat update packet.
  651.      */
  652.     public static MaplePacket updatePlayerStats(List<Pair<MapleStat, Integer>> stats, boolean itemReaction) {
  653.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  654.  
  655.         mplew.writeShort(SendPacketOpcode.UPDATE_STATS.getValue());
  656.         if (itemReaction) {
  657.             mplew.write(1);
  658.         } else {
  659.             mplew.write(0);
  660.         }
  661.         int updateMask = 0;
  662.         for (Pair<MapleStat, Integer> statupdate : stats) {
  663.             updateMask |= statupdate.getLeft().getValue();
  664.         }
  665.         List<Pair<MapleStat, Integer>> mystats = stats;
  666.         if (mystats.size() > 1) {
  667.             Collections.sort(mystats, new Comparator<Pair<MapleStat, Integer>>() {
  668.                 @Override
  669.                 public int compare(Pair<MapleStat, Integer> o1, Pair<MapleStat, Integer> o2) {
  670.                     int val1 = o1.getLeft().getValue();
  671.                     int val2 = o2.getLeft().getValue();
  672.                     return (val1 < val2 ? -1 : (val1 == val2 ? 0 : 1));
  673.                 }
  674.             });
  675.         }
  676.         mplew.writeInt(updateMask);
  677.         for (Pair<MapleStat, Integer> statupdate : mystats) {
  678.             if (statupdate.getLeft().getValue() >= 1) {
  679.                 if (statupdate.getLeft().getValue() == 0x1) {
  680.                     mplew.writeShort(statupdate.getRight().shortValue());
  681.                 } else if (statupdate.getLeft().getValue() <= 0x4) {
  682.                     mplew.writeInt(statupdate.getRight());
  683.                 } else if (statupdate.getLeft().getValue() < 0x20) {
  684.                     mplew.write(statupdate.getRight().shortValue());
  685.                 } else if (statupdate.getLeft().getValue() < 0xFFFF) {
  686.                     mplew.writeShort(statupdate.getRight().shortValue());
  687.                 } else {
  688.                     mplew.writeInt(statupdate.getRight().intValue());
  689.                 }
  690.             }
  691.         }
  692.  
  693.         return mplew.getPacket();
  694.     }
  695.  
  696.     /**
  697.      * Gets a packet telling the client to change maps.
  698.      *
  699.      * @param to The <code>MapleMap</code> to warp to.
  700.      * @param spawnPoint The spawn portal number to spawn at.
  701.      * @param chr The character warping to <code>to</code>
  702.      * @return The map change packet.
  703.      */
  704.     public static MaplePacket getWarpToMap(MapleMap to, int spawnPoint, MapleCharacter chr) {
  705.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  706.  
  707.         mplew.writeShort(SendPacketOpcode.WARP_TO_MAP.getValue()); // 0x49
  708.  
  709.         mplew.writeInt(chr.getClient().getChannel() - 1);
  710.         mplew.writeShort(0x2);
  711.         mplew.writeShort(0);
  712.         mplew.writeInt(to.getId());
  713.         mplew.write(spawnPoint);
  714.         mplew.writeShort(chr.getHp()); // hp (???)
  715.  
  716.         mplew.write(0);
  717.         long questMask = 0x1ffffffffffffffL;
  718.         mplew.writeLong(questMask);
  719.  
  720.         return mplew.getPacket();
  721.     }
  722.  
  723.     /**
  724.      * Gets a packet to spawn a portal.
  725.      *
  726.      * @param townId The ID of the town the portal goes to.
  727.      * @param targetId The ID of the target.
  728.      * @param pos Where to put the portal.
  729.      * @return The portal spawn packet.
  730.      */
  731.     public static MaplePacket spawnPortal(int townId, int targetId, Point pos) {
  732.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  733.         mplew.writeShort(SendPacketOpcode.SPAWN_PORTAL.getValue());
  734.         mplew.writeInt(townId);
  735.         mplew.writeInt(targetId);
  736.         if (pos != null) {
  737.             mplew.writeShort(pos.x);
  738.             mplew.writeShort(pos.y);
  739.         }
  740.         return mplew.getPacket();
  741.     }
  742.  
  743.     /**
  744.      * Gets a packet to spawn a door.
  745.      *
  746.      * @param oid The door's object ID.
  747.      * @param pos The position of the door.
  748.      * @param town
  749.      * @return The remove door packet.
  750.      */
  751.     public static MaplePacket spawnDoor(int oid, Point pos, boolean town) {
  752.         // [D3 00] [01] [93 AC 00 00] [6B 05] [37 03]
  753.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  754.         mplew.writeShort(SendPacketOpcode.SPAWN_DOOR.getValue());
  755.  
  756.         mplew.write(town ? 1 : 0);
  757.         mplew.writeInt(oid);
  758.         mplew.writeShort(pos.x);
  759.         mplew.writeShort(pos.y);
  760.  
  761.         return mplew.getPacket();
  762.     }
  763.  
  764.     /**
  765.      * Gets a packet to remove a door.
  766.      *
  767.      * @param oid The door's ID.
  768.      * @param town
  769.      * @return The remove door packet.
  770.      */
  771.     public static MaplePacket removeDoor(int oid, boolean town) {
  772.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  773.         if (town) {
  774.             mplew.writeShort(SendPacketOpcode.SPAWN_PORTAL.getValue());
  775.             mplew.writeInt(999999999);
  776.             mplew.writeInt(999999999);
  777.         } else {
  778.             mplew.writeShort(SendPacketOpcode.REMOVE_DOOR.getValue());
  779.             mplew.write(/*town ? 1 : */0);
  780.             mplew.writeInt(oid);
  781.         }
  782.         return mplew.getPacket();
  783.     }
  784.  
  785.     /**
  786.      * Gets a packet to spawn a special map object.
  787.      *
  788.      * @param chr The MapleCharacter who spawned the object.
  789.      * @param skill The skill used.
  790.      * @param skillLevel The level of the skill used.
  791.      * @param pos Where the object was spawned.
  792.      * @param movementType Movement type of the object.
  793.      * @param animated Animated spawn?
  794.      * @return The spawn packet for the map object.
  795.      */
  796.     public static MaplePacket spawnSpecialMapObject(MapleSummon summon, int skillLevel, boolean animated) {
  797.         // 72 00 29 1D 02 00 FD FE 30 00 19 7D FF BA 00 04 01 00 03 01 00
  798.         // 85 00 [6A 4D 27 00] [35 1F 00 00] [2D 5D 20 00] [0C] [8C 16] [CA 01] [03] [00] [00] [01] [01] [00]
  799.  
  800.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  801.         mplew.writeShort(SendPacketOpcode.SPAWN_SPECIAL_MAPOBJECT.getValue());
  802.  
  803.         mplew.writeInt(summon.getOwner().getId());
  804.         mplew.writeInt(summon.getObjectId()); // Supposed to be Object ID, but this works too! <3
  805.  
  806.         mplew.writeInt(summon.getSkill());
  807.         mplew.write(skillLevel);
  808.         mplew.writeShort(summon.getPosition().x);
  809.         mplew.writeShort(summon.getPosition().y);
  810.         mplew.write(3); // test
  811.  
  812.         mplew.write(0); // test
  813.  
  814.         mplew.write(0); // test
  815.  
  816.         mplew.write(summon.getMovementType().getValue()); // 0 = don't move, 1 = follow
  817.         // (4th mage summons?), 2/4 =
  818.         // only tele follow, 3 = bird
  819.         // follow
  820.  
  821.         mplew.write(1); // 0 and the summon can't attack - but puppets don't
  822.         // attack with 1 either ^.-
  823.  
  824.         mplew.write(animated ? 0 : 1);
  825.  
  826.         return mplew.getPacket();
  827.     }
  828.  
  829.     /**
  830.      * Gets a packet to remove a special map object.
  831.      *
  832.      * @param chr The MapleCharacter who removed the object.
  833.      * @param skill The skill used to create the object.
  834.      * @param animated Animated removal?
  835.      * @return The packet removing the object.
  836.      */
  837.     public static MaplePacket removeSpecialMapObject(MapleSummon summon, boolean animated) {
  838.         // [86 00] [6A 4D 27 00] 33 1F 00 00 02
  839.         // 92 00 36 1F 00 00 0F 65 85 01 84 02 06 46 28 00 06 81 02 01 D9 00 BD FB D9 00 BD FB 38 04 2F 21 00 00 10 C1 2A 00 06 00 06 01 00 01 BD FB FC 00 BD FB 6A 04 88 1D 00 00 7D 01 AF FB
  840.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  841.         mplew.writeShort(SendPacketOpcode.REMOVE_SPECIAL_MAPOBJECT.getValue());
  842.  
  843.         mplew.writeInt(summon.getOwner().getId());
  844.         mplew.writeInt(summon.getObjectId());
  845.  
  846.         mplew.write(animated ? 4 : 1); // ?
  847.  
  848.         return mplew.getPacket();
  849.     }
  850.  
  851.     private static void addSkillInfo(MaplePacketLittleEndianWriter mplew, MapleCharacter chr) {
  852.         Map<ISkill, MapleCharacter.SkillEntry> skills = chr.getSkills();
  853.         mplew.writeShort(skills.size());
  854.         for (Entry<ISkill, MapleCharacter.SkillEntry> skill : skills.entrySet()) {
  855.             mplew.writeInt(skill.getKey().getId());
  856.             mplew.writeInt(skill.getValue().skillevel);
  857.             if (skill.getKey().isFourthJob()) {
  858.                 mplew.writeInt(skill.getValue().masterlevel);
  859.             }
  860.         }
  861.         mplew.writeShort(0);
  862.     }
  863.  
  864.     private static void addInventoryInfo(MaplePacketLittleEndianWriter mplew, MapleCharacter chr) {
  865.         mplew.writeInt(chr.getMeso());
  866.         mplew.write(chr.getEquipSlots());
  867.         mplew.write(chr.getUseSlots());
  868.         mplew.write(chr.getSetupSlots());
  869.         mplew.write(chr.getEtcSlots());
  870.         mplew.write(chr.getCashSlots());
  871.  
  872.         MapleInventory iv = chr.getInventory(MapleInventoryType.EQUIPPED);
  873.  
  874.         for (IItem item : iv.list()) {
  875.             if (item.getPosition() > -100) {
  876.                 addItemInfo(mplew, item);
  877.             }
  878.         }
  879.         mplew.write(0);
  880.  
  881.         for (IItem item : iv.list()) {
  882.             if (item.getPosition() < -100) {
  883.                 addItemInfo(mplew, item);
  884.             }
  885.         }
  886.         mplew.write(0);
  887.  
  888.         iv = chr.getInventory(MapleInventoryType.EQUIP);
  889.         for (IItem item : iv.list()) {
  890.             addItemInfo(mplew, item);
  891.         }
  892.         mplew.write(0);
  893.  
  894.         iv = chr.getInventory(MapleInventoryType.USE);
  895.         for (IItem item : iv.list()) {
  896.             addItemInfo(mplew, item);
  897.         }
  898.         mplew.write(0);
  899.  
  900.         iv = chr.getInventory(MapleInventoryType.SETUP);
  901.         for (IItem item : iv.list()) {
  902.             addItemInfo(mplew, item);
  903.         }
  904.         mplew.write(0);
  905.  
  906.         iv = chr.getInventory(MapleInventoryType.ETC);
  907.         for (IItem item : iv.list()) {
  908.             addItemInfo(mplew, item);
  909.         }
  910.         mplew.write(0);
  911.  
  912.         iv = chr.getInventory(MapleInventoryType.CASH);
  913.         for (IItem item : iv.list()) {
  914.             if (item.getPetId() > -1) {
  915.                 addPetInfo(mplew, MaplePet.loadFromDb(item.getItemId(), item.getPosition(), item.getPetId()));
  916.             } else {
  917.                 addItemInfo(mplew, item);
  918.             }
  919.         }
  920.         mplew.write(0);
  921.     }
  922.  
  923.     /**
  924.      * Adds info about an item to an existing MaplePacketLittleEndianWriter.
  925.      *
  926.      * @param mplew The MaplePacketLittleEndianWriter to write to.
  927.      * @param item The item to write info about.
  928.      */
  929.     protected static void addItemInfo(MaplePacketLittleEndianWriter mplew, IItem item) {
  930.         addItemInfo(mplew, item, false, false, false);
  931.     }
  932.  
  933.     /**
  934.      * Adds expiration time info to an existing MaplePacketLittleEndianWriter.
  935.      *
  936.      * @param mplew The MaplePacketLittleEndianWriter to write to.
  937.      * @param time The expiration time.
  938.      * @param showexpirationtime Show the expiration time?
  939.      */
  940.     private static void addExpirationTime(MaplePacketLittleEndianWriter mplew, long time, boolean showexpirationtime) {
  941.         mplew.writeInt(KoreanDateUtil.getItemTimestamp(time));
  942.         mplew.write(showexpirationtime ? 1 : 2);
  943.     }
  944.  
  945.     /**
  946.      * Adds item info to existing MaplePacketLittleEndianWriter.
  947.      *
  948.      * @param mplew The MaplePacketLittleEndianWriter to write to.
  949.      * @param item The item to add info about.
  950.      * @param zeroPosition Is the position zero?
  951.      * @param leaveOut Leave out the item if position is zero?
  952.      */
  953.     private static void addItemInfo(MaplePacketLittleEndianWriter mplew, IItem item, boolean zeroPosition, boolean leaveOut, boolean shortSlot) {
  954.         // 01 // 01 // 41 BF 0F 00 // 00 //
  955.         // 00 80 05 BB 46 E6 17 02 //
  956.  
  957.  
  958.         MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
  959.         IEquip equip = null;
  960.         if (item.getType() == IItem.EQUIP) {
  961.             equip = (IEquip) item;
  962.         }
  963.         if (shortSlot) {
  964.             mplew.writeShort(item.getPosition());
  965.         } else if (zeroPosition) {
  966.             if (!leaveOut) {
  967.                 mplew.write(0);
  968.             }
  969.         } else {
  970.             int slot = Math.abs(item.getPosition());
  971.             if (slot > 100) {
  972.                 slot -= 100;
  973.             }
  974.             mplew.write(slot);
  975.         }
  976.  
  977.         mplew.write(item.getType());
  978.         mplew.writeInt(item.getItemId());
  979.         mplew.write(0);
  980.  
  981.         mplew.write(0);
  982.         mplew.write(ITEM_MAGIC);
  983.         addExpirationTime(mplew, 0, false);
  984.  
  985.         if (item.getType() == IItem.EQUIP) {
  986.             mplew.write(equip.getUpgradeSlots());
  987.             mplew.write(equip.getLevel());
  988.             mplew.writeShort(equip.getStr());
  989.             mplew.writeShort(equip.getDex());
  990.             mplew.writeShort(equip.getInt());
  991.             mplew.writeShort(equip.getLuk());
  992.             mplew.writeShort(equip.getHp());
  993.             mplew.writeShort(equip.getMp());
  994.             mplew.writeShort(equip.getWatk());
  995.             mplew.writeShort(equip.getMatk());
  996.             mplew.writeShort(equip.getWdef());
  997.             mplew.writeShort(equip.getMdef());
  998.             mplew.writeShort(equip.getAcc());
  999.             mplew.writeShort(equip.getAvoid());
  1000.             mplew.writeShort(equip.getHands());
  1001.             mplew.writeShort(equip.getSpeed());
  1002.             mplew.writeShort(equip.getJump());
  1003.             mplew.writeMapleAsciiString(equip.getOwner());
  1004.             mplew.writeShort(0); // Flags - Locked/Cold/Spikes/etc
  1005.             mplew.write(0);
  1006.             mplew.write(0); // Item Level
  1007.             mplew.writeShort(0);
  1008.             mplew.writeShort(0); // Item EXP
  1009.             mplew.writeInt(equip.getHammers());
  1010.             mplew.writeLong(-1);
  1011.             mplew.write(HexTool.getByteArrayFromHexString("00 40 E0 FD 3B 37 4F 01"));
  1012.             mplew.writeInt(-1);
  1013.         } else {
  1014.             mplew.writeShort(item.getQuantity());
  1015.             mplew.writeMapleAsciiString(item.getOwner());
  1016.             mplew.writeShort(0); // Flags i.e. locked
  1017.  
  1018.             if (ii.isThrowingStar(item.getItemId()) || ii.isBullet(item.getItemId())) {
  1019.                 mplew.writeLong(0);
  1020.             }
  1021.         }
  1022.     }
  1023.  
  1024.     private static void addPetInfo(MaplePacketLittleEndianWriter mplew, MaplePet pet) {
  1025.         addPetInfo(mplew, pet, false);
  1026.     }
  1027.  
  1028.     private static void addPetInfo(MaplePacketLittleEndianWriter mplew, MaplePet pet, boolean zeroPosition) {
  1029.         mplew.write(zeroPosition ? 0 : pet.getPosition());
  1030.         mplew.write(3);
  1031.         mplew.writeInt(pet.getItemId());
  1032.         mplew.write(1);
  1033.         mplew.writeInt(pet.getUniqueId());
  1034.         mplew.writeInt(0);
  1035.         mplew.write(0);
  1036.         mplew.write(ITEM_MAGIC);
  1037.         addExpirationTime(mplew, 0, false);
  1038.         String petname = pet.getName();
  1039.         if (petname.length() > 13) {
  1040.             petname = petname.substring(0, 13);
  1041.         }
  1042.         mplew.writeAsciiString(StringUtil.getRightPaddedStr(petname, '\0', 13));
  1043.         mplew.write(pet.getLevel());
  1044.         mplew.writeShort(pet.getCloseness());
  1045.         mplew.write(pet.getFullness());
  1046.         mplew.writeLong(getKoreanTimestamp((long) (System.currentTimeMillis() * 1.2)));
  1047.         mplew.writeInt(0);
  1048.         mplew.writeInt(0);
  1049.     }
  1050.  
  1051.     /**
  1052.      * Gets the response to a relog request.
  1053.      *
  1054.      * @return The relog response packet.
  1055.      */
  1056.     public static MaplePacket getRelogResponse() {
  1057.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(3);
  1058.         mplew.writeShort(SendPacketOpcode.RELOG_RESPONSE.getValue());
  1059.         mplew.write(1);
  1060.         return mplew.getPacket();
  1061.     }
  1062.  
  1063.     /**
  1064.      * Gets a server message packet.
  1065.      *
  1066.      * @param message The message to convey.
  1067.      * @return The server message packet.
  1068.      */
  1069.     public static MaplePacket serverMessage(String message) {
  1070.         return serverMessage(4, 0, message, true);
  1071.     }
  1072.  
  1073.     /**
  1074.      * Gets a server notice packet.
  1075.      *
  1076.      * Possible values for <code>type</code>:<br>
  1077.      * 0: [Notice]<br>
  1078.      * 1: Popup<br>
  1079.      * 2: Light blue background and lolwhut<br>
  1080.      * 4: Scrolling message at top<br>
  1081.      * 5: Pink Text<br>
  1082.      * 6: Lightblue Text
  1083.      *
  1084.      * @param type The type of the notice.
  1085.      * @param message The message to convey.
  1086.      * @return The server notice packet.
  1087.      */
  1088.     public static MaplePacket serverNotice(int type, String message) {
  1089.         return serverMessage(type, 0, message, false);
  1090.     }
  1091.  
  1092.     /**
  1093.      * Gets a server notice packet.
  1094.      *
  1095.      * Possible values for <code>type</code>:<br>
  1096.      * 0: [Notice]<br>
  1097.      * 1: Popup<br>
  1098.      * 2: Light blue background and lolwhut<br>
  1099.      * 4: Scrolling message at top<br>
  1100.      * 5: Pink Text<br>
  1101.      * 6: Lightblue Text
  1102.      *
  1103.      * @param type The type of the notice.
  1104.      * @param channel The channel this notice was sent on.
  1105.      * @param message The message to convey.
  1106.      * @return The server notice packet.
  1107.      */
  1108.     public static MaplePacket serverNotice(int type, int channel, String message) {
  1109.         return serverMessage(type, channel, message, false);
  1110.     }
  1111.  
  1112.     /**
  1113.      * Gets a server message packet.
  1114.      *
  1115.      * Possible values for <code>type</code>:<br>
  1116.      * 0: [Notice]<br>
  1117.      * 1: Popup<br>
  1118.      * 2: Light blue background and lolwhut<br>
  1119.      * 4: Scrolling message at top<br>
  1120.      * 5: Pink Text<br>
  1121.      * 6: Lightblue Text
  1122.      * 8: Item Megaphone
  1123.      *
  1124.      * @param type The type of the notice.
  1125.      * @param channel The channel this notice was sent on.
  1126.      * @param message The message to convey.
  1127.      * @param servermessage Is this a scrolling ticker?
  1128.      * @return The server notice packet.
  1129.      */
  1130.     private static MaplePacket serverMessage(int type, int channel, String message, boolean servermessage) {
  1131.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  1132.  
  1133.         // 41 00 //
  1134.         // 08 //
  1135.         // 48 00 // 70 6F 6F 70 6F 6F 31 32 33 20 3A 20 3C 3C 53 65 6C 6C 69 6E 67 20 74 68 65 73 65 20 57 68 69 73 70 20 6F 66 66 65 72 73 20 31 38 30 6D 20 48 2F 4F 20 53 68 65 72 20 69 73 20 6C 61 7A 79 21 21 20 46 61 74 61 6C 3C 33 //
  1136.         // 11 //
  1137.         // 01 //
  1138.  
  1139.         mplew.writeShort(SendPacketOpcode.SERVERMESSAGE.getValue()); // 0.47:
  1140.         // 0x37,
  1141.         // unchanged
  1142.  
  1143.         mplew.write(type);
  1144.         if (servermessage) {
  1145.             mplew.write(1);
  1146.         }
  1147.         mplew.writeMapleAsciiString(message);
  1148.  
  1149.         if (type == 3) {
  1150.             mplew.write(channel - 1);
  1151.             mplew.write(0);
  1152.         } else if (type == 6) {
  1153.             mplew.writeInt(0);
  1154.         } else if (type == 8) {
  1155.             mplew.write(channel - 1);
  1156.             mplew.write(0);
  1157.         }
  1158.  
  1159.         return mplew.getPacket();
  1160.     }
  1161.  
  1162.     /**
  1163.      * Gets a server message packet.
  1164.      *
  1165.      * Possible values for <code>type</code>:<br />
  1166.      * 0: Megaphone<br />
  1167.      * 1: Supermegaphone<br />
  1168.      *
  1169.      *
  1170.      * @param type The type of the notice.
  1171.      * @param channel The channel this notice was sent on.
  1172.      * @param message The message to convey.
  1173.      * @param servermessage Is this a scrolling ticker?
  1174.      * @return The server notice packet.
  1175.      */
  1176.     public static MaplePacket getMegaphone(Items.MegaPhoneType type, int channel, String message, IItem item, boolean showEar) {
  1177.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  1178.         mplew.writeShort(SendPacketOpcode.SERVERMESSAGE.getValue());
  1179.         mplew.write(type.getValue());
  1180.         mplew.writeMapleAsciiString(message);
  1181.         if (type == Items.MegaPhoneType.SUPERMEGAPHONE) {
  1182.             mplew.write(channel - 1);
  1183.             mplew.write(showEar ? 1 : 0);
  1184.         } else if (type == Items.MegaPhoneType.ITEMMEGAPHONE) {
  1185.             mplew.write(channel - 1);
  1186.             mplew.write(showEar ? 1 : 0);
  1187.             if (item != null) {
  1188.                 addItemInfo(mplew, item);
  1189.             } else {
  1190.                 mplew.write(0);
  1191.             }
  1192.         }
  1193.         return mplew.getPacket();
  1194.     }
  1195.  
  1196.     public static MaplePacket getTripleMegaphone(int channel, String[] messages, boolean showEar) {
  1197.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  1198.         mplew.writeShort(SendPacketOpcode.SERVERMESSAGE.getValue());
  1199.         mplew.write(10);
  1200.         if (messages[0] != null) {
  1201.             mplew.writeMapleAsciiString(messages[0]);
  1202.         }
  1203.         mplew.write(messages.length);
  1204.         for (int i = 1; i < messages.length; i++) {
  1205.             if (messages[i] != null) {
  1206.                 mplew.writeMapleAsciiString(messages[i]);
  1207.             }
  1208.         }
  1209.         for (int i = 0; i < 10; i++) {
  1210.             mplew.write(channel - 1);
  1211.         }
  1212.         mplew.write(showEar ? 1 : 0);
  1213.         mplew.write(1);
  1214.         return mplew.getPacket();
  1215.     }
  1216.  
  1217.     /**
  1218.      * Gets an avatar megaphone packet.
  1219.      *
  1220.      * @param chr The character using the avatar megaphone.
  1221.      * @param channel The channel the character is on.
  1222.      * @param itemId The ID of the avatar-mega.
  1223.      * @param message The message that is sent.
  1224.      * @return The avatar mega packet.
  1225.      */
  1226.     public static MaplePacket getAvatarMega(MapleCharacter chr, int channel, int itemId, List<String> message) {
  1227.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  1228.  
  1229.         mplew.writeShort(SendPacketOpcode.AVATAR_MEGA.getValue());
  1230.         mplew.writeInt(itemId);
  1231.         mplew.writeMapleAsciiString(chr.getName());
  1232.         for (String s : message) {
  1233.             mplew.writeMapleAsciiString(s);
  1234.         }
  1235.         mplew.writeInt(channel - 1); // channel
  1236.  
  1237.         mplew.write(0);
  1238.         addCharLook(mplew, chr, true);
  1239.  
  1240.         return mplew.getPacket();
  1241.     }
  1242.  
  1243.     /**
  1244.      * Gets a NPC spawn packet.
  1245.      *
  1246.      * @param life The NPC to spawn.
  1247.      * @param requestController Does the NPC want a controller?
  1248.      * @return The NPC spawn packet.
  1249.      */
  1250.     public static MaplePacket spawnNPC(MapleNPC life, boolean requestController) {
  1251.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  1252.         // Request
  1253.         // E5 00 [01] [7D 01 00 00] [24 71 0F 00] [2B 0D] [8C FF] [01] [3F 00] [F9 0C] [5D 0D] [01]
  1254.         // Spawn
  1255.         // E3 00 [7E 01 00 00] [44 DB 8A 00] [00 02] [9A 00] [01] [77 00] [CE 01] [32 02] [01]
  1256.         if (requestController) {
  1257.             mplew.writeShort(SendPacketOpcode.SPAWN_NPC_REQUEST_CONTROLLER.getValue());
  1258.             mplew.write(1); // ?
  1259.  
  1260.         } else {
  1261.             mplew.writeShort(SendPacketOpcode.SPAWN_NPC.getValue());
  1262.         }
  1263.         mplew.writeInt(life.getObjectId());
  1264.         mplew.writeInt(life.getId());
  1265.         mplew.writeShort(life.getPosition().x);
  1266.         mplew.writeShort(life.getCy());
  1267.         mplew.write(life.getF() == 1 ? 0 : 1); //Facing Left
  1268.  
  1269.         mplew.writeShort(life.getFh());
  1270.         mplew.writeShort(life.getRx0());
  1271.         mplew.writeShort(life.getRx1());
  1272.  
  1273.         mplew.write(1);
  1274.  
  1275.         return mplew.getPacket();
  1276.     }
  1277.  
  1278.     /**
  1279.      * Gets a spawn monster packet.
  1280.      *
  1281.      * @param life The monster to spawn.
  1282.      * @param newSpawn Is it a new spawn?
  1283.      * @return The spawn monster packet.
  1284.      */
  1285.     public static MaplePacket spawnMonster(MapleMonster life, boolean newSpawn) {
  1286.         return spawnMonsterInternal(life, false, newSpawn, false, 0);
  1287.     }
  1288.  
  1289.     /**
  1290.      * Gets a spawn monster packet.
  1291.      *
  1292.      * @param life The monster to spawn.
  1293.      * @param newSpawn Is it a new spawn?
  1294.      * @param effect The spawn effect.
  1295.      * @return The spawn monster packet.
  1296.      */
  1297.     public static MaplePacket spawnMonster(MapleMonster life, boolean newSpawn, int effect) {
  1298.         return spawnMonsterInternal(life, false, newSpawn, false, effect);
  1299.     }
  1300.  
  1301.     /**
  1302.      * Gets a control monster packet.
  1303.      *
  1304.      * @param life The monster to give control to.
  1305.      * @param newSpawn Is it a new spawn?
  1306.      * @param aggro Aggressive monster?
  1307.      * @return The monster control packet.
  1308.      */
  1309.     public static MaplePacket controlMonster(MapleMonster life, boolean newSpawn, boolean aggro) {
  1310.         return spawnMonsterInternal(life, true, newSpawn, aggro, 0);
  1311.     }
  1312.  
  1313.     /**
  1314.      * Internal function to handler monster spawning and controlling.
  1315.      *
  1316.      * @param life The mob to perform operations with.
  1317.      * @param requestController Requesting control of mob?
  1318.      * @param newSpawn New spawn (fade in?)
  1319.      * @param aggro Aggressive mob?
  1320.      * @param effect The spawn effect to use.
  1321.      * @return The spawn/control packet.
  1322.      */
  1323.     private static MaplePacket spawnMonsterInternal(MapleMonster life, boolean requestController, boolean newSpawn,
  1324.             boolean aggro, int effect) {
  1325.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  1326.  
  1327.         if (requestController) {
  1328.             mplew.writeShort(SendPacketOpcode.SPAWN_MONSTER_CONTROL.getValue());
  1329.             if (aggro) {
  1330.                 mplew.write(2);
  1331.             } else {
  1332.                 mplew.write(1);
  1333.             }
  1334.         } else {
  1335.             mplew.writeShort(SendPacketOpcode.SPAWN_MONSTER.getValue());
  1336.         }
  1337.         mplew.writeInt(life.getObjectId());
  1338.         mplew.write(5);
  1339.  
  1340.         mplew.writeInt(life.getId());
  1341.         mplew.writeShort(0);
  1342.         mplew.write(0);
  1343.         mplew.write(8);
  1344.         mplew.writeInt(0);
  1345.  
  1346.         mplew.writeShort(life.getPosition().x);
  1347.         mplew.writeShort(life.getPosition().y);
  1348.         mplew.write(life.getStance()); // or 5? o.O"
  1349.  
  1350.         mplew.writeShort(0); // seems to be left and right
  1351.         // restriction...
  1352.  
  1353.         mplew.writeShort(life.getFh());
  1354.  
  1355.         if (effect > 0) {
  1356.             mplew.write(effect);
  1357.             mplew.write(0);
  1358.             mplew.writeShort(0);
  1359.         }
  1360.  
  1361.         if (newSpawn) {
  1362.             mplew.writeShort(-2);
  1363.         } else {
  1364.             mplew.writeShort(-1);
  1365.         }
  1366.  
  1367.         mplew.writeInt(0);
  1368.  
  1369.         return mplew.getPacket();
  1370.     }
  1371.  
  1372.     /**
  1373.      * Handles spawning monsters that spawn after another is killed
  1374.      * @param life The mob to spawn
  1375.      * @param parent The OID of the parent mob
  1376.      * @return The packet to spawn the mob
  1377.      */
  1378.     public static MaplePacket spawnRevives(MapleMonster life, int parent) {
  1379.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  1380.  
  1381.         mplew.writeShort(SendPacketOpcode.SPAWN_MONSTER.getValue());
  1382.         mplew.writeInt(life.getObjectId());
  1383.         mplew.write(1);
  1384.         mplew.writeInt(life.getId());
  1385.         mplew.write(0); // Status
  1386.  
  1387.         mplew.writeShort(0);
  1388.         mplew.write(8);
  1389.         mplew.writeInt(0);
  1390.         mplew.writeShort(life.getPosition().x);
  1391.         mplew.writeShort(life.getPosition().y);
  1392.         mplew.write(life.getStance());
  1393.         mplew.writeShort(life.getFh());
  1394.         mplew.writeShort(life.getStartFh());
  1395.         mplew.write(0xFD); // FD
  1396.  
  1397.         mplew.writeInt(parent); // oid of the mob that spawned it
  1398.  
  1399.         mplew.writeShort(-1);
  1400.         mplew.writeInt(0);
  1401.  
  1402.         return mplew.getPacket();
  1403.     }
  1404.  
  1405.     /**
  1406.      * Handles monsters not being targettable, such as Zakum's first body.
  1407.      * @param life The mob to spawn as non-targettable.
  1408.      * @param effect The effect to show when spawning.
  1409.      * @return The packet to spawn the mob as non-targettable.
  1410.      */
  1411.     public static MaplePacket spawnFakeMonster(MapleMonster life, int effect) {
  1412.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  1413.  
  1414.         mplew.writeShort(SendPacketOpcode.SPAWN_MONSTER_CONTROL.getValue());
  1415.  
  1416.         mplew.write(1);
  1417.         mplew.writeInt(life.getObjectId());
  1418.         mplew.write(5);
  1419.         mplew.writeInt(life.getId());
  1420.         mplew.writeInt(0);
  1421.         mplew.writeShort(life.getPosition().x);
  1422.         mplew.writeShort(life.getPosition().y);
  1423.         mplew.write(life.getStance());
  1424.         mplew.writeShort(life.getStartFh());
  1425.         mplew.writeShort(life.getFh());
  1426.  
  1427.         if (effect > 0) {
  1428.             mplew.write(effect);
  1429.             mplew.write(0);
  1430.             mplew.writeShort(0);
  1431.         }
  1432.  
  1433.         mplew.writeShort(-2);
  1434.  
  1435.         mplew.writeInt(0);
  1436.  
  1437.         return mplew.getPacket();
  1438.     }
  1439.  
  1440.     /**
  1441.      * Makes a monster previously spawned as non-targettable, targettable.
  1442.      * @param life The mob to make targettable.
  1443.      * @return The packet to make the mob targettable.
  1444.      */
  1445.     public static MaplePacket makeMonsterReal(MapleMonster life) {
  1446.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  1447.         mplew.writeShort(SendPacketOpcode.SPAWN_MONSTER.getValue());
  1448.  
  1449.         mplew.writeInt(life.getObjectId());
  1450.         mplew.write(5);
  1451.         mplew.writeInt(life.getId());
  1452.         mplew.writeInt(0);
  1453.         mplew.writeShort(life.getPosition().x);
  1454.         mplew.writeShort(life.getPosition().y);
  1455.         mplew.write(life.getStance());
  1456.         mplew.writeShort(life.getStartFh());
  1457.         mplew.writeShort(life.getFh());
  1458.         mplew.writeShort(-1);
  1459.  
  1460.         mplew.writeInt(0);
  1461.  
  1462.         return mplew.getPacket();
  1463.     }
  1464.  
  1465.     /**
  1466.      * Gets a stop control monster packet.
  1467.      *
  1468.      * @param oid The ObjectID of the monster to stop controlling.
  1469.      * @return The stop control monster packet.
  1470.      */
  1471.     public static MaplePacket stopControllingMonster(int oid) {
  1472.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  1473.  
  1474.         mplew.writeShort(SendPacketOpcode.SPAWN_MONSTER_CONTROL.getValue());
  1475.         mplew.write(0);
  1476.         mplew.writeInt(oid);
  1477.  
  1478.         return mplew.getPacket();
  1479.     }
  1480.  
  1481.     /**
  1482.      * Gets a response to a move monster packet.
  1483.      *
  1484.      * @param objectid The ObjectID of the monster being moved.
  1485.      * @param moveid The movement ID.
  1486.      * @param currentMp The current MP of the monster.
  1487.      * @param useSkills Can the monster use skills?
  1488.      * @return The move response packet.
  1489.      */
  1490.     public static MaplePacket moveMonsterResponse(int objectid, short moveid, int currentMp, boolean useSkills) {
  1491.         return moveMonsterResponse(objectid, moveid, currentMp, useSkills, 0, 0);
  1492.     }
  1493.  
  1494.     /**
  1495.      * Gets a response to a move monster packet.
  1496.      *
  1497.      * @param objectid The ObjectID of the monster being moved.
  1498.      * @param moveid The movement ID.
  1499.      * @param currentMp The current MP of the monster.
  1500.      * @param useSkills Can the monster use skills?
  1501.      * @param skillId The skill ID for the monster to use.
  1502.      * @param skillLevel The level of the skill to use.
  1503.      * @return The move response packet.
  1504.      */
  1505.     public static MaplePacket moveMonsterResponse(int objectid, short moveid, int currentMp, boolean useSkills, int skillId, int skillLevel) {
  1506.         // A1 00 18 DC 41 00 01 00 00 1E 00 00 00
  1507.         // A1 00 22 22 22 22 01 00 00 00 00 00 00
  1508.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  1509.  
  1510.         mplew.writeShort(SendPacketOpcode.MOVE_MONSTER_RESPONSE.getValue());
  1511.         mplew.writeInt(objectid);
  1512.         mplew.writeShort(moveid);
  1513.         mplew.write(useSkills ? 1 : 0);
  1514.         mplew.writeShort(currentMp);
  1515.         mplew.write(skillId);
  1516.         mplew.write(skillLevel);
  1517.  
  1518.         return mplew.getPacket();
  1519.     }
  1520.  
  1521.     /**
  1522.      * Gets a general chat packet.
  1523.      *
  1524.      * @param cidfrom The character ID who sent the chat.
  1525.      * @param text The text of the chat.
  1526.      * @return The general chat packet.
  1527.      */
  1528.     public static MaplePacket getChatText(int cidfrom, String text, boolean whiteBG, int show) {
  1529.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  1530.  
  1531.         mplew.writeShort(SendPacketOpcode.CHATTEXT.getValue());
  1532.         mplew.writeInt(cidfrom);
  1533.         mplew.write(whiteBG ? 1 : 0);
  1534.         mplew.writeMapleAsciiString(text);
  1535.         mplew.write(show);
  1536.  
  1537.         return mplew.getPacket();
  1538.     }
  1539.  
  1540.     /**
  1541.      * For testing only! Gets a packet from a hexadecimal string.
  1542.      *
  1543.      * @param hex The hexadecimal packet to create.
  1544.      * @return The MaplePacket representing the hex string.
  1545.      */
  1546.     public static MaplePacket getPacketFromHexString(String hex) {
  1547.         byte[] b = HexTool.getByteArrayFromHexString(hex);
  1548.         return new ByteArrayMaplePacket(b);
  1549.     }
  1550.  
  1551.     /**
  1552.      * Gets a packet telling the client to show an EXP increase.
  1553.      *
  1554.      * @param gain The amount of EXP gained.
  1555.      * @param inChat In the chat box?
  1556.      * @param white White text or yellow?
  1557.      * @return The exp gained packet.
  1558.      */
  1559.     public static MaplePacket getShowExpGain(int gain, boolean inChat, boolean white) {
  1560.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  1561.  
  1562.         // 20 00 03 01 0A 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00
  1563.         // 24 00 03 01 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  1564.         mplew.writeShort(SendPacketOpcode.SHOW_STATUS_INFO.getValue());
  1565.         mplew.write(3);
  1566.         mplew.write(white ? 1 : 0);
  1567.         mplew.writeInt(gain);
  1568.         mplew.writeInt(inChat ? 1 : 0);
  1569.         mplew.writeInt(0);
  1570.         mplew.writeInt(0);
  1571.         mplew.writeInt(0);
  1572.         if (inChat) {
  1573.             mplew.write(0);
  1574.         }
  1575.         return mplew.getPacket();
  1576.     }
  1577.  
  1578.     /**
  1579.      * Gets a packet telling the client to show a meso gain.
  1580.      *
  1581.      * @param gain How many mesos gained.
  1582.      * @return The meso gain packet.
  1583.      */
  1584.     public static MaplePacket getShowMesoGain(int gain) {
  1585.         return getShowMesoGain(gain, false);
  1586.     }
  1587.  
  1588.     /**
  1589.      * Gets a packet telling the client to show a meso gain.
  1590.      *
  1591.      * @param gain How many mesos gained.
  1592.      * @param inChat Show in the chat window?
  1593.      * @return The meso gain packet.
  1594.      */
  1595.     public static MaplePacket getShowMesoGain(int gain, boolean inChat) {
  1596.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  1597.  
  1598.         mplew.writeShort(SendPacketOpcode.SHOW_STATUS_INFO.getValue());
  1599.         if (!inChat) {
  1600.             mplew.write(0);
  1601.             mplew.write(1);
  1602.         } else {
  1603.             mplew.write(5);
  1604.         }
  1605.         mplew.writeInt(gain);
  1606.         mplew.writeShort(0); // inet cafe meso gain ?.o
  1607.  
  1608.         return mplew.getPacket();
  1609.     }
  1610.  
  1611.     /**
  1612.      * Gets a packet telling the client to show a item gain.
  1613.      *
  1614.      * @param itemId The ID of the item gained.
  1615.      * @param quantity How many items gained.
  1616.      * @return The item gain packet.
  1617.      */
  1618.     public static MaplePacket getShowItemGain(int itemId, short quantity) {
  1619.         return getShowItemGain(itemId, quantity, false);
  1620.     }
  1621.  
  1622.     /**
  1623.      * Gets a packet telling the client to show an item gain.
  1624.      *
  1625.      * @param itemId The ID of the item gained.
  1626.      * @param quantity The number of items gained.
  1627.      * @param inChat Show in the chat window?
  1628.      * @return The item gain packet.
  1629.      */
  1630.     public static MaplePacket getShowItemGain(int itemId, short quantity, boolean inChat) {
  1631.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  1632.         if (inChat) {
  1633.             mplew.writeShort(SendPacketOpcode.SHOW_ITEM_GAIN_INCHAT.getValue());
  1634.             mplew.write(3);
  1635.             mplew.write(1);
  1636.             mplew.writeInt(itemId);
  1637.             mplew.writeInt(quantity);
  1638.         } else {
  1639.             mplew.writeShort(SendPacketOpcode.SHOW_STATUS_INFO.getValue());
  1640.             mplew.writeShort(0);
  1641.             mplew.writeInt(itemId);
  1642.             mplew.writeInt(quantity);
  1643.             mplew.writeInt(0);
  1644.             mplew.writeInt(0);
  1645.         }
  1646.         return mplew.getPacket();
  1647.     }
  1648.  
  1649.     /**
  1650.      * Gets a packet telling the client that a monster was killed.
  1651.      *
  1652.      * @param oid The objectID of the killed monster.
  1653.      * @param animation Show killed animation?
  1654.      * @return The kill monster packet.
  1655.      */
  1656.     public static MaplePacket killMonster(int oid, boolean animation) {
  1657.         // 9D 00 45 2B 67 00 01
  1658.         // D1 00 05 80 36 00 01
  1659.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  1660.  
  1661.         mplew.writeShort(SendPacketOpcode.KILL_MONSTER.getValue());
  1662.         mplew.writeInt(oid);
  1663.         mplew.write(animation ? 1 : 0);//Not a boolean, really an int type
  1664.  
  1665.         return mplew.getPacket();
  1666.     }
  1667.  
  1668.     /**
  1669.      * Gets a packet telling the client to show mesos coming out of a map
  1670.      * object.
  1671.      *
  1672.      * @param amount The amount of mesos.
  1673.      * @param itemoid The ObjectID of the dropped mesos.
  1674.      * @param dropperoid The OID of the dropper.
  1675.      * @param ownerid The ID of the drop owner.
  1676.      * @param dropfrom Where to drop from.
  1677.      * @param dropto Where the drop lands.
  1678.      * @param mod ?
  1679.      * @return The drop mesos packet.
  1680.      */
  1681.     public static MaplePacket dropMesoFromMapObject(int amount, int itemoid, int dropperoid, int ownerid, Point dropfrom, Point dropto, byte mod) {
  1682.         return dropItemFromMapObjectInternal(amount, itemoid, dropperoid, ownerid, dropfrom, dropto, mod, true);
  1683.     }
  1684.  
  1685.     /**
  1686.      * Gets a packet telling the client to show an item coming out of a map
  1687.      * object.
  1688.      *
  1689.      * @param itemid The ID of the dropped item.
  1690.      * @param itemoid The ObjectID of the dropped item.
  1691.      * @param dropperoid The OID of the dropper.
  1692.      * @param ownerid The ID of the drop owner.
  1693.      * @param dropfrom Where to drop from.
  1694.      * @param dropto Where the drop lands.
  1695.      * @param mod ?
  1696.      * @return The drop mesos packet.
  1697.      */
  1698.     public static MaplePacket dropItemFromMapObject(int itemid, int itemoid, int dropperoid, int ownerid, Point dropfrom, Point dropto, byte mod) {
  1699.         return dropItemFromMapObjectInternal(itemid, itemoid, dropperoid, ownerid, dropfrom, dropto, mod, false);
  1700.     }
  1701.  
  1702.     /**
  1703.      * Internal function to get a packet to tell the client to drop an item onto
  1704.      * the map.
  1705.      *
  1706.      * @param itemid The ID of the item to drop.
  1707.      * @param itemoid The ObjectID of the dropped item.
  1708.      * @param dropperoid The OID of the dropper.
  1709.      * @param ownerid The ID of the drop owner.
  1710.      * @param dropfrom Where to drop from.
  1711.      * @param dropto Where the drop lands.
  1712.      * @param mod ?
  1713.      * @param mesos Is the drop mesos?
  1714.      * @return The item drop packet.
  1715.      */
  1716.     public static MaplePacket dropItemFromMapObjectInternal(int itemid, int itemoid, int dropperoid, int ownerid, Point dropfrom, Point dropto, byte mod, boolean mesos) {
  1717.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  1718.  
  1719.         mplew.writeShort(SendPacketOpcode.DROP_ITEM_FROM_MAPOBJECT.getValue());
  1720.         mplew.write(mod);
  1721.         mplew.writeInt(itemoid);
  1722.         mplew.write(mesos ? 1 : 0);
  1723.         mplew.writeInt(itemid);
  1724.         mplew.writeInt(ownerid);
  1725.         mplew.write(0); // TODO : DROP OWNERSHIP (0 = owner, 1 = party, 2 = FFA, 3 = explosive/FFA)
  1726.         mplew.writeShort(dropto.x);
  1727.         mplew.writeShort(dropto.y);
  1728.         if (mod != 2) {
  1729.             mplew.writeInt(dropperoid);
  1730.             mplew.writeShort(dropfrom.x);
  1731.             mplew.writeShort(dropfrom.y);
  1732.         } else {
  1733.             mplew.writeInt(dropperoid);
  1734.         }
  1735.         mplew.write(0xC2);
  1736.         if (mod != 2) {
  1737.             mplew.write(1);
  1738.             mplew.write(mesos ? 1 : 0);
  1739.         }
  1740.         if (!mesos) {
  1741.             mplew.write(ITEM_MAGIC);
  1742.             addExpirationTime(mplew, System.currentTimeMillis(), false);
  1743.             mplew.write(0);
  1744.         }
  1745.  
  1746.         return mplew.getPacket();
  1747.     }
  1748.  
  1749.     /**
  1750.      * Gets a packet spawning a player as a mapobject to other clients.
  1751.      *
  1752.      * @param chr The character to spawn to other clients.
  1753.      * @return The spawn player packet.
  1754.      */
  1755.     public static MaplePacket spawnPlayerMapobject(MapleCharacter chr) {
  1756.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  1757.         mplew.writeShort(SendPacketOpcode.SPAWN_PLAYER.getValue());
  1758.         mplew.writeInt(chr.getId());
  1759.         mplew.writeMapleAsciiString(chr.getName());
  1760.         if (chr.getGuildId() <= 0) {
  1761.             mplew.writeMapleAsciiString("");
  1762.             mplew.write(new byte[6]);
  1763.         } else {
  1764.             MapleGuildSummary gs = chr.getClient().getChannelServer().getGuildSummary(chr.getGuildId());
  1765.             if (gs != null) {
  1766.                 mplew.writeMapleAsciiString(gs.getName());
  1767.                 mplew.writeShort(gs.getLogoBG());
  1768.                 mplew.write(gs.getLogoBGColor());
  1769.                 mplew.writeShort(gs.getLogo());
  1770.                 mplew.write(gs.getLogoColor());
  1771.             } else {
  1772.                 mplew.writeMapleAsciiString("");
  1773.                 mplew.write(new byte[6]);
  1774.             }
  1775.         }
  1776.  
  1777.         mplew.writeInt(0);
  1778.         mplew.writeInt(1016);
  1779.  
  1780.         if (chr.getBuffedValue(MapleBuffStat.MORPH) != null) {
  1781.             mplew.writeInt(2);
  1782.         } else {
  1783.             mplew.writeInt(0);
  1784.         }
  1785.  
  1786.         long buffmask = 0;
  1787.         Integer buffvalue = null;
  1788.  
  1789.         if (chr.getBuffedValue(MapleBuffStat.DARKSIGHT) != null && !chr.isHidden()) {
  1790.             buffmask |= MapleBuffStat.DARKSIGHT.getValue();
  1791.         }
  1792.         if (chr.getBuffedValue(MapleBuffStat.COMBO) != null) {
  1793.             buffmask |= MapleBuffStat.COMBO.getValue();
  1794.             buffvalue = chr.getBuffedValue(MapleBuffStat.COMBO);
  1795.         }
  1796.         if (chr.getBuffedValue(MapleBuffStat.SHADOWPARTNER) != null) {
  1797.             buffmask |= MapleBuffStat.SHADOWPARTNER.getValue();
  1798.         }
  1799.         if (chr.getBuffedValue(MapleBuffStat.SOULARROW) != null) {
  1800.             buffmask |= MapleBuffStat.SOULARROW.getValue();
  1801.         }
  1802.         if (chr.getBuffedValue(MapleBuffStat.MORPH) != null) {
  1803.             buffvalue = chr.getBuffedValue(MapleBuffStat.MORPH);
  1804.         }
  1805.  
  1806.         mplew.writeInt((int) ((buffmask >> 32) & 0xffffffffL));
  1807.  
  1808.         if (buffvalue != null) {
  1809.             if (chr.getBuffedValue(MapleBuffStat.MORPH) != null) {
  1810.                 mplew.writeShort(buffvalue);
  1811.             } else {
  1812.                 mplew.write(buffvalue.byteValue());
  1813.             }
  1814.         }
  1815.  
  1816.         mplew.writeInt((int) (buffmask & 0xffffffffL));
  1817.  
  1818.         int CHAR_MAGIC_SPAWN = new Random().nextInt();
  1819.         mplew.writeInt(0);
  1820.         mplew.writeShort(0);
  1821.         mplew.writeInt(CHAR_MAGIC_SPAWN);
  1822.         mplew.writeLong(0);
  1823.         mplew.writeShort(0);
  1824.         mplew.write(0);
  1825.         mplew.writeInt(CHAR_MAGIC_SPAWN);
  1826.         mplew.writeLong(0);
  1827.         mplew.writeShort(0);
  1828.         mplew.write(0);
  1829.         mplew.writeInt(CHAR_MAGIC_SPAWN);
  1830.         mplew.writeShort(0);
  1831.         mplew.write(0);
  1832.  
  1833.         if (chr.getBuffedValue(MapleBuffStat.MONSTER_RIDING) != null) {
  1834.             if (chr.getBuffedValue(MapleBuffStat.MONSTER_RIDING) == 1004) {
  1835.                 IItem mount = chr.getInventory(MapleInventoryType.EQUIPPED).getItem((byte) -18);
  1836.                 mplew.writeInt(mount.getItemId());
  1837.                 mplew.writeInt(1004);
  1838.                 mplew.writeInt(2100000000);
  1839.             } else {
  1840.                 mplew.writeInt(1932000);
  1841.                 mplew.writeInt(5221006);
  1842.                 mplew.writeInt(2100000000);
  1843.             }
  1844.         } else {
  1845.             mplew.writeLong(0);
  1846.             mplew.writeInt(CHAR_MAGIC_SPAWN);
  1847.         }
  1848.  
  1849.         mplew.writeLong(0);
  1850.         mplew.write(0);
  1851.         mplew.writeInt(CHAR_MAGIC_SPAWN);
  1852.         mplew.writeLong(0);
  1853.         mplew.writeLong(0);
  1854.         mplew.writeInt(CHAR_MAGIC_SPAWN);
  1855.         mplew.writeLong(0);
  1856.         mplew.writeInt(0);
  1857.         mplew.write(0);
  1858.         mplew.writeInt(CHAR_MAGIC_SPAWN);
  1859.         mplew.writeShort(0);
  1860.         mplew.write(0);
  1861.  
  1862.         mplew.writeShort(chr.getJob().getId());
  1863.  
  1864.         addCharLook(mplew, chr, false);
  1865.  
  1866.         mplew.writeInt(0);
  1867.         mplew.writeInt(chr.getItemEffect());
  1868.         mplew.writeInt(chr.getChair());
  1869.         mplew.writeShort(chr.getPosition().x);
  1870.         mplew.writeShort(chr.getPosition().y);
  1871.         mplew.write(chr.getStance());
  1872.         mplew.writeShort(0); // FH
  1873.         mplew.write(0);
  1874.         for (int i = 0; i < 3; i++) {
  1875.             MaplePet pet = chr.getPet(i);
  1876.             if (pet != null) {
  1877.                 mplew.write(1);
  1878.                 mplew.writeInt(pet.getItemId());
  1879.                 mplew.writeMapleAsciiString(pet.getName());
  1880.                 mplew.writeInt(pet.getUniqueId());
  1881.                 mplew.writeInt(0);
  1882.                 mplew.writeShort(pet.getPos().x);
  1883.                 mplew.writeShort(pet.getPos().y);
  1884.                 mplew.write(pet.getStance());
  1885.                 mplew.writeInt(pet.getFh());
  1886.             }
  1887.         }
  1888.  
  1889.         mplew.write(0);
  1890.         mplew.writeShort(1);
  1891.         mplew.writeInt(0);
  1892.         mplew.writeInt(0);
  1893.         mplew.writeInt(0);
  1894.         mplew.writeInt(0);
  1895.         mplew.writeInt(0);
  1896.         mplew.writeInt(0);
  1897.         mplew.writeInt(0);
  1898.         mplew.writeShort(0);
  1899.         return mplew.getPacket();
  1900.     }
  1901.  
  1902.     /**
  1903.      * Adds a announcement box to an existing MaplePacketLittleEndianWriter.
  1904.      *
  1905.      * @param mplew The MaplePacketLittleEndianWriter to add an announcement box
  1906.      *            to.
  1907.      * @param shop The shop to announce.
  1908.      */
  1909.     private static void addAnnounceBox(MaplePacketLittleEndianWriter mplew, MaplePlayerShop shop) {
  1910.         // 00: no game
  1911.         // 01: omok game
  1912.         // 02: card game
  1913.         // 04: shop
  1914.         mplew.write(4);
  1915.         mplew.writeInt(shop.getObjectId()); // gameid/shopid
  1916.  
  1917.         mplew.writeMapleAsciiString(shop.getDescription()); // desc
  1918.         // 00: public
  1919.         // 01: private
  1920.  
  1921.         mplew.write(0);
  1922.         // 00: red 4x3
  1923.         // 01: green 5x4
  1924.         // 02: blue 6x5
  1925.         // omok:
  1926.         // 00: normal
  1927.         mplew.write(0);
  1928.         // first slot: 1/2/3/4
  1929.         // second slot: 1/2/3/4
  1930.         mplew.write(1);
  1931.         mplew.write(4);
  1932.         // 0: open
  1933.         // 1: in progress
  1934.         mplew.write(0);
  1935.     }
  1936.  
  1937.     public static MaplePacket facialExpression(MapleCharacter from, int expression) {
  1938.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  1939.         mplew.writeShort(SendPacketOpcode.FACIAL_EXPRESSION.getValue());
  1940.  
  1941.         mplew.writeInt(from.getId());
  1942.         mplew.writeInt(expression);
  1943.  
  1944.         return mplew.getPacket();
  1945.     }
  1946.  
  1947.     private static void serializeMovementList(LittleEndianWriter lew, List<LifeMovementFragment> moves) {
  1948.         lew.write(moves.size());
  1949.         for (LifeMovementFragment move : moves) {
  1950.             move.serialize(lew);
  1951.         }
  1952.     }
  1953.  
  1954.     public static MaplePacket movePlayer(int cid, List<LifeMovementFragment> moves) {
  1955.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  1956.  
  1957.         mplew.writeShort(SendPacketOpcode.MOVE_PLAYER.getValue());
  1958.         mplew.writeInt(cid);
  1959.  
  1960.         mplew.writeInt(0);
  1961.  
  1962.         serializeMovementList(mplew, moves);
  1963.  
  1964.         return mplew.getPacket();
  1965.     }
  1966.  
  1967.     public static MaplePacket moveSummon(int cid, int oid, Point startPos, List<LifeMovementFragment> moves) {
  1968.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  1969.  
  1970.         mplew.writeShort(SendPacketOpcode.MOVE_SUMMON.getValue());
  1971.         mplew.writeInt(cid);
  1972.         mplew.writeInt(oid);
  1973.         mplew.writeShort(startPos.x);
  1974.         mplew.writeShort(startPos.y);
  1975.  
  1976.         serializeMovementList(mplew, moves);
  1977.  
  1978.         return mplew.getPacket();
  1979.     }
  1980.  
  1981.     public static MaplePacket moveMonster(int useskill, int skill, int skill_1, int skill_2, int skill_3, int oid, Point startPos,
  1982.             List<LifeMovementFragment> moves) {
  1983.         /*
  1984.          * A0 00 C8 00 00 00 00 FF 00 00 00 00 48 02 7D FE 02 00 1C 02 7D FE 9C FF 00 00 2A 00 03 BD 01 00 DC 01 7D FE
  1985.          * 9C FF 00 00 2B 00 03 7B 02
  1986.          */
  1987.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  1988.  
  1989.         mplew.writeShort(SendPacketOpcode.MOVE_MONSTER.getValue());
  1990.         // mplew.writeShort(0xA2); // 47 a0
  1991.         mplew.writeInt(oid);
  1992.         mplew.write(useskill);
  1993.         mplew.write(skill);
  1994.         mplew.write(skill_1);
  1995.         mplew.write(skill_2);
  1996.         mplew.write(skill_3);
  1997.         mplew.write(0);
  1998.         mplew.writeShort(startPos.x);
  1999.         mplew.writeShort(startPos.y);
  2000.  
  2001.         serializeMovementList(mplew, moves);
  2002.  
  2003.         return mplew.getPacket();
  2004.     }
  2005.  
  2006.     public static MaplePacket summonAttack(int cid, int summonSkillId, int newStance, List<SummonAttackEntry> allDamage) {
  2007.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2008.  
  2009.         mplew.writeShort(SendPacketOpcode.SUMMON_ATTACK.getValue());
  2010.         mplew.writeInt(cid);
  2011.         mplew.writeInt(summonSkillId);
  2012.         mplew.write(newStance);
  2013.         mplew.write(allDamage.size());
  2014.         for (SummonAttackEntry attackEntry : allDamage) {
  2015.             mplew.writeInt(attackEntry.getMonsterOid()); // oid
  2016.  
  2017.             mplew.write(6); // who knows
  2018.  
  2019.             mplew.writeInt(attackEntry.getDamage()); // damage
  2020.  
  2021.         }
  2022.  
  2023.         return mplew.getPacket();
  2024.     }
  2025.  
  2026.     public static MaplePacket closeRangeAttack(int cid, int skill, int stance, int numAttackedAndDamage,
  2027.                                 List<Pair<Integer, List<Integer>>> damage, int speed) {
  2028.         // 7D 00 #30 75 00 00# 12 00 06 02 0A 00 00 00 00 01 00 00 00 00 97 02
  2029.         // 00 00 97 02 00 00
  2030.         // 7D 00 #30 75 00 00# 11 00 06 02 0A 00 00 00 00 20 00 00 00 49 06 00
  2031.         // 00
  2032.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2033.  
  2034.         mplew.writeShort(SendPacketOpcode.CLOSE_RANGE_ATTACK.getValue());
  2035.         // mplew.writeShort(0x7F); // 47 7D
  2036.         if (skill == 4211006) { // meso explosion
  2037.             addMesoExplosion(mplew, cid, skill, stance, numAttackedAndDamage, 0, damage, speed);
  2038.         } else {
  2039.             addAttackBody(mplew, cid, skill, stance, numAttackedAndDamage, 0, damage, speed);
  2040.         }
  2041.         return mplew.getPacket();
  2042.     }
  2043.  
  2044.     public static MaplePacket rangedAttack(int cid, int skill, int stance, int numAttackedAndDamage, int projectile,
  2045.                                 List<Pair<Integer, List<Integer>>> damage, int speed) {
  2046.         // 7E 00 30 75 00 00 01 00 97 04 0A CB 72 1F 00
  2047.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2048.  
  2049.         mplew.writeShort(SendPacketOpcode.RANGED_ATTACK.getValue());
  2050.         // mplew.writeShort(0x80); // 47 7E
  2051.         addAttackBody(mplew, cid, skill, stance, numAttackedAndDamage, projectile, damage, speed);
  2052.         mplew.writeInt(0);
  2053.  
  2054.         return mplew.getPacket();
  2055.     }
  2056.  
  2057.  
  2058.     public static MaplePacket magicAttack(int cid, int skill, int stance, int numAttackedAndDamage,
  2059.                                 List<Pair<Integer, List<Integer>>> damage, int charge, int speed) {
  2060.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2061.  
  2062.         mplew.writeShort(SendPacketOpcode.MAGIC_ATTACK.getValue());
  2063.         // mplew.writeShort(0x81);
  2064.         addAttackBody(mplew, cid, skill, stance, numAttackedAndDamage, 0, damage, speed);
  2065.         if (charge != -1) {
  2066.             mplew.writeInt(charge);
  2067.         }
  2068.  
  2069.         return mplew.getPacket();
  2070.     }
  2071.  
  2072.     private static void addAttackBody(LittleEndianWriter lew, int cid, int skill, int stance, int numAttackedAndDamage,
  2073.                                 int projectile, List<Pair<Integer, List<Integer>>> damage, int speed) {
  2074.         lew.writeInt(cid);
  2075.         lew.write(numAttackedAndDamage);
  2076.         if (skill > 0) {
  2077.             lew.write(0xFF); // too low and some skills don't work (?)
  2078.             lew.writeInt(skill);
  2079.         } else {
  2080.             lew.write(0);
  2081.         }
  2082.         lew.write(0);
  2083.         lew.write(stance);
  2084.         lew.write(speed);
  2085.         lew.write(0x0A);
  2086.         //lew.write(0);
  2087.         lew.writeInt(projectile);
  2088.  
  2089.         for (Pair<Integer, List<Integer>> oned : damage) {
  2090.             if (oned.getRight() != null) {
  2091.                 lew.writeInt(oned.getLeft().intValue());
  2092.                 lew.write(0xFF);
  2093.                 for (Integer eachd : oned.getRight()) {
  2094.                     // highest bit set = crit
  2095.                     lew.writeInt(eachd.intValue());
  2096.                 }
  2097.             }
  2098.         }
  2099.     }
  2100.     private static void addMesoExplosion(LittleEndianWriter lew, int cid, int skill, int stance,
  2101.                                     int numAttackedAndDamage, int projectile,
  2102.                                     List<Pair<Integer, List<Integer>>> damage, int speed) {
  2103.         // 7A 00 6B F4 0C 00 22 1E 3E 41 40 00 38 04 0A 00 00 00 00 44 B0 04 00
  2104.         // 06 02 E6 00 00 00 D0 00 00 00 F2 46 0E 00 06 02 D3 00 00 00 3B 01 00
  2105.         // 00
  2106.         // 7A 00 6B F4 0C 00 00 1E 3E 41 40 00 38 04 0A 00 00 00 00
  2107.         lew.writeInt(cid);
  2108.         lew.write(numAttackedAndDamage);
  2109.         lew.write(0x1E);
  2110.         lew.writeInt(skill);
  2111.         lew.write(0);
  2112.         lew.write(stance);
  2113.         lew.write(speed);
  2114.         lew.write(0x0A);
  2115.         lew.writeInt(projectile);
  2116.  
  2117.         for (Pair<Integer, List<Integer>> oned : damage) {
  2118.             if (oned.getRight() != null) {
  2119.                 lew.writeInt(oned.getLeft().intValue());
  2120.                 lew.write(0xFF);
  2121.                 lew.write(oned.getRight().size());
  2122.                 for (Integer eachd : oned.getRight()) {
  2123.                     lew.writeInt(eachd.intValue());
  2124.                 }
  2125.             }
  2126.         }
  2127.  
  2128.     }
  2129.        
  2130.     private static void addMesoExplosion(LittleEndianWriter lew, int cid, int skill, int skillLevel, int stance,
  2131.             int numAttackedAndDamage, int projectile,
  2132.             List<Pair<Integer, List<Integer>>> damage, int speed) {
  2133.         // 7A 00 6B F4 0C 00 22 1E 3E 41 40 00 38 04 0A 00 00 00 00 44 B0 04 00
  2134.         // 06 02 E6 00 00 00 D0 00 00 00 F2 46 0E 00 06 02 D3 00 00 00 3B 01 00
  2135.         // 00
  2136.         // 7A 00 6B F4 0C 00 00 1E 3E 41 40 00 38 04 0A 00 00 00 00
  2137.         lew.writeInt(cid);
  2138.         lew.write(numAttackedAndDamage);
  2139.         lew.write(skillLevel);
  2140.         lew.writeInt(skill);
  2141.         lew.write(0);
  2142.         lew.write(stance);
  2143.         lew.write(speed);
  2144.         lew.write(0x0A);
  2145.         lew.writeInt(projectile);
  2146.  
  2147.         for (Pair<Integer, List<Integer>> oned : damage) {
  2148.             if (oned.getRight() != null) {
  2149.                 lew.writeInt(oned.getLeft().intValue());
  2150.                 lew.write(0xFF);
  2151.                 lew.write(oned.getRight().size());
  2152.                 for (Integer eachd : oned.getRight()) {
  2153.                     lew.writeInt(eachd.intValue());
  2154.                 }
  2155.             }
  2156.         }
  2157.  
  2158.     }
  2159.  
  2160.     public static MaplePacket getNPCShop(int sid, List<MapleShopItem> items) {
  2161.         MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
  2162.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2163.         mplew.writeShort(SendPacketOpcode.OPEN_NPC_SHOP.getValue());
  2164.         mplew.writeInt(sid);
  2165.         mplew.writeShort(items.size());
  2166.         for (MapleShopItem item : items) {
  2167.             mplew.writeInt(item.getItemId());
  2168.             mplew.writeInt(item.getPrice());
  2169.             if (!ii.isThrowingStar(item.getItemId()) && !ii.isBullet(item.getItemId())) {
  2170.                 mplew.writeShort(1);
  2171.                 mplew.writeShort(item.getMaxSlot());
  2172.             } else {
  2173.                 mplew.writeLong(Double.doubleToLongBits(ii.getPrice(item.getItemId())));
  2174.                 mplew.writeShort(item.getMaxSlot());
  2175.             }
  2176.         }
  2177.         return mplew.getPacket();
  2178.     }
  2179.  
  2180.     /**
  2181.      * code (8 = sell, 0 = buy, 0x20 = due to an error the trade did not happen
  2182.      * o.o)
  2183.      *
  2184.      * @param code
  2185.      * @return
  2186.      */
  2187.     public static MaplePacket confirmShopTransaction(byte code) {
  2188.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2189.         mplew.writeShort(SendPacketOpcode.CONFIRM_SHOP_TRANSACTION.getValue());
  2190.         mplew.write(code);
  2191.         return mplew.getPacket();
  2192.     }
  2193.  
  2194.     /*
  2195.      * 19 reference 00 01 00 = new while adding 01 01 00 = add from drop 00 01 01 = update count 00 01 03 = clear slot
  2196.      * 01 01 02 = move to empty slot 01 02 03 = move and merge 01 02 01 = move and merge with rest
  2197.      */
  2198.     public static MaplePacket addInventorySlot(MapleInventoryType type, IItem item) {
  2199.         return addInventorySlot(type, item, false);
  2200.     }
  2201.  
  2202.     public static MaplePacket addInventorySlot(MapleInventoryType type, IItem item, boolean fromDrop) {
  2203.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2204.         mplew.writeShort(SendPacketOpcode.MODIFY_INVENTORY_ITEM.getValue());
  2205.         // mplew.writeShort(0x19);
  2206.         if (fromDrop) {
  2207.             mplew.write(1);
  2208.         } else {
  2209.             mplew.write(0);
  2210.         }
  2211.         mplew.write(HexTool.getByteArrayFromHexString("01 00")); // add mode
  2212.         mplew.write(type.getType()); // iv type
  2213.         mplew.write(item.getPosition()); // slot id
  2214.         if (item.getPetId() != -1) {
  2215.             addPetInfo(mplew, MaplePet.loadFromDb(item.getItemId(), item.getPosition(), item.getPetId()), true);
  2216.         } else {
  2217.             addItemInfo(mplew, item, true, false, false);
  2218.         }
  2219.         return mplew.getPacket();
  2220.     }
  2221.  
  2222.     public static MaplePacket updateInventorySlot(MapleInventoryType type, IItem item) {
  2223.         return updateInventorySlot(type, item, false);
  2224.     }
  2225.  
  2226.     public static MaplePacket updateInventorySlot(MapleInventoryType type, IItem item, boolean fromDrop) {
  2227.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2228.         mplew.writeShort(SendPacketOpcode.MODIFY_INVENTORY_ITEM.getValue());
  2229.         if (fromDrop) {
  2230.             mplew.write(1);
  2231.         } else {
  2232.             mplew.write(0);
  2233.         }
  2234.         mplew.write(HexTool.getByteArrayFromHexString("01 01"));
  2235.         mplew.write(type.getType());
  2236.         mplew.write(item.getPosition());
  2237.         mplew.write(0);
  2238.         mplew.writeShort(item.getQuantity());
  2239.  
  2240.         return mplew.getPacket();
  2241.     }
  2242.  
  2243.     public static MaplePacket moveInventoryItem(MapleInventoryType type, byte src, byte dst) {
  2244.         return moveInventoryItem(type, src, dst, (byte) -1);
  2245.     }
  2246.  
  2247.     public static MaplePacket moveInventoryItem(MapleInventoryType type, byte src, byte dst, byte equipIndicator) {
  2248.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2249.         mplew.writeShort(SendPacketOpcode.MODIFY_INVENTORY_ITEM.getValue());
  2250.         mplew.write(HexTool.getByteArrayFromHexString("01 01 02"));
  2251.         mplew.write(type.getType());
  2252.         mplew.writeShort(src);
  2253.         mplew.writeShort(dst);
  2254.         if (equipIndicator != -1) {
  2255.             mplew.write(equipIndicator);
  2256.         }
  2257.         return mplew.getPacket();
  2258.     }
  2259.  
  2260.     public static MaplePacket moveAndMergeInventoryItem(MapleInventoryType type, byte src, byte dst, short total) {
  2261.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2262.         mplew.writeShort(SendPacketOpcode.MODIFY_INVENTORY_ITEM.getValue());
  2263.         mplew.write(HexTool.getByteArrayFromHexString("01 02 03"));
  2264.         mplew.write(type.getType());
  2265.         mplew.writeShort(src);
  2266.         mplew.write(1); // merge mode?
  2267.  
  2268.         mplew.write(type.getType());
  2269.         mplew.writeShort(dst);
  2270.         mplew.writeShort(total);
  2271.         return mplew.getPacket();
  2272.     }
  2273.  
  2274.     public static MaplePacket moveAndMergeWithRestInventoryItem(MapleInventoryType type, byte src, byte dst,
  2275.             short srcQ, short dstQ) {
  2276.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2277.         mplew.writeShort(SendPacketOpcode.MODIFY_INVENTORY_ITEM.getValue());
  2278.         mplew.write(HexTool.getByteArrayFromHexString("01 02 01"));
  2279.         mplew.write(type.getType());
  2280.         mplew.writeShort(src);
  2281.         mplew.writeShort(srcQ);
  2282.         mplew.write(HexTool.getByteArrayFromHexString("01"));
  2283.         mplew.write(type.getType());
  2284.         mplew.writeShort(dst);
  2285.         mplew.writeShort(dstQ);
  2286.         return mplew.getPacket();
  2287.     }
  2288.  
  2289.     public static MaplePacket clearInventoryItem(MapleInventoryType type, byte slot, boolean fromDrop) {
  2290.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2291.         mplew.writeShort(SendPacketOpcode.MODIFY_INVENTORY_ITEM.getValue());
  2292.         mplew.write(fromDrop ? 1 : 0);
  2293.         mplew.write(HexTool.getByteArrayFromHexString("01 03"));
  2294.         mplew.write(type.getType());
  2295.         mplew.writeShort(slot);
  2296.         return mplew.getPacket();
  2297.     }
  2298.  
  2299.     public static MaplePacket scrolledItem(IItem scroll, IItem item, boolean destroyed) {
  2300.         // 18 00 01 02 03 02 08 00 03 01 F7 FF 01
  2301.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2302.         mplew.writeShort(SendPacketOpcode.MODIFY_INVENTORY_ITEM.getValue());
  2303.         mplew.write(1); // fromdrop always true
  2304.  
  2305.         mplew.write(destroyed ? 2 : 3);
  2306.         mplew.write(scroll.getQuantity() > 0 ? 1 : 3);
  2307.         mplew.write(MapleInventoryType.USE.getType());
  2308.         mplew.writeShort(scroll.getPosition());
  2309.         if (scroll.getQuantity() > 0) {
  2310.             mplew.writeShort(scroll.getQuantity());
  2311.         }
  2312.         mplew.write(3);
  2313.         if (!destroyed) {
  2314.             mplew.write(MapleInventoryType.EQUIP.getType());
  2315.             mplew.writeShort(item.getPosition());
  2316.             mplew.write(0);
  2317.         }
  2318.         mplew.write(MapleInventoryType.EQUIP.getType());
  2319.         mplew.writeShort(item.getPosition());
  2320.         if (!destroyed) {
  2321.             addItemInfo(mplew, item, true, true, false);
  2322.         }
  2323.         mplew.write(1);
  2324.         return mplew.getPacket();
  2325.     }
  2326.  
  2327.     public static MaplePacket getScrollEffect(int chr, ScrollResult scrollSuccess, boolean legendarySpirit) {
  2328.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2329.         mplew.writeShort(SendPacketOpcode.SHOW_SCROLL_EFFECT.getValue());
  2330.         mplew.writeInt(chr);
  2331.         switch (scrollSuccess) {
  2332.             case SUCCESS:
  2333.                 mplew.writeShort(1);
  2334.                 mplew.writeShort(legendarySpirit ? 1 : 0);
  2335.                 break;
  2336.             case FAIL:
  2337.                 mplew.writeShort(0);
  2338.                 mplew.writeShort(legendarySpirit ? 1 : 0);
  2339.                 break;
  2340.             case CURSE:
  2341.                 mplew.write(0);
  2342.                 mplew.write(1);
  2343.                 mplew.writeShort(legendarySpirit ? 1 : 0);
  2344.                 break;
  2345.             default:
  2346.                 throw new IllegalArgumentException("effect in illegal range");
  2347.         }
  2348.  
  2349.         return mplew.getPacket();
  2350.     }
  2351.  
  2352.     public static MaplePacket removePlayerFromMap(int cid) {
  2353.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2354.         mplew.writeShort(SendPacketOpcode.REMOVE_PLAYER_FROM_MAP.getValue());
  2355.         // mplew.writeShort(0x65); // 47 63
  2356.         mplew.writeInt(cid);
  2357.         return mplew.getPacket();
  2358.     }
  2359.  
  2360.     /**
  2361.      * animation: 0 - expire<br/> 1 - without animation<br/> 2 - pickup<br/>
  2362.      * 4 - explode<br/> cid is ignored for 0 and 1
  2363.      *
  2364.      * @param oid
  2365.      * @param animation
  2366.      * @param cid
  2367.      * @return
  2368.      */
  2369.     public static MaplePacket removeItemFromMap(int oid, int animation, int cid) {
  2370.         return removeItemFromMap(oid, animation, cid, false, 0);
  2371.     }
  2372.  
  2373.     /**
  2374.      * animation: 0 - expire<br/> 1 - without animation<br/> 2 - pickup<br/>
  2375.      * 4 - explode<br/> cid is ignored for 0 and 1.<br /><br />Flagging pet
  2376.      * as true will make a pet pick up the item.
  2377.      *
  2378.      * @param oid
  2379.      * @param animation
  2380.      * @param cid
  2381.      * @param pet
  2382.      * @param slot
  2383.      * @return
  2384.      */
  2385.     public static MaplePacket removeItemFromMap(int oid, int animation, int cid, boolean pet, int slot) {
  2386.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2387.         mplew.writeShort(SendPacketOpcode.REMOVE_ITEM_FROM_MAP.getValue());
  2388.         mplew.write(animation); // expire
  2389.  
  2390.         mplew.writeInt(oid);
  2391.         if (animation >= 2) {
  2392.             mplew.writeInt(cid);
  2393.             if (pet) {
  2394.                 mplew.write(slot);
  2395.             }
  2396.         }
  2397.         return mplew.getPacket();
  2398.     }
  2399.  
  2400.     public static MaplePacket updateCharLook(MapleCharacter chr) {
  2401.         // 88 00 80 74 03 00 01 00 00 19 50 00 00 00 67 75 00 00 02 34 71 0F 00
  2402.         // 04 59 BF 0F 00 05 AB 05 10 00 07 8C 5B
  2403.         // 10 00 08 F4 82 10 00 09 E7 D0 10 00 0A BE A9 10 00 0B 0C 05 14 00 FF
  2404.         // FF 00 00 00 00 00 00 00 00 00 00 00
  2405.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2406.         mplew.writeShort(SendPacketOpcode.UPDATE_CHAR_LOOK.getValue());
  2407.         mplew.writeInt(chr.getId());
  2408.         mplew.write(1);
  2409.  
  2410.         addCharLook(mplew, chr, false);
  2411.  
  2412.         mplew.write(0);
  2413.         mplew.writeShort(0);
  2414.  
  2415.         return mplew.getPacket();
  2416.     }
  2417.  
  2418.     public static MaplePacket dropInventoryItem(MapleInventoryType type, short src) {
  2419.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2420.         mplew.writeShort(SendPacketOpcode.MODIFY_INVENTORY_ITEM.getValue());
  2421.         // mplew.writeShort(0x19);
  2422.         mplew.write(HexTool.getByteArrayFromHexString("01 01 03"));
  2423.         mplew.write(type.getType());
  2424.         mplew.writeShort(src);
  2425.         if (src < 0) {
  2426.             mplew.write(1);
  2427.         }
  2428.         return mplew.getPacket();
  2429.     }
  2430.  
  2431.     public static MaplePacket dropInventoryItemUpdate(MapleInventoryType type, IItem item) {
  2432.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2433.         mplew.writeShort(SendPacketOpcode.MODIFY_INVENTORY_ITEM.getValue());
  2434.         mplew.write(HexTool.getByteArrayFromHexString("01 01 01"));
  2435.         mplew.write(type.getType());
  2436.         mplew.writeShort(item.getPosition());
  2437.         mplew.writeShort(item.getQuantity());
  2438.         return mplew.getPacket();
  2439.     }
  2440.  
  2441.     public static MaplePacket damagePlayer(int skill, int monsteridfrom, int cid, int damage, int fake, int direction, boolean pgmr, int pgmr_1, boolean is_pg, int oid, int pos_x, int pos_y) {
  2442.         // 82 00 30 C0 23 00 FF 00 00 00 00 B4 34 03 00 01 00 00 00 00 00 00
  2443.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2444.         mplew.writeShort(SendPacketOpcode.DAMAGE_PLAYER.getValue());
  2445.         // mplew.writeShort(0x84); // 47 82
  2446.         mplew.writeInt(cid);
  2447.         mplew.write(skill);
  2448.         mplew.writeInt(damage);
  2449.         mplew.writeInt(monsteridfrom);
  2450.         mplew.write(direction);
  2451.         if (pgmr) {
  2452.             mplew.write(pgmr_1);
  2453.             mplew.write(is_pg ? 1 : 0);
  2454.             mplew.writeInt(oid);
  2455.             mplew.write(6);
  2456.             mplew.writeShort(pos_x);
  2457.             mplew.writeShort(pos_y);
  2458.             mplew.write(0);
  2459.         } else {
  2460.             mplew.writeShort(0);
  2461.         }
  2462.  
  2463.         mplew.writeInt(damage);
  2464.  
  2465.         if (fake > 0) {
  2466.             mplew.writeInt(fake);
  2467.         }
  2468.  
  2469.         return mplew.getPacket();
  2470.     }
  2471.  
  2472.     public static MaplePacket charNameResponse(String charname, boolean nameUsed) {
  2473.         // 0D 00 0C 00 42 6C 61 62 6C 75 62 62 31 32 33 34 00
  2474.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2475.         mplew.writeShort(SendPacketOpcode.CHAR_NAME_RESPONSE.getValue());
  2476.         mplew.writeMapleAsciiString(charname);
  2477.         mplew.write(nameUsed ? 1 : 0);
  2478.  
  2479.         return mplew.getPacket();
  2480.     }
  2481.  
  2482.     public static MaplePacket addNewCharEntry(MapleCharacter chr, boolean worked) {
  2483.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2484.         mplew.writeShort(SendPacketOpcode.ADD_NEW_CHAR_ENTRY.getValue());
  2485.         mplew.write(worked ? 0 : 1);
  2486.         addCharEntry(mplew, chr);
  2487.         return mplew.getPacket();
  2488.     }
  2489.  
  2490.     /**
  2491.      *
  2492.      * @param c
  2493.      * @param quest
  2494.      * @return
  2495.      */
  2496.     public static MaplePacket startQuest(MapleCharacter c, short quest) {
  2497.         // [24 00] [01] [69 08] [01 00] [00]
  2498.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2499.         // mplew.writeShort(0x21);
  2500.         mplew.writeShort(SendPacketOpcode.SHOW_STATUS_INFO.getValue());
  2501.         mplew.write(1);
  2502.         mplew.writeShort(quest);
  2503.         mplew.writeShort(1);
  2504.         mplew.write(0);
  2505.         return mplew.getPacket();
  2506.     }
  2507.  
  2508.     /**
  2509.      * state 0 = del ok state 12 = invalid bday
  2510.      *
  2511.      * @param cid
  2512.      * @param state
  2513.      * @return
  2514.      */
  2515.     public static MaplePacket deleteCharResponse(int cid, int state) {
  2516.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2517.         mplew.writeShort(SendPacketOpcode.DELETE_CHAR_RESPONSE.getValue());
  2518.         mplew.writeInt(cid);
  2519.         mplew.write(state);
  2520.         return mplew.getPacket();
  2521.     }
  2522.  
  2523.     public static MaplePacket charInfo(MapleCharacter chr) {
  2524.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2525.         mplew.writeShort(SendPacketOpcode.CHAR_INFO.getValue());
  2526.         // mplew.writeShort(0x31);
  2527.         mplew.writeInt(chr.getId());
  2528.         mplew.write(chr.getLevel());
  2529.         mplew.writeShort(chr.getJob().getId());
  2530.         mplew.writeShort(chr.getFame());
  2531.         mplew.write(0); // heart red or gray
  2532.  
  2533.         if (chr.getGuildId() <= 0) {
  2534.             mplew.writeMapleAsciiString("-"); // guild
  2535.  
  2536.         } else {
  2537.             MapleGuildSummary gs = null;
  2538.  
  2539.             gs = chr.getClient().getChannelServer().getGuildSummary(chr.getGuildId());
  2540.             if (gs != null) {
  2541.                 mplew.writeMapleAsciiString(gs.getName());
  2542.             } else {
  2543.                 mplew.writeMapleAsciiString("-"); // guild
  2544.  
  2545.             }
  2546.         }
  2547.  
  2548.         mplew.writeMapleAsciiString(""); // Alliance
  2549.  
  2550.         mplew.write(0);
  2551.  
  2552.         MaplePet[] pets = chr.getPets();
  2553.         for (int i = 0; i < 3; i++) {
  2554.             if (pets[i] != null) {
  2555.                 mplew.write(pets[i].getUniqueId());
  2556.                 mplew.writeInt(pets[i].getItemId()); // petid
  2557.                 mplew.writeMapleAsciiString(pets[i].getName());
  2558.                 mplew.write(pets[i].getLevel()); // pet level
  2559.                 mplew.writeShort(pets[i].getCloseness()); // pet closeness
  2560.                 mplew.write(pets[i].getFullness()); // pet fullness
  2561.                 mplew.writeShort(0); // ??
  2562.                 mplew.writeInt(0);
  2563.             }
  2564.         }
  2565.  
  2566.         mplew.writeShort(0);
  2567.         mplew.write(0);
  2568.         mplew.writeInt(1);
  2569.         mplew.writeLong(0);
  2570.         mplew.writeLong(0);
  2571.         return mplew.getPacket();
  2572.     }
  2573.  
  2574.     /**
  2575.      *
  2576.      * @param c
  2577.      * @param quest
  2578.      * @return
  2579.      */
  2580.     public static MaplePacket forfeitQuest(MapleCharacter c, short quest) {
  2581.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2582.         mplew.writeShort(SendPacketOpcode.SHOW_STATUS_INFO.getValue());
  2583.         mplew.write(1);
  2584.         mplew.writeShort(quest);
  2585.         mplew.writeShort(0);
  2586.         mplew.write(0);
  2587.         mplew.writeInt(0);
  2588.         mplew.writeInt(0);
  2589.         return mplew.getPacket();
  2590.     }
  2591.  
  2592.     /**
  2593.      *
  2594.      * @param c
  2595.      * @param quest
  2596.      * @return
  2597.      */
  2598.     public static MaplePacket completeQuest(MapleCharacter c, short quest) {
  2599.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2600.         mplew.writeShort(SendPacketOpcode.SHOW_STATUS_INFO.getValue());
  2601.         mplew.write(1);
  2602.         mplew.writeShort(quest);
  2603.         mplew.write(HexTool.getByteArrayFromHexString("02 A0 67 B9 DA 69 3A C8 01"));
  2604.         mplew.writeInt(0);
  2605.         mplew.writeInt(0);
  2606.         return mplew.getPacket();
  2607.     }
  2608.  
  2609.     /**
  2610.      *
  2611.      * @param c
  2612.      * @param quest
  2613.      * @param npc
  2614.      * @param progress
  2615.      * @return
  2616.      */
  2617.     // frz note, 0.52 transition: this is only used when starting a quest and
  2618.     // seems to have no effect, is it needed?
  2619.     public static MaplePacket updateQuestInfo(MapleCharacter c, short quest, int npc, byte progress) {
  2620.         // [A5 00] [08] [69 08] [86 71 0F 00] [00 00 00 00]
  2621.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2622.         mplew.writeShort(SendPacketOpcode.UPDATE_QUEST_INFO.getValue());
  2623.         mplew.write(progress);
  2624.         mplew.writeShort(quest);
  2625.         mplew.writeInt(npc);
  2626.         mplew.writeInt(0);
  2627.         return mplew.getPacket();
  2628.     }
  2629.  
  2630.     private static long getLongMask(List<Pair<MapleBuffStat, Integer>> statups) {
  2631.         long mask = 0;
  2632.         for (Pair<MapleBuffStat, Integer> statup : statups) {
  2633.             mask |= statup.getLeft().getValue();
  2634.         }
  2635.         return mask;
  2636.     }
  2637.  
  2638.     private static long getLongMaskFromList(List<MapleBuffStat> statups) {
  2639.         long mask = 0;
  2640.         for (MapleBuffStat statup : statups) {
  2641.             mask |= statup.getValue();
  2642.         }
  2643.         return mask;
  2644.     }
  2645.  
  2646.     private static long getLongMaskD(List<Pair<MapleDisease, Integer>> statups) {
  2647.         long mask = 0;
  2648.         for (Pair<MapleDisease, Integer> statup : statups) {
  2649.             mask |= statup.getLeft().getValue();
  2650.         }
  2651.         return mask;
  2652.     }
  2653.  
  2654.     private static long getLongMaskFromListD(List<MapleDisease> statups) {
  2655.         long mask = 0;
  2656.         for (MapleDisease statup : statups) {
  2657.             mask |= statup.getValue();
  2658.         }
  2659.         return mask;
  2660.     }
  2661.  
  2662.     /**
  2663.      * It is important that statups is in the correct order (see decleration
  2664.      * order in MapleBuffStat) since this method doesn't do automagical
  2665.      * reordering.
  2666.      *
  2667.      * @param buffid
  2668.      * @param bufflength
  2669.      * @param statups
  2670.      * @param morph
  2671.      * @param firstLong
  2672.      * @return
  2673.      */
  2674.     public static MaplePacket giveBuff(int buffid, int bufflength, List<Pair<MapleBuffStat, Integer>> statups) {
  2675.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2676.         mplew.writeShort(SendPacketOpcode.GIVE_BUFF.getValue());
  2677.  
  2678.         long mask = getLongMask(statups);
  2679.  
  2680.         mplew.writeLong(0);
  2681.         mplew.writeLong(mask);
  2682.         for (Pair<MapleBuffStat, Integer> statup : statups) {
  2683.             mplew.writeShort(statup.getRight().shortValue());
  2684.             mplew.writeInt(buffid);
  2685.             mplew.writeInt(bufflength);
  2686.         }
  2687.         mplew.writeShort(0);
  2688.         mplew.write(0);
  2689.         mplew.write(0);
  2690.         mplew.write(0);
  2691.  
  2692.         return mplew.getPacket();
  2693.     }
  2694.  
  2695.     /**
  2696.      * @param buffid
  2697.      * @param bufflength
  2698.      * @param statups
  2699.      * @param morph
  2700.      * @param firstLong
  2701.      * @return
  2702.      */
  2703.     public static MaplePacket giveSpeedInfusion(int buffid, int bufflength, List<Pair<MapleBuffStat, Integer>> statups, int addedInfo) {
  2704.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2705.         mplew.writeShort(SendPacketOpcode.GIVE_BUFF.getValue());
  2706.  
  2707.         long mask = getLongMask(statups);
  2708.  
  2709.         mplew.writeLong(mask);
  2710.         mplew.writeLong(0);
  2711.         mplew.writeShort(0);
  2712.         mplew.writeInt(statups.get(0).getRight().intValue());
  2713.         mplew.writeInt(buffid);
  2714.         mplew.writeInt(0);
  2715.         mplew.writeInt(0);
  2716.         mplew.writeShort(0);
  2717.         mplew.writeShort(bufflength);
  2718.         mplew.writeShort(addedInfo);
  2719.         return mplew.getPacket();
  2720.     }
  2721.  
  2722.     /**
  2723.      * @param buffid
  2724.      * @param bufflength
  2725.      * @param statups
  2726.      * @param morph
  2727.      * @param firstLong
  2728.      * @return
  2729.      */
  2730.     public static MaplePacket givePirateBuff(int buffid, int bufflength, List<Pair<MapleBuffStat, Integer>> statups) {
  2731.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2732.         mplew.writeShort(SendPacketOpcode.GIVE_BUFF.getValue());
  2733.  
  2734.         long mask = getLongMask(statups);
  2735.  
  2736.         mplew.writeLong(mask);
  2737.         mplew.writeLong(0);
  2738.         mplew.writeShort(0);
  2739.         for (Pair<MapleBuffStat, Integer> statup : statups) {
  2740.             mplew.writeShort(statup.getRight().shortValue());
  2741.             mplew.writeShort(0);
  2742.             mplew.writeInt(buffid);
  2743.             mplew.writeInt(0);
  2744.             mplew.write(0);
  2745.             mplew.writeShort(bufflength);
  2746.         }
  2747.         mplew.writeShort(0);
  2748.         mplew.write(0);
  2749.  
  2750.         return mplew.getPacket();
  2751.     }
  2752.  
  2753.     public static MaplePacket giveMountBuff(int skillid, int mountid) {
  2754.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2755.         mplew.writeShort(SendPacketOpcode.GIVE_BUFF.getValue());
  2756.  
  2757.         mplew.writeLong(MapleBuffStat.MONSTER_RIDING.getValue());
  2758.         mplew.writeLong(0);
  2759.         mplew.writeShort(0);
  2760.         mplew.writeInt(mountid);
  2761.         mplew.writeInt(skillid);
  2762.         mplew.writeInt(0);
  2763.         mplew.writeShort(0);
  2764.         mplew.write(0);
  2765.         mplew.write(0);
  2766.  
  2767.         return mplew.getPacket();
  2768.     }
  2769.  
  2770.     public static MaplePacket giveDebuff(List<Pair<MapleDisease, Integer>> statups, MobSkill skill) {
  2771.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2772.  
  2773.         mplew.writeShort(SendPacketOpcode.GIVE_BUFF.getValue());
  2774.  
  2775.         long mask = getLongMaskD(statups);
  2776.  
  2777.         mplew.writeLong(0);
  2778.         mplew.writeLong(mask);
  2779.  
  2780.         for (Pair<MapleDisease, Integer> statup : statups) {
  2781.             mplew.writeShort(statup.getRight().shortValue());
  2782.             mplew.writeShort(skill.getSkillId());
  2783.             mplew.writeShort(skill.getSkillLevel());
  2784.             mplew.writeInt((int) skill.getDuration());
  2785.         }
  2786.  
  2787.         mplew.writeShort(0); // ??? wk charges have 600 here o.o
  2788.  
  2789.         mplew.writeShort(900);//Delay
  2790.  
  2791.         mplew.write(1);
  2792.  
  2793.         return mplew.getPacket();
  2794.     }
  2795.        
  2796.         public static MaplePacket giveEnergyCharge(int barammount) {
  2797.             MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2798.             mplew.writeShort(SendPacketOpcode.GIVE_BUFF.getValue());
  2799.             mplew.writeInt(0);
  2800.             mplew.writeLong(MapleBuffStat.ENERGY_CHARGE.getValue()); //energy charge buffstat
  2801.             mplew.writeShort(0);
  2802.             mplew.writeInt(0);
  2803.             mplew.writeShort(barammount); // 0=no bar, 10000=full bar
  2804.             mplew.writeShort(0);
  2805.             mplew.writeLong(0);
  2806.             mplew.write(0);
  2807.             mplew.writeInt(50);
  2808.             return mplew.getPacket();
  2809.         }  
  2810.  
  2811.         public static MaplePacket giveForeignEnergyCharge(int cid, int barammount) {
  2812.             MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2813.             mplew.writeShort(SendPacketOpcode.GIVE_FOREIGN_BUFF.getValue());
  2814.             mplew.writeInt(cid);
  2815.             mplew.writeInt(0);
  2816.             mplew.writeLong(MapleBuffStat.ENERGY_CHARGE.getValue()); //energy charge buffstat
  2817.             mplew.writeShort(0);
  2818.             mplew.writeInt(0);
  2819.             mplew.writeShort(barammount); // 0=no bar, 10000=full bar
  2820.             mplew.writeShort(0);
  2821.             mplew.writeLong(0);
  2822.             mplew.write(0);
  2823.             mplew.writeInt(50);
  2824.             return mplew.getPacket();
  2825.         }
  2826.  
  2827.     public static MaplePacket giveForeignDebuff(int cid, List<Pair<MapleDisease, Integer>> statups, MobSkill skill) {
  2828.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2829.  
  2830.         mplew.writeShort(SendPacketOpcode.GIVE_FOREIGN_BUFF.getValue());
  2831.  
  2832.         mplew.writeInt(cid);
  2833.         long mask = getLongMaskD(statups);
  2834.  
  2835.         mplew.writeLong(0);
  2836.         mplew.writeLong(mask);
  2837.  
  2838.         for (@SuppressWarnings("unused") Pair<MapleDisease, Integer> statup : statups) {
  2839.             //mplew.writeShort(statup.getRight().byteValue());
  2840.             mplew.writeShort(skill.getSkillId());
  2841.             mplew.writeShort(skill.getSkillLevel());
  2842.         }
  2843.         mplew.writeShort(0); // same as give_buff
  2844.  
  2845.         mplew.writeShort(900);//Delay
  2846.  
  2847.         return mplew.getPacket();
  2848.     }
  2849.  
  2850.     public static MaplePacket cancelForeignDebuff(int cid, List<MapleDisease> statups) {
  2851.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2852.  
  2853.         mplew.writeShort(SendPacketOpcode.CANCEL_FOREIGN_BUFF.getValue());
  2854.  
  2855.         mplew.writeInt(cid);
  2856.         long mask = getLongMaskFromListD(statups);
  2857.  
  2858.         mplew.writeLong(0);
  2859.         mplew.writeLong(mask);
  2860.  
  2861.         return mplew.getPacket();
  2862.     }
  2863.  
  2864.     public static MaplePacket showMountBuff(int cid, int skillid, int mountid) {
  2865.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2866.         mplew.writeShort(SendPacketOpcode.GIVE_FOREIGN_BUFF.getValue());
  2867.         mplew.writeInt(cid);
  2868.         mplew.writeLong(MapleBuffStat.MONSTER_RIDING.getValue());
  2869.         mplew.writeLong(0);
  2870.         mplew.writeShort(0);
  2871.         mplew.writeInt(mountid);
  2872.         mplew.writeInt(skillid);
  2873.         mplew.writeInt(0);
  2874.         mplew.writeShort(0);
  2875.         mplew.write(0);
  2876.  
  2877.         return mplew.getPacket();
  2878.     }
  2879.  
  2880.     public static MaplePacket showPirateBuff(int cid, int skillid, int time, List<Pair<MapleBuffStat, Integer>> statups) {
  2881.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2882.  
  2883.         mplew.writeShort(SendPacketOpcode.GIVE_FOREIGN_BUFF.getValue());
  2884.         mplew.writeInt(cid);
  2885.         long mask = getLongMask(statups);
  2886.         mplew.writeLong(mask);
  2887.         mplew.writeLong(0);
  2888.         mplew.writeShort(0);
  2889.         for (Pair<MapleBuffStat, Integer> statup : statups) {
  2890.             mplew.writeShort(statup.getRight());
  2891.             mplew.writeShort(0);
  2892.             mplew.writeInt(skillid);
  2893.             mplew.writeInt(0);
  2894.             mplew.write(0);
  2895.             mplew.writeShort(time);
  2896.         }
  2897.         mplew.writeShort(0);
  2898.  
  2899.         return mplew.getPacket();
  2900.     }
  2901.  
  2902.     public static MaplePacket showSpeedInfusion(int cid, int skillid, int time, List<Pair<MapleBuffStat, Integer>> statups) {
  2903.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2904.  
  2905.         mplew.writeShort(SendPacketOpcode.GIVE_FOREIGN_BUFF.getValue());
  2906.         mplew.writeInt(cid);
  2907.         long mask = getLongMask(statups);
  2908.         mplew.writeLong(mask);
  2909.         mplew.writeLong(0);
  2910.         mplew.writeShort(0);
  2911.         mplew.writeInt(statups.get(0).getRight());
  2912.         mplew.writeInt(skillid);
  2913.         mplew.writeInt(0);
  2914.         mplew.writeInt(0);
  2915.         mplew.writeShort(0);
  2916.         mplew.writeShort(time);
  2917.         mplew.writeShort(0);
  2918.  
  2919.         return mplew.getPacket();
  2920.     }
  2921.  
  2922.     public static MaplePacket giveForeignBuff(int cid, List<Pair<MapleBuffStat, Integer>> statups, boolean morph) {
  2923.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2924.  
  2925.         mplew.writeShort(SendPacketOpcode.GIVE_FOREIGN_BUFF.getValue());
  2926.         mplew.writeInt(cid);
  2927.         long mask = getLongMask(statups);
  2928.         mplew.writeLong(0);
  2929.         mplew.writeLong(mask);
  2930.  
  2931.         for (Pair<MapleBuffStat, Integer> statup : statups) {
  2932.             if (morph) {
  2933.                 mplew.writeInt(statup.getRight());
  2934.             } else {
  2935.                 mplew.writeShort(statup.getRight());
  2936.             }
  2937.         }
  2938.  
  2939.         mplew.writeShort(0);
  2940.         mplew.write(0);
  2941.  
  2942.         return mplew.getPacket();
  2943.     }
  2944.  
  2945.     public static MaplePacket cancelForeignBuff(int cid, List<MapleBuffStat> statups) {
  2946.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2947.  
  2948.         mplew.writeShort(SendPacketOpcode.CANCEL_FOREIGN_BUFF.getValue());
  2949.         mplew.writeInt(cid);
  2950.         long mask = getLongMaskFromList(statups);
  2951.         mplew.writeLong(isFirstLong(statups) ? mask : 0);
  2952.         mplew.writeLong(isFirstLong(statups) ? 0 : mask);
  2953.  
  2954.         return mplew.getPacket();
  2955.     }
  2956.  
  2957.     public static MaplePacket cancelBuff(List<MapleBuffStat> statups) {
  2958.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2959.  
  2960.         mplew.writeShort(SendPacketOpcode.CANCEL_BUFF.getValue());
  2961.  
  2962.         long mask = getLongMaskFromList(statups);
  2963.  
  2964.         mplew.writeLong(isFirstLong(statups) ? mask : 0);
  2965.         mplew.writeLong(isFirstLong(statups) ? 0 : mask);
  2966.         mplew.write(3); // wtf?
  2967.  
  2968.         return mplew.getPacket();
  2969.     }
  2970.  
  2971.     private static boolean isFirstLong(List<MapleBuffStat> statups) {
  2972.         for (MapleBuffStat stat : statups) {
  2973.             if (stat.equals(MapleBuffStat.DASH) ||
  2974.                     stat.equals(MapleBuffStat.DASH2) ||
  2975.                     stat.equals(MapleBuffStat.SPEED_INFUSION) ||
  2976.                     stat.equals(MapleBuffStat.MONSTER_RIDING) ||
  2977.                     stat.equals(MapleBuffStat.ENERGY_CHARGE)) {
  2978.                 return true;
  2979.             }
  2980.         }
  2981.         return false;
  2982.     }
  2983.  
  2984.     public static MaplePacket cancelDebuff(List<MapleDisease> statups) {
  2985.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2986.  
  2987.         mplew.writeShort(SendPacketOpcode.CANCEL_BUFF.getValue());
  2988.         long mask = getLongMaskFromListD(statups);
  2989.  
  2990.         mplew.writeLong(0);
  2991.         mplew.writeLong(mask);
  2992.  
  2993.         mplew.write(0);
  2994.         return mplew.getPacket();
  2995.     }
  2996.  
  2997.     public static MaplePacket getPlayerShopChat(MapleCharacter c, String chat, boolean owner) {
  2998.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  2999.         mplew.writeShort(SendPacketOpcode.PLAYER_INTERACTION.getValue());
  3000.         mplew.write(HexTool.getByteArrayFromHexString("06 08"));
  3001.         mplew.write(owner ? 0 : 1);
  3002.         mplew.writeMapleAsciiString(c.getName() + " : " + chat);
  3003.         return mplew.getPacket();
  3004.     }
  3005.  
  3006.     public static MaplePacket getPlayerShopNewVisitor(MapleCharacter c) {
  3007.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3008.         mplew.writeShort(SendPacketOpcode.PLAYER_INTERACTION.getValue());
  3009.         mplew.write(HexTool.getByteArrayFromHexString("04 02"));
  3010.         addCharLook(mplew, c, false);
  3011.         mplew.writeMapleAsciiString(c.getName());
  3012.         return mplew.getPacket();
  3013.     }
  3014.  
  3015.     public static MaplePacket getTradePartnerAdd(MapleCharacter c) {
  3016.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3017.         mplew.writeShort(SendPacketOpcode.PLAYER_INTERACTION.getValue());
  3018.         mplew.write(HexTool.getByteArrayFromHexString("04 01"));
  3019.  
  3020.         addCharLook(mplew, c, false);
  3021.         mplew.writeMapleAsciiString(c.getName());
  3022.         return mplew.getPacket();
  3023.     }
  3024.  
  3025.     public static MaplePacket getTradeInvite(MapleCharacter c) {
  3026.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3027.         mplew.writeShort(SendPacketOpcode.PLAYER_INTERACTION.getValue());
  3028.         mplew.write(HexTool.getByteArrayFromHexString("02 03"));
  3029.         mplew.writeMapleAsciiString(c.getName());
  3030.         mplew.write(HexTool.getByteArrayFromHexString("B7 50 00 00"));
  3031.         return mplew.getPacket();
  3032.     }
  3033.  
  3034.     public static MaplePacket getTradeMesoSet(byte number, int meso) {
  3035.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3036.         mplew.writeShort(SendPacketOpcode.PLAYER_INTERACTION.getValue());
  3037.         mplew.write(0xF);
  3038.         mplew.write(number);
  3039.         mplew.writeInt(meso);
  3040.         return mplew.getPacket();
  3041.     }
  3042.  
  3043.     public static MaplePacket getTradeItemAdd(byte number, IItem item) {
  3044.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3045.         mplew.writeShort(SendPacketOpcode.PLAYER_INTERACTION.getValue());
  3046.         mplew.write(0xE);
  3047.         mplew.write(number);
  3048.         addItemInfo(mplew, item);
  3049.         return mplew.getPacket();
  3050.     }
  3051.  
  3052.     public static MaplePacket getPlayerShopItemUpdate(MaplePlayerShop shop) {
  3053.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3054.         mplew.writeShort(SendPacketOpcode.PLAYER_INTERACTION.getValue());
  3055.         mplew.write(0x16);
  3056.         mplew.write(shop.getItems().size());
  3057.         for (MaplePlayerShopItem item : shop.getItems()) {
  3058.             mplew.writeShort(item.getBundles());
  3059.             mplew.writeShort(item.getItem().getQuantity());
  3060.             mplew.writeInt(item.getPrice());
  3061.             addItemInfo(mplew, item.getItem(), true, true, false);
  3062.         }
  3063.         return mplew.getPacket();
  3064.     }
  3065.  
  3066.     /**
  3067.      *
  3068.      * @param c
  3069.      * @param shop
  3070.      * @param owner
  3071.      * @return
  3072.      */
  3073.     public static MaplePacket getPlayerShop(MapleClient c, MaplePlayerShop shop, boolean owner) {
  3074.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3075.         mplew.writeShort(SendPacketOpcode.PLAYER_INTERACTION.getValue());
  3076.         mplew.write(HexTool.getByteArrayFromHexString("05 04 04"));
  3077.         mplew.write(owner ? 0 : 1);
  3078.         mplew.write(0);
  3079.         addCharLook(mplew, shop.getOwner(), false);
  3080.         mplew.writeMapleAsciiString(shop.getOwner().getName());
  3081.  
  3082.         MapleCharacter[] visitors = shop.getVisitors();
  3083.         for (int i = 0; i < visitors.length; i++) {
  3084.             if (visitors[i] != null) {
  3085.                 mplew.write(i + 1);
  3086.                 addCharLook(mplew, visitors[i], false);
  3087.                 mplew.writeMapleAsciiString(visitors[i].getName());
  3088.             }
  3089.         }
  3090.         mplew.write(0xFF);
  3091.         mplew.writeMapleAsciiString(shop.getDescription());
  3092.         List<MaplePlayerShopItem> items = shop.getItems();
  3093.         mplew.write(0x10);
  3094.         mplew.write(items.size());
  3095.         for (MaplePlayerShopItem item : items) {
  3096.             mplew.writeShort(item.getBundles());
  3097.             mplew.writeShort(item.getItem().getQuantity());
  3098.             mplew.writeInt(item.getPrice());
  3099.             addItemInfo(mplew, item.getItem(), true, true, false);
  3100.         }
  3101.         return mplew.getPacket();
  3102.     }
  3103.  
  3104.     public static MaplePacket getTradeStart(MapleClient c, MapleTrade trade, byte number) {
  3105.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3106.         mplew.writeShort(SendPacketOpcode.PLAYER_INTERACTION.getValue());
  3107.         mplew.write(HexTool.getByteArrayFromHexString("05 03 02"));
  3108.         mplew.write(number);
  3109.         if (number == 1) {
  3110.             mplew.write(0);
  3111.             addCharLook(mplew, trade.getPartner().getChr(), false);
  3112.             mplew.writeMapleAsciiString(trade.getPartner().getChr().getName());
  3113.         }
  3114.         mplew.write(number);
  3115.         /*if (number == 1) {
  3116.         mplew.write(0);
  3117.         mplew.writeInt(c.getPlayer().getId());
  3118.         }*/
  3119.         addCharLook(mplew, c.getPlayer(), false);
  3120.         mplew.writeMapleAsciiString(c.getPlayer().getName());
  3121.         mplew.write(0xFF);
  3122.         return mplew.getPacket();
  3123.     }
  3124.  
  3125.     public static MaplePacket getTradeConfirmation() {
  3126.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3127.         mplew.writeShort(SendPacketOpcode.PLAYER_INTERACTION.getValue());
  3128.         mplew.write(0x10);
  3129.         return mplew.getPacket();
  3130.     }
  3131.  
  3132.     public static MaplePacket getTradeCompletion(byte number) {
  3133.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3134.         mplew.writeShort(SendPacketOpcode.PLAYER_INTERACTION.getValue());
  3135.         mplew.write(0xA);
  3136.         mplew.write(number);
  3137.         mplew.write(6);
  3138.         return mplew.getPacket();
  3139.     }
  3140.  
  3141.     public static MaplePacket getTradeCancel(byte number) {
  3142.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3143.         mplew.writeShort(SendPacketOpcode.PLAYER_INTERACTION.getValue());
  3144.         mplew.write(0xA);
  3145.         mplew.write(number);
  3146.         mplew.write(2);
  3147.         return mplew.getPacket();
  3148.     }
  3149.  
  3150.     public static MaplePacket updateCharBox(MapleCharacter c) {
  3151.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3152.         mplew.writeShort(SendPacketOpcode.UPDATE_CHAR_BOX.getValue());
  3153.         mplew.writeInt(c.getId());
  3154.         if (c.getPlayerShop() != null) {
  3155.             addAnnounceBox(mplew, c.getPlayerShop());
  3156.         } else {
  3157.             mplew.write(0);
  3158.         }
  3159.         return mplew.getPacket();
  3160.     }
  3161.  
  3162.     public static MaplePacket getNPCTalk(int npc, byte msgType, String talk, String endBytes) {
  3163.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3164.         mplew.writeShort(SendPacketOpcode.NPC_TALK.getValue());
  3165.         mplew.write(4); // ?
  3166.  
  3167.         mplew.writeInt(npc);
  3168.         mplew.write(msgType);
  3169.         mplew.writeMapleAsciiString(talk);
  3170.         mplew.write(HexTool.getByteArrayFromHexString(endBytes));
  3171.         return mplew.getPacket();
  3172.     }
  3173.  
  3174.     public static MaplePacket getNPCTalkStyle(int npc, String talk, int styles[]) {
  3175.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3176.         mplew.writeShort(SendPacketOpcode.NPC_TALK.getValue());
  3177.         mplew.write(4); // ?
  3178.  
  3179.         mplew.writeInt(npc);
  3180.         mplew.write(7);
  3181.         mplew.writeMapleAsciiString(talk);
  3182.         mplew.write(styles.length);
  3183.         for (int i = 0; i < styles.length; i++) {
  3184.             mplew.writeInt(styles[i]);
  3185.         }
  3186.         return mplew.getPacket();
  3187.     }
  3188.  
  3189.     public static MaplePacket getNPCTalkNum(int npc, String talk, int def, int min, int max) {
  3190.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3191.         mplew.writeShort(SendPacketOpcode.NPC_TALK.getValue());
  3192.         mplew.write(4); // ?
  3193.  
  3194.         mplew.writeInt(npc);
  3195.         mplew.write(3);
  3196.         mplew.writeMapleAsciiString(talk);
  3197.         mplew.writeInt(def);
  3198.         mplew.writeInt(min);
  3199.         mplew.writeInt(max);
  3200.         mplew.writeInt(0);
  3201.         return mplew.getPacket();
  3202.     }
  3203.  
  3204.     public static MaplePacket getNPCTalkText(int npc, String talk) {
  3205.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3206.         mplew.writeShort(SendPacketOpcode.NPC_TALK.getValue());
  3207.         mplew.write(4); // ?
  3208.  
  3209.         mplew.writeInt(npc);
  3210.         mplew.write(2);
  3211.         mplew.writeMapleAsciiString(talk);
  3212.         mplew.writeInt(0);
  3213.         mplew.writeInt(0);
  3214.         return mplew.getPacket();
  3215.     }
  3216.  
  3217.     public static MaplePacket showLevelup(int cid) {
  3218.         return showForeignEffect(cid, 0);
  3219.     }
  3220.  
  3221.     public static MaplePacket showJobChange(int cid) {
  3222.         return showForeignEffect(cid, 8);
  3223.     }
  3224.  
  3225.     public static MaplePacket showForeignEffect(int cid, int effect) {
  3226.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3227.         mplew.writeShort(SendPacketOpcode.SHOW_FOREIGN_EFFECT.getValue());
  3228.         mplew.writeInt(cid); // ?
  3229.  
  3230.         mplew.write(effect);
  3231.         return mplew.getPacket();
  3232.     }
  3233.  
  3234.     public static MaplePacket showBuffeffect(int cid, int skillid, int effectid) {
  3235.         return showBuffeffect(cid, skillid, effectid, (byte) 3, false);
  3236.     }
  3237.  
  3238.         public static MaplePacket showBuffeffect(int cid, int skillid, int effectid, byte direction) {
  3239.             MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3240.             mplew.writeShort(SendPacketOpcode.SHOW_FOREIGN_EFFECT.getValue());
  3241.             mplew.writeInt(cid); // ?
  3242.                 mplew.write(effectid); //buff level
  3243.                 mplew.writeInt(skillid);
  3244.                 mplew.write(1);
  3245.                 if (direction != (byte) 3)
  3246.                     mplew.write(direction);
  3247.             return mplew.getPacket();
  3248.         }
  3249.  
  3250.     public static MaplePacket showBuffeffect(int cid, int skillid, int effectid, byte direction, boolean morph) {
  3251.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3252.         mplew.writeShort(SendPacketOpcode.SHOW_FOREIGN_EFFECT.getValue());
  3253.         mplew.writeInt(cid);
  3254.         if (morph) {
  3255.             mplew.write(1);
  3256.             mplew.writeInt(skillid);
  3257.             mplew.write(direction);
  3258.         }
  3259.         mplew.write(effectid);
  3260.         mplew.writeInt(skillid);
  3261.         mplew.write(1); // probably buff level but we don't know it and it
  3262.         // doesn't really matter
  3263.  
  3264.         if (direction != (byte) 3) {
  3265.             mplew.write(direction);
  3266.         }
  3267.  
  3268.         return mplew.getPacket();
  3269.     }
  3270.  
  3271.     public static MaplePacket showOwnBuffEffect(int skillid, int effectid) {
  3272.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3273.         mplew.writeShort(SendPacketOpcode.SHOW_ITEM_GAIN_INCHAT.getValue());
  3274.         mplew.write(effectid);
  3275.         mplew.writeInt(skillid);
  3276.         mplew.write(1); // probably buff level but we don't know it and it
  3277.         // doesn't really matter
  3278.  
  3279.         return mplew.getPacket();
  3280.     }
  3281.  
  3282.     public static MaplePacket updateSkill(int skillid, int level, int masterlevel) {
  3283.         // 1E 00 01 01 00 E9 03 00 00 01 00 00 00 00 00 00 00 01
  3284.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3285.         mplew.writeShort(SendPacketOpcode.UPDATE_SKILLS.getValue());
  3286.         mplew.write(1);
  3287.         mplew.writeShort(1);
  3288.         mplew.writeInt(skillid);
  3289.         mplew.writeInt(level);
  3290.         mplew.writeInt(masterlevel);
  3291.         mplew.write(1);
  3292.         return mplew.getPacket();
  3293.     }
  3294.  
  3295.     public static MaplePacket updateQuestMobKills(MapleQuestStatus status) {
  3296.         // 21 00 01 FB 03 01 03 00 30 30 31
  3297.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3298.         mplew.writeShort(SendPacketOpcode.SHOW_STATUS_INFO.getValue());
  3299.         mplew.write(1);
  3300.         mplew.writeShort(status.getQuest().getId());
  3301.         mplew.write(1);
  3302.         String killStr = "";
  3303.         for (int kills : status.getMobKills().values()) {
  3304.             killStr += StringUtil.getLeftPaddedStr(String.valueOf(kills), '0', 3);
  3305.         }
  3306.         mplew.writeMapleAsciiString(killStr);
  3307.         mplew.writeInt(0);
  3308.         mplew.writeInt(0);
  3309.         return mplew.getPacket();
  3310.     }
  3311.  
  3312.     public static MaplePacket getShowQuestCompletion(int id) {
  3313.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3314.         mplew.writeShort(SendPacketOpcode.SHOW_QUEST_COMPLETION.getValue());
  3315.         mplew.writeShort(id);
  3316.         return mplew.getPacket();
  3317.     }
  3318.  
  3319.     public static MaplePacket getKeymap(Map<Integer, MapleKeyBinding> keybindings) {
  3320.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3321.         mplew.writeShort(SendPacketOpcode.KEYMAP.getValue());
  3322.         mplew.write(0);
  3323.  
  3324.         for (int x = 0; x < 90; x++) {
  3325.             MapleKeyBinding binding = keybindings.get(Integer.valueOf(x));
  3326.             if (binding != null) {
  3327.                 mplew.write(binding.getType());
  3328.                 mplew.writeInt(binding.getAction());
  3329.             } else {
  3330.                 mplew.write(0);
  3331.                 mplew.writeInt(0);
  3332.             }
  3333.         }
  3334.  
  3335.         return mplew.getPacket();
  3336.     }
  3337.  
  3338.     public static MaplePacket getWhisper(String sender, int channel, String text) {
  3339.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3340.         mplew.writeShort(SendPacketOpcode.WHISPER.getValue());
  3341.         mplew.write(0x12);
  3342.         mplew.writeMapleAsciiString(sender);
  3343.         mplew.writeShort(channel - 1); // I guess this is the channel
  3344.  
  3345.         mplew.writeMapleAsciiString(text);
  3346.         return mplew.getPacket();
  3347.     }
  3348.  
  3349.     /**
  3350.      *
  3351.      * @param target name of the target character
  3352.      * @param reply error code: 0x0 = cannot find char, 0x1 = success
  3353.      * @return the MaplePacket
  3354.      */
  3355.     public static MaplePacket getWhisperReply(String target, byte reply) {
  3356.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3357.         mplew.writeShort(SendPacketOpcode.WHISPER.getValue());
  3358.         mplew.write(0x0A); // whisper?
  3359.  
  3360.         mplew.writeMapleAsciiString(target);
  3361.         mplew.write(reply);
  3362.         // System.out.println(HexTool.toString(mplew.getPacket().getBytes()));
  3363.         return mplew.getPacket();
  3364.     }
  3365.  
  3366.     public static MaplePacket getFindReplyWithMap(String target, int mapid) {
  3367.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3368.         mplew.writeShort(SendPacketOpcode.WHISPER.getValue());
  3369.         mplew.write(9);
  3370.         mplew.writeMapleAsciiString(target);
  3371.         mplew.write(1);
  3372.         mplew.writeInt(mapid);
  3373.         // ?? official doesn't send zeros here but whatever
  3374.         mplew.write(new byte[8]);
  3375.         return mplew.getPacket();
  3376.     }
  3377.  
  3378.     public static MaplePacket getFindReply(String target, int channel) {
  3379.         // Received UNKNOWN (1205941596.79689): (25)
  3380.         // 54 00 09 07 00 64 61 76 74 73 61 69 01 86 7F 3D 36 D5 02 00 00 22 00
  3381.         // 00 00
  3382.         // T....davtsai..=6...."...
  3383.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3384.         mplew.writeShort(SendPacketOpcode.WHISPER.getValue());
  3385.         mplew.write(9);
  3386.         mplew.writeMapleAsciiString(target);
  3387.         mplew.write(3);
  3388.         mplew.writeInt(channel - 1);
  3389.         return mplew.getPacket();
  3390.     }
  3391.  
  3392.     public static MaplePacket getInventoryFull() {
  3393.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3394.         mplew.writeShort(SendPacketOpcode.MODIFY_INVENTORY_ITEM.getValue());
  3395.         mplew.write(1);
  3396.         mplew.write(0);
  3397.         return mplew.getPacket();
  3398.     }
  3399.  
  3400.     public static MaplePacket getShowInventoryFull() {
  3401.         return getShowInventoryStatus(0xff);
  3402.     }
  3403.  
  3404.     public static MaplePacket showItemUnavailable() {
  3405.         return getShowInventoryStatus(0xfe);
  3406.     }
  3407.  
  3408.     public static MaplePacket getShowInventoryStatus(int mode) {
  3409.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3410.         mplew.writeShort(SendPacketOpcode.SHOW_STATUS_INFO.getValue());
  3411.         mplew.write(0);
  3412.         mplew.write(mode);
  3413.         mplew.writeInt(0);
  3414.         mplew.writeInt(0);
  3415.         return mplew.getPacket();
  3416.     }
  3417.  
  3418.     public static MaplePacket getStorage(int npcId, byte slots, Collection<IItem> items, int meso) {
  3419.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3420.         mplew.writeShort(SendPacketOpcode.OPEN_STORAGE.getValue());
  3421.         mplew.write(0x16);
  3422.         mplew.writeInt(npcId);
  3423.         mplew.write(slots);
  3424.         mplew.writeShort(0x7E);
  3425.         mplew.writeShort(0);
  3426.         mplew.writeInt(0);
  3427.         mplew.writeInt(meso);
  3428.         mplew.writeShort(0);
  3429.         mplew.write((byte) items.size());
  3430.         for (IItem item : items) {
  3431.             addItemInfo(mplew, item, true, true, false);
  3432.         }
  3433.         mplew.writeShort(0);
  3434.         mplew.write(0);
  3435.         return mplew.getPacket();
  3436.     }
  3437.  
  3438.     public static MaplePacket getStorageFull() {
  3439.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3440.         mplew.writeShort(SendPacketOpcode.OPEN_STORAGE.getValue());
  3441.         mplew.write(0x11);
  3442.         return mplew.getPacket();
  3443.     }
  3444.  
  3445.     public static MaplePacket mesoStorage(byte slots, int meso) {
  3446.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3447.         mplew.writeShort(SendPacketOpcode.OPEN_STORAGE.getValue());
  3448.         mplew.write(0x13);
  3449.         mplew.write(slots);
  3450.         mplew.writeShort(2);
  3451.         mplew.writeShort(0);
  3452.         mplew.writeInt(0);
  3453.         mplew.writeInt(meso);
  3454.         return mplew.getPacket();
  3455.     }
  3456.  
  3457.     public static MaplePacket storeStorage(byte slots, MapleInventoryType type, Collection<IItem> items) {
  3458.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3459.         mplew.writeShort(SendPacketOpcode.OPEN_STORAGE.getValue());
  3460.         mplew.write(0xD);
  3461.         mplew.write(slots);
  3462.         mplew.writeShort(type.getBitfieldEncoding());
  3463.         mplew.writeShort(0);
  3464.         mplew.writeInt(0);
  3465.         mplew.write(items.size());
  3466.         for (IItem item : items) {
  3467.             addItemInfo(mplew, item, true, true, false);
  3468.             // mplew.write(0);
  3469.         }
  3470.  
  3471.         return mplew.getPacket();
  3472.     }
  3473.  
  3474.     public static MaplePacket takeOutStorage(byte slots, MapleInventoryType type, Collection<IItem> items) {
  3475.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3476.         mplew.writeShort(SendPacketOpcode.OPEN_STORAGE.getValue());
  3477.         mplew.write(0x9);
  3478.         mplew.write(slots);
  3479.         mplew.writeShort(type.getBitfieldEncoding());
  3480.         mplew.writeShort(0);
  3481.         mplew.writeInt(0);
  3482.         mplew.write(items.size());
  3483.         for (IItem item : items) {
  3484.             addItemInfo(mplew, item, true, true, false);
  3485.             // mplew.write(0);
  3486.         }
  3487.  
  3488.         return mplew.getPacket();
  3489.     }
  3490.  
  3491.     /**
  3492.      *
  3493.      * @param oid
  3494.      * @param remhp in %
  3495.      * @return
  3496.      */
  3497.     public static MaplePacket showMonsterHP(int oid, int remhppercentage) {
  3498.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3499.         mplew.writeShort(SendPacketOpcode.SHOW_MONSTER_HP.getValue());
  3500.         mplew.writeInt(oid);
  3501.         mplew.write(remhppercentage);
  3502.  
  3503.         return mplew.getPacket();
  3504.     }
  3505.  
  3506.     public static MaplePacket showBossHP(int oid, int currHP, int maxHP, byte tagColor, byte tagBgColor) {
  3507.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3508.  
  3509.         //53 00 05 21 B3 81 00 46 F2 5E 01 C0 F3 5E 01 04 01
  3510.         //00 81 B3 21 = 8500001 = Pap monster ID
  3511.         //01 5E F3 C0 = 23,000,000 = Pap max HP
  3512.         //04, 01 - boss bar color/background color as provided in WZ
  3513.  
  3514.         mplew.writeShort(SendPacketOpcode.BOSS_ENV.getValue());
  3515.         mplew.write(5);
  3516.         mplew.writeInt(oid);
  3517.         mplew.writeInt(currHP);
  3518.         mplew.writeInt(maxHP);
  3519.         mplew.write(tagColor);
  3520.         mplew.write(tagBgColor);
  3521.  
  3522.         return mplew.getPacket();
  3523.     }
  3524.  
  3525.     public static MaplePacket giveFameResponse(int mode, String charname, int newfame) {
  3526.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3527.         mplew.writeShort(SendPacketOpcode.FAME_RESPONSE.getValue());
  3528.  
  3529.         mplew.write(0);
  3530.         mplew.writeMapleAsciiString(charname);
  3531.         mplew.write(mode);
  3532.         mplew.writeShort(newfame);
  3533.         mplew.writeShort(0);
  3534.  
  3535.         return mplew.getPacket();
  3536.     }
  3537.  
  3538.     /**
  3539.      * status can be: <br>
  3540.      * 0: ok, use giveFameResponse<br>
  3541.      * 1: the username is incorrectly entered<br>
  3542.      * 2: users under level 15 are unable to toggle with fame.<br>
  3543.      * 3: can't raise or drop fame anymore today.<br>
  3544.      * 4: can't raise or drop fame for this character for this month anymore.<br>
  3545.      * 5: received fame, use receiveFame()<br>
  3546.      * 6: level of fame neither has been raised nor dropped due to an unexpected
  3547.      * error
  3548.      *
  3549.      * @param status
  3550.      * @param mode
  3551.      * @param charname
  3552.      * @param newfame
  3553.      * @return
  3554.      */
  3555.     public static MaplePacket giveFameErrorResponse(int status) {
  3556.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3557.         mplew.writeShort(SendPacketOpcode.FAME_RESPONSE.getValue());
  3558.  
  3559.         mplew.write(status);
  3560.  
  3561.         return mplew.getPacket();
  3562.     }
  3563.  
  3564.     public static MaplePacket receiveFame(int mode, String charnameFrom) {
  3565.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3566.         mplew.writeShort(SendPacketOpcode.FAME_RESPONSE.getValue());
  3567.         mplew.write(5);
  3568.         mplew.writeMapleAsciiString(charnameFrom);
  3569.         mplew.write(mode);
  3570.  
  3571.         return mplew.getPacket();
  3572.     }
  3573.  
  3574.     public static MaplePacket partyCreated() {
  3575.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3576.         mplew.writeShort(SendPacketOpcode.PARTY_OPERATION.getValue());
  3577.         mplew.write(8);
  3578.         mplew.writeShort(0x8b);
  3579.         mplew.writeShort(2);
  3580.         mplew.write(CHAR_INFO_MAGIC);
  3581.         mplew.write(CHAR_INFO_MAGIC);
  3582.         mplew.writeInt(0);
  3583.  
  3584.         return mplew.getPacket();
  3585.     }
  3586.  
  3587.     public static MaplePacket partyInvite(MapleCharacter from) {
  3588.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3589.         mplew.writeShort(SendPacketOpcode.PARTY_OPERATION.getValue());
  3590.         mplew.write(4);
  3591.         mplew.writeInt(from.getParty().getId());
  3592.         mplew.writeMapleAsciiString(from.getName());
  3593.         mplew.write(0);
  3594.  
  3595.         return mplew.getPacket();
  3596.     }
  3597.  
  3598.     /**
  3599.      * 10: a beginner can't create a party<br>
  3600.      * 11/14/19: your request for a party didn't work due to an unexpected error<br>
  3601.      * 13: you have yet to join a party<br>
  3602.      * 16: already have joined a party<br>
  3603.      * 17: the party you are trying to join is already at full capacity<br>
  3604.      * 18: unable to find the requested character in this channel<br>
  3605.      *
  3606.      * @param message
  3607.      * @return
  3608.      */
  3609.     public static MaplePacket partyStatusMessage(int message) {
  3610.         // 32 00 08 DA 14 00 00 FF C9 9A 3B FF C9 9A 3B 22 03 6E 67
  3611.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3612.         mplew.writeShort(SendPacketOpcode.PARTY_OPERATION.getValue());
  3613.         mplew.write(message);
  3614.  
  3615.         return mplew.getPacket();
  3616.     }
  3617.  
  3618.     /**
  3619.      * 22: has denied the invitation<br>
  3620.      *
  3621.      * @param message
  3622.      * @param charname
  3623.      * @return
  3624.      */
  3625.     public static MaplePacket partyStatusMessage(int message, String charname) {
  3626.         // 32 00 08 DA 14 00 00 FF C9 9A 3B FF C9 9A 3B 22 03 6E 67
  3627.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3628.         mplew.writeShort(SendPacketOpcode.PARTY_OPERATION.getValue());
  3629.         mplew.write(message);
  3630.         mplew.writeMapleAsciiString(charname);
  3631.  
  3632.         return mplew.getPacket();
  3633.     }
  3634.  
  3635.     private static void addPartyStatus(int forchannel, MapleParty party, LittleEndianWriter lew, boolean leaving) {
  3636.         List<MaplePartyCharacter> partymembers = new ArrayList<MaplePartyCharacter>(party.getMembers());
  3637.         while (partymembers.size() < 6) {
  3638.             partymembers.add(new MaplePartyCharacter());
  3639.         }
  3640.         for (MaplePartyCharacter partychar : partymembers) {
  3641.             lew.writeInt(partychar.getId());
  3642.         }
  3643.         for (MaplePartyCharacter partychar : partymembers) {
  3644.             lew.writeAsciiString(StringUtil.getRightPaddedStr(partychar.getName(), '\0', 13));
  3645.         }
  3646.         for (MaplePartyCharacter partychar : partymembers) {
  3647.             lew.writeInt(partychar.getJobId());
  3648.         }
  3649.         for (MaplePartyCharacter partychar : partymembers) {
  3650.             lew.writeInt(partychar.getLevel());
  3651.         }
  3652.         for (MaplePartyCharacter partychar : partymembers) {
  3653.             if (partychar.isOnline()) {
  3654.                 lew.writeInt(partychar.getChannel() - 1);
  3655.             } else {
  3656.                 lew.writeInt(-2);
  3657.             }
  3658.         }
  3659.         lew.writeInt(party.getLeader().getId());
  3660.         for (MaplePartyCharacter partychar : partymembers) {
  3661.             if (partychar.getChannel() == forchannel) {
  3662.                 lew.writeInt(partychar.getMapid());
  3663.             } else {
  3664.                 lew.writeInt(0);
  3665.             }
  3666.         }
  3667.         for (MaplePartyCharacter partychar : partymembers) {
  3668.             if (partychar.getChannel() == forchannel && !leaving) {
  3669.                 lew.writeInt(partychar.getDoorTown());
  3670.                 lew.writeInt(partychar.getDoorTarget());
  3671.                 lew.writeInt(partychar.getDoorPosition().x);
  3672.                 lew.writeInt(partychar.getDoorPosition().y);
  3673.             } else {
  3674.                 lew.writeInt(0);
  3675.                 lew.writeInt(0);
  3676.                 lew.writeInt(0);
  3677.                 lew.writeInt(0);
  3678.             }
  3679.         }
  3680.     }
  3681.  
  3682.     public static MaplePacket updateParty(int forChannel, MapleParty party, PartyOperation op, MaplePartyCharacter target) {
  3683.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3684.  
  3685.         mplew.writeShort(SendPacketOpcode.PARTY_OPERATION.getValue());
  3686.         switch (op) {
  3687.             case DISBAND:
  3688.             case EXPEL:
  3689.             case LEAVE:
  3690.                 mplew.write(0xC);
  3691.                 mplew.writeInt(40546);
  3692.                 mplew.writeInt(target.getId());
  3693.  
  3694.                 if (op == PartyOperation.DISBAND) {
  3695.                     mplew.write(0);
  3696.                     mplew.writeInt(party.getId());
  3697.                 } else {
  3698.                     mplew.write(1);
  3699.                     if (op == PartyOperation.EXPEL) {
  3700.                         mplew.write(1);
  3701.                     } else {
  3702.                         mplew.write(0);
  3703.                     }
  3704.                     mplew.writeMapleAsciiString(target.getName());
  3705.                     addPartyStatus(forChannel, party, mplew, false);
  3706.                     // addLeavePartyTail(mplew);
  3707.                 }
  3708.  
  3709.                 break;
  3710.             case JOIN:
  3711.                 mplew.write(0xF);
  3712.                 mplew.writeInt(40546);
  3713.                 mplew.writeMapleAsciiString(target.getName());
  3714.                 addPartyStatus(forChannel, party, mplew, false);
  3715.                 // addJoinPartyTail(mplew);
  3716.                 break;
  3717.             case SILENT_UPDATE:
  3718.             case LOG_ONOFF:
  3719.                 mplew.write(0x7);
  3720.                 mplew.writeInt(party.getId());
  3721.                 addPartyStatus(forChannel, party, mplew, false);
  3722.                 break;
  3723.  
  3724.         }
  3725.         return mplew.getPacket();
  3726.     }
  3727.  
  3728.     public static MaplePacket partyPortal(int townId, int targetId, Point position) {
  3729.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3730.  
  3731.         mplew.writeShort(SendPacketOpcode.PARTY_OPERATION.getValue());
  3732.         mplew.writeShort(0x23);
  3733.         mplew.writeInt(townId);
  3734.         mplew.writeInt(targetId);
  3735.         mplew.writeShort(position.x);
  3736.         mplew.writeShort(position.y);
  3737.         return mplew.getPacket();
  3738.     }
  3739.  
  3740.     public static MaplePacket updatePartyMemberHP(int cid, int curhp, int maxhp) {
  3741.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3742.  
  3743.         mplew.writeShort(SendPacketOpcode.UPDATE_PARTYMEMBER_HP.getValue());
  3744.         mplew.writeInt(cid);
  3745.         mplew.writeInt(curhp);
  3746.         mplew.writeInt(maxhp);
  3747.         return mplew.getPacket();
  3748.     }
  3749.  
  3750.     /**
  3751.      * mode: 0 buddychat; 1 partychat; 2 guildchat
  3752.      *
  3753.      * @param name
  3754.      * @param chattext
  3755.      * @param mode
  3756.      * @return
  3757.      */
  3758.     public static MaplePacket multiChat(String name, String chattext, int mode) {
  3759.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3760.  
  3761.         mplew.writeShort(SendPacketOpcode.MULTICHAT.getValue());
  3762.         mplew.write(mode);
  3763.         mplew.writeMapleAsciiString(name);
  3764.         mplew.writeMapleAsciiString(chattext);
  3765.         return mplew.getPacket();
  3766.     }
  3767.  
  3768.     public static MaplePacket applyMonsterStatus(int oid, Map<MonsterStatus, Integer> stats, int skill,
  3769.             boolean monsterSkill, int delay) {
  3770.         return applyMonsterStatus(oid, stats, skill, monsterSkill, delay, null);
  3771.     }
  3772.  
  3773.     public static MaplePacket applyMonsterStatusTest(int oid, int mask, int delay, MobSkill mobskill, int value) {
  3774.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3775.  
  3776.         // 9B 00 67 40 6F 00 80 00 00 00 01 00 FD FE 30 00 08 00 64 00 01
  3777.         // 1D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00 01 00 79 00 01 00 B4 78 00 00 00 00 84 03
  3778.         // B4 00 A8 90 03 00 00 00 04 00 01 00 8C 00 03 00 14 00 4C 04 02
  3779.         mplew.writeShort(SendPacketOpcode.APPLY_MONSTER_STATUS.getValue());
  3780.         mplew.writeInt(oid);
  3781.  
  3782.         mplew.writeInt(mask);
  3783.         mplew.writeShort(1);
  3784.         mplew.writeShort(mobskill.getSkillId());
  3785.         mplew.writeShort(mobskill.getSkillLevel());
  3786.         mplew.writeShort(0); // as this looks similar to giveBuff this
  3787.         // might actually be the buffTime but it's
  3788.         // not displayed anywhere
  3789.  
  3790.         mplew.writeShort(delay); // delay in ms
  3791.  
  3792.         mplew.write(1); // ?
  3793.  
  3794.         return mplew.getPacket();
  3795.     }
  3796.  
  3797.     public static MaplePacket applyMonsterStatusTest2(int oid, int mask, int skill, int value) {
  3798.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3799.  
  3800.         // 9B 00 67 40 6F 00 80 00 00 00 01 00 FD FE 30 00 08 00 64 00 01
  3801.         // 1D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00 01 00 79 00 01 00 B4 78 00 00 00 00 84 03
  3802.         // B4 00 A8 90 03 00 00 00 04 00 01 00 8C 00 03 00 14 00 4C 04 02
  3803.         mplew.writeShort(SendPacketOpcode.APPLY_MONSTER_STATUS.getValue());
  3804.         mplew.writeInt(oid);
  3805.  
  3806.         mplew.writeInt(mask);
  3807.  
  3808.         mplew.writeShort(value);
  3809.         mplew.writeInt(skill);
  3810.         mplew.writeShort(0); // as this looks similar to giveBuff this
  3811.         // might actually be the buffTime but it's
  3812.         // not displayed anywhere
  3813.  
  3814.         mplew.writeShort(0); // delay in ms
  3815.  
  3816.         mplew.write(1); // ?
  3817.  
  3818.         return mplew.getPacket();
  3819.     }
  3820.  
  3821.     public static MaplePacket applyMonsterStatus(int oid, Map<MonsterStatus, Integer> stats, int skill,
  3822.             boolean monsterSkill, int delay, MobSkill mobskill) {
  3823.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3824.  
  3825.         // 9B 00 67 40 6F 00 80 00 00 00 01 00 FD FE 30 00 08 00 64 00 01
  3826.         // 1D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00 01 00 79 00 01 00 B4 78 00 00 00 00 84 03
  3827.         // B4 00 A8 90 03 00 00 00 04 00 01 00 8C 00 03 00 14 00 4C 04 02
  3828.         mplew.writeShort(SendPacketOpcode.APPLY_MONSTER_STATUS.getValue());
  3829.         mplew.writeInt(oid);
  3830.  
  3831.         int mask = 0;
  3832.         for (MonsterStatus stat : stats.keySet()) {
  3833.             mask |= stat.getValue();
  3834.         }
  3835.  
  3836.         mplew.writeInt(mask);
  3837.  
  3838.         for (Integer val : stats.values()) {
  3839.             mplew.writeShort(val);
  3840.             if (monsterSkill) {
  3841.                 mplew.writeShort(mobskill.getSkillId());
  3842.                 mplew.writeShort(mobskill.getSkillLevel());
  3843.             } else {
  3844.                 mplew.writeInt(skill);
  3845.             }
  3846.             mplew.writeShort(0); // as this looks similar to giveBuff this
  3847.             // might actually be the buffTime but it's
  3848.             // not displayed anywhere
  3849.  
  3850.         }
  3851.  
  3852.         mplew.writeShort(delay); // delay in ms
  3853.  
  3854.         mplew.write(1); // ?
  3855.  
  3856.         return mplew.getPacket();
  3857.     }
  3858.  
  3859.     public static MaplePacket cancelMonsterStatus(int oid, Map<MonsterStatus, Integer> stats) {
  3860.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3861.         mplew.writeShort(SendPacketOpcode.CANCEL_MONSTER_STATUS.getValue());
  3862.  
  3863.         mplew.writeInt(oid);
  3864.         int mask = 0;
  3865.         for (MonsterStatus stat : stats.keySet()) {
  3866.             mask |= stat.getValue();
  3867.         }
  3868.  
  3869.         mplew.writeInt(mask);
  3870.         mplew.write(1);
  3871.  
  3872.         return mplew.getPacket();
  3873.     }
  3874.  
  3875.     public static MaplePacket getClock(int time) {
  3876.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3877.  
  3878.         mplew.writeShort(SendPacketOpcode.CLOCK.getValue());
  3879.         mplew.write(2);
  3880.         mplew.writeInt(time);
  3881.  
  3882.         return mplew.getPacket();
  3883.     }
  3884.  
  3885.     public static MaplePacket getClockTime(int hour, int min, int sec) {
  3886.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3887.  
  3888.         mplew.writeShort(SendPacketOpcode.CLOCK.getValue());
  3889.         mplew.write(1);
  3890.         mplew.write(hour);
  3891.         mplew.write(min);
  3892.         mplew.write(sec);
  3893.  
  3894.         return mplew.getPacket();
  3895.     }
  3896.  
  3897.     public static MaplePacket spawnMist(int oid, int ownerCid, int skill, int level, MapleMist mist) {
  3898.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3899.  
  3900.         mplew.writeShort(SendPacketOpcode.SPAWN_MIST.getValue());
  3901.         mplew.writeInt(oid);
  3902.         mplew.writeInt(mist.isMobMist() ? 0 : mist.isPoisonMist() ? 1 : 2);
  3903.         mplew.writeInt(ownerCid);
  3904.         mplew.writeInt(skill);
  3905.         mplew.write(level);
  3906.         mplew.writeShort(mist.getSkillDelay());
  3907.         mplew.writeInt(mist.getBox().x);
  3908.         mplew.writeInt(mist.getBox().y);
  3909.         mplew.writeInt(mist.getBox().x + mist.getBox().width);
  3910.         mplew.writeInt(mist.getBox().y + mist.getBox().height);
  3911.         mplew.writeInt(0);
  3912.  
  3913.         return mplew.getPacket();
  3914.     }
  3915.  
  3916.     public static MaplePacket removeMist(int oid) {
  3917.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3918.  
  3919.         mplew.writeShort(SendPacketOpcode.REMOVE_MIST.getValue());
  3920.         mplew.writeInt(oid);
  3921.  
  3922.         return mplew.getPacket();
  3923.     }
  3924.  
  3925.     public static MaplePacket damageSummon(int cid, int summonSkillId, int damage, int unkByte, int monsterIdFrom) {
  3926.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3927.  
  3928.         mplew.writeShort(SendPacketOpcode.DAMAGE_SUMMON.getValue());
  3929.         mplew.writeInt(cid);
  3930.         mplew.writeInt(summonSkillId);
  3931.         mplew.write(unkByte);
  3932.         mplew.writeInt(damage);
  3933.         mplew.writeInt(monsterIdFrom);
  3934.         mplew.write(0);
  3935.  
  3936.         return mplew.getPacket();
  3937.     }
  3938.  
  3939.     public static MaplePacket damageMonster(int oid, int damage) {
  3940.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3941.  
  3942.         mplew.writeShort(SendPacketOpcode.DAMAGE_MONSTER.getValue());
  3943.         mplew.writeInt(oid);
  3944.         mplew.write(0);
  3945.         mplew.writeInt(damage);
  3946.  
  3947.         return mplew.getPacket();
  3948.     }
  3949.  
  3950.     public static MaplePacket healMonster(int oid, int heal) {
  3951.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3952.  
  3953.         mplew.writeShort(SendPacketOpcode.DAMAGE_MONSTER.getValue());
  3954.         mplew.writeInt(oid);
  3955.         mplew.write(0);
  3956.         mplew.writeInt(-heal);
  3957.  
  3958.         return mplew.getPacket();
  3959.     }
  3960.  
  3961.     public static MaplePacket updateBuddylist(Collection<BuddylistEntry> buddylist) {
  3962.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3963.  
  3964.         mplew.writeShort(SendPacketOpcode.BUDDYLIST.getValue());
  3965.         mplew.write(7);
  3966.         mplew.write(buddylist.size());
  3967.         for (BuddylistEntry buddy : buddylist) {
  3968.             if (buddy.isVisible()) {
  3969.                 mplew.writeInt(buddy.getCharacterId());
  3970.                 mplew.writeAsciiString(StringUtil.getRightPaddedStr(buddy.getName(), '\0', 13));
  3971.                 mplew.write(0);
  3972.                 mplew.writeInt(buddy.getChannel() - 1);
  3973.                 mplew.writeAsciiString(StringUtil.getRightPaddedStr(buddy.getGroup(), '\0', 17));
  3974.             }
  3975.         }
  3976.         for (int x = 0; x < buddylist.size(); x++) {
  3977.             mplew.writeInt(0);
  3978.         }
  3979.         return mplew.getPacket();
  3980.  
  3981.     }
  3982.  
  3983.     public static MaplePacket requestBuddylistAdd(int cidFrom, String nameFrom) {
  3984.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  3985.  
  3986.         mplew.writeShort(SendPacketOpcode.BUDDYLIST.getValue());
  3987.         mplew.write(9);
  3988.         mplew.writeInt(cidFrom);
  3989.         mplew.writeMapleAsciiString(nameFrom);
  3990.         mplew.writeInt(cidFrom);
  3991.         mplew.writeAsciiString(StringUtil.getRightPaddedStr(nameFrom, '\0', 13));
  3992.         mplew.write(1);
  3993.         mplew.write(31);
  3994.         mplew.writeShort(0);
  3995.         mplew.write(0);
  3996.         mplew.writeAsciiString(StringUtil.getRightPaddedStr("Default Group", '\0', 17));
  3997.         mplew.write(0);
  3998.  
  3999.         return mplew.getPacket();
  4000.     }
  4001.  
  4002.     public static MaplePacket updateBuddyChannel(int characterid, int channel) {
  4003.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4004.  
  4005.         mplew.writeShort(SendPacketOpcode.BUDDYLIST.getValue());
  4006.         // 2B 00 14 30 C0 23 00 00 11 00 00 00
  4007.         mplew.write(0x14);
  4008.         mplew.writeInt(characterid);
  4009.         mplew.write(0);
  4010.         mplew.writeInt(channel);
  4011.  
  4012.         // 2B 00 14 30 C0 23 00 00 0D 00 00 00
  4013.         // 2B 00 14 30 75 00 00 00 11 00 00 00
  4014.         return mplew.getPacket();
  4015.     }
  4016.  
  4017.     public static MaplePacket itemEffect(int characterid, int itemid) {
  4018.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4019.  
  4020.         mplew.writeShort(SendPacketOpcode.SHOW_ITEM_EFFECT.getValue());
  4021.  
  4022.         mplew.writeInt(characterid);
  4023.         mplew.writeInt(itemid);
  4024.  
  4025.         return mplew.getPacket();
  4026.     }
  4027.  
  4028.     public static MaplePacket updateBuddyCapacity(int capacity) {
  4029.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4030.  
  4031.         mplew.writeShort(SendPacketOpcode.BUDDYLIST.getValue());
  4032.         mplew.write(0x15);
  4033.         mplew.write(capacity);
  4034.  
  4035.         return mplew.getPacket();
  4036.     }
  4037.  
  4038.     public static MaplePacket showChair(int characterid, int itemid) {
  4039.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4040.  
  4041.         mplew.writeShort(SendPacketOpcode.SHOW_CHAIR.getValue());
  4042.  
  4043.         mplew.writeInt(characterid);
  4044.         mplew.writeInt(itemid);
  4045.  
  4046.         return mplew.getPacket();
  4047.     }
  4048.  
  4049.     public static MaplePacket cancelChair() {
  4050.         return cancelChair(-1);
  4051.     }
  4052.  
  4053.     public static MaplePacket cancelChair(int id) {
  4054.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4055.  
  4056.         mplew.writeShort(SendPacketOpcode.CANCEL_CHAIR.getValue());
  4057.  
  4058.         if (id == -1) {
  4059.             mplew.write(0);
  4060.         } else {
  4061.             mplew.write(1);
  4062.             mplew.writeShort(id);
  4063.         }
  4064.  
  4065.         return mplew.getPacket();
  4066.     }
  4067.  
  4068.     // is there a way to spawn reactors non-animated?
  4069.     public static MaplePacket spawnReactor(MapleReactor reactor) {
  4070.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4071.         Point pos = reactor.getPosition();
  4072.  
  4073.         mplew.writeShort(SendPacketOpcode.REACTOR_SPAWN.getValue());
  4074.         mplew.writeInt(reactor.getObjectId());
  4075.         mplew.writeInt(reactor.getId());
  4076.         mplew.write(reactor.getState());
  4077.         mplew.writeShort(pos.x);
  4078.         mplew.writeShort(pos.y);
  4079.         mplew.write(0);
  4080.  
  4081.         return mplew.getPacket();
  4082.     }
  4083.  
  4084.     public static MaplePacket triggerReactor(MapleReactor reactor, int stance) {
  4085.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4086.         Point pos = reactor.getPosition();
  4087.  
  4088.         mplew.writeShort(SendPacketOpcode.REACTOR_HIT.getValue());
  4089.         mplew.writeInt(reactor.getObjectId());
  4090.         mplew.write(reactor.getState());
  4091.         mplew.writeShort(pos.x);
  4092.         mplew.writeShort(pos.y);
  4093.         mplew.writeShort(stance);
  4094.         mplew.write(0);
  4095.  
  4096.         //frame delay, set to 5 since there doesn't appear to be a fixed formula for it
  4097.         mplew.write(5);
  4098.  
  4099.         return mplew.getPacket();
  4100.     }
  4101.  
  4102.     public static MaplePacket destroyReactor(MapleReactor reactor) {
  4103.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4104.         Point pos = reactor.getPosition();
  4105.  
  4106.         mplew.writeShort(SendPacketOpcode.REACTOR_DESTROY.getValue());
  4107.         mplew.writeInt(reactor.getObjectId());
  4108.         mplew.write(reactor.getState());
  4109.         mplew.writeShort(pos.x);
  4110.         mplew.writeShort(pos.y);
  4111.  
  4112.         return mplew.getPacket();
  4113.     }
  4114.  
  4115.     public static MaplePacket musicChange(String song) {
  4116.         return environmentChange(song, 6);
  4117.     }
  4118.  
  4119.     public static MaplePacket showEffect(String effect) {
  4120.         return environmentChange(effect, 3);
  4121.     }
  4122.  
  4123.     public static MaplePacket playSound(String sound) {
  4124.         return environmentChange(sound, 4);
  4125.     }
  4126.  
  4127.     public static MaplePacket environmentChange(String env, int mode) {
  4128.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4129.  
  4130.         mplew.writeShort(SendPacketOpcode.BOSS_ENV.getValue());
  4131.         mplew.write(mode);
  4132.         mplew.writeMapleAsciiString(env);
  4133.  
  4134.         return mplew.getPacket();
  4135.     }
  4136.  
  4137.     public static MaplePacket startMapEffect(String msg, int itemid, boolean active) {
  4138.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4139.  
  4140.         mplew.writeShort(SendPacketOpcode.MAP_EFFECT.getValue());
  4141.         mplew.write(active ? 0 : 1);
  4142.  
  4143.         mplew.writeInt(itemid);
  4144.         if (active) {
  4145.             mplew.writeMapleAsciiString(msg);
  4146.         }
  4147.         return mplew.getPacket();
  4148.     }
  4149.  
  4150.     public static MaplePacket removeMapEffect() {
  4151.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4152.  
  4153.         mplew.writeShort(SendPacketOpcode.MAP_EFFECT.getValue());
  4154.         mplew.write(0);
  4155.         mplew.writeInt(0);
  4156.  
  4157.         return mplew.getPacket();
  4158.     }
  4159.  
  4160.     public static MaplePacket showGuildInfo(MapleCharacter c) {
  4161.         //whatever functions calling this better make sure
  4162.         //that the character actually HAS a guild
  4163.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4164.  
  4165.         mplew.writeShort(SendPacketOpcode.GUILD_OPERATION.getValue());
  4166.         mplew.write(0x1A); //signature for showing guild info
  4167.  
  4168.         if (c == null) //show empty guild (used for leaving, expelled)
  4169.         {
  4170.             mplew.write(0);
  4171.             return mplew.getPacket();
  4172.         }
  4173.  
  4174.         MapleGuildCharacter initiator = c.getMGC();
  4175.  
  4176.         MapleGuild g = c.getClient().getChannelServer().getGuild(initiator);
  4177.  
  4178.         if (g == null) //failed to read from DB - don't show a guild
  4179.         {
  4180.             mplew.write(0);
  4181.             log.warn(MapleClient.getLogMessage(c, "Couldn't load a guild"));
  4182.             return mplew.getPacket();
  4183.         } else {
  4184.             //MapleGuild holds the absolute correct value of guild rank
  4185.             //after it is initiated
  4186.             MapleGuildCharacter mgc = g.getMGC(c.getId());
  4187.             c.setGuildRank(mgc.getGuildRank());
  4188.         }
  4189.  
  4190.         mplew.write(1); //bInGuild
  4191.  
  4192.         mplew.writeInt(c.getGuildId()); //not entirely sure about this one
  4193.  
  4194.         mplew.writeMapleAsciiString(g.getName());
  4195.  
  4196.         for (int i = 1; i <= 5; i++) {
  4197.             mplew.writeMapleAsciiString(g.getRankTitle(i));
  4198.         }
  4199.         Collection<MapleGuildCharacter> members = g.getMembers();
  4200.  
  4201.         mplew.write(members.size());
  4202.         //then it is the size of all the members
  4203.  
  4204.         for (MapleGuildCharacter mgc : members) //and each of their character ids o_O
  4205.         {
  4206.             mplew.writeInt(mgc.getId());
  4207.         }
  4208.         for (MapleGuildCharacter mgc : members) {
  4209.             mplew.writeAsciiString(StringUtil.getRightPaddedStr(mgc.getName(), '\0', 13));
  4210.             mplew.writeInt(mgc.getJobId());
  4211.             mplew.writeInt(mgc.getLevel());
  4212.             mplew.writeInt(mgc.getGuildRank());
  4213.             mplew.writeInt(mgc.isOnline() ? 1 : 0);
  4214.             mplew.writeInt(g.getSignature());
  4215.             mplew.writeInt(3);
  4216.         }
  4217.  
  4218.         mplew.writeInt(g.getCapacity());
  4219.         mplew.writeShort(g.getLogoBG());
  4220.         mplew.write(g.getLogoBGColor());
  4221.         mplew.writeShort(g.getLogo());
  4222.         mplew.write(g.getLogoColor());
  4223.         mplew.writeMapleAsciiString(g.getNotice());
  4224.         mplew.writeInt(g.getGP());
  4225.         mplew.writeInt(0);
  4226.  
  4227.         //System.out.println("DEBUG: showGuildInfo packet:\n" + mplew.toString());
  4228.  
  4229.         return mplew.getPacket();
  4230.     }
  4231.  
  4232.     public static MaplePacket guildMemberOnline(int gid, int cid, boolean bOnline) {
  4233.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4234.  
  4235.         mplew.writeShort(SendPacketOpcode.GUILD_OPERATION.getValue());
  4236.         mplew.write(0x3d);
  4237.         mplew.writeInt(gid);
  4238.         mplew.writeInt(cid);
  4239.         mplew.write(bOnline ? 1 : 0);
  4240.  
  4241.         return mplew.getPacket();
  4242.     }
  4243.  
  4244.     public static MaplePacket guildInvite(int gid, String charName) {
  4245.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4246.  
  4247.         mplew.writeShort(SendPacketOpcode.GUILD_OPERATION.getValue());
  4248.         mplew.write(0x05);
  4249.         mplew.writeInt(gid);
  4250.         mplew.writeMapleAsciiString(charName);
  4251.  
  4252.         return mplew.getPacket();
  4253.     }
  4254.  
  4255.     public static MaplePacket genericGuildMessage(byte code) {
  4256.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4257.  
  4258.         mplew.writeShort(SendPacketOpcode.GUILD_OPERATION.getValue());
  4259.         mplew.write(code);
  4260.  
  4261.         return mplew.getPacket();
  4262.     }
  4263.  
  4264.     public static MaplePacket newGuildMember(MapleGuildCharacter mgc) {
  4265.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4266.  
  4267.         mplew.writeShort(SendPacketOpcode.GUILD_OPERATION.getValue());
  4268.         mplew.write(0x27);
  4269.  
  4270.         mplew.writeInt(mgc.getGuildId());
  4271.         mplew.writeInt(mgc.getId());
  4272.         mplew.writeAsciiString(StringUtil.getRightPaddedStr(mgc.getName(), '\0', 13));
  4273.         mplew.writeInt(mgc.getJobId());
  4274.         mplew.writeInt(mgc.getLevel());
  4275.         mplew.writeInt(mgc.getGuildRank()); //should be always 5 but whatevs
  4276.  
  4277.         mplew.writeInt(mgc.isOnline() ? 1 : 0); //should always be 1 too
  4278.  
  4279.         mplew.writeInt(1); //? could be guild signature, but doesn't seem to matter
  4280.  
  4281.         mplew.writeInt(3);
  4282.  
  4283.         return mplew.getPacket();
  4284.     }
  4285.  
  4286.     //someone leaving, mode == 0x2c for leaving, 0x2f for expelled
  4287.     public static MaplePacket memberLeft(MapleGuildCharacter mgc, boolean bExpelled) {
  4288.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4289.  
  4290.         mplew.writeShort(SendPacketOpcode.GUILD_OPERATION.getValue());
  4291.         mplew.write(bExpelled ? 0x2f : 0x2c);
  4292.  
  4293.         mplew.writeInt(mgc.getGuildId());
  4294.         mplew.writeInt(mgc.getId());
  4295.         mplew.writeMapleAsciiString(mgc.getName());
  4296.  
  4297.         return mplew.getPacket();
  4298.     }
  4299.  
  4300.     //rank change
  4301.     public static MaplePacket changeRank(MapleGuildCharacter mgc) {
  4302.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4303.  
  4304.         mplew.writeShort(SendPacketOpcode.GUILD_OPERATION.getValue());
  4305.         mplew.write(0x40);
  4306.         mplew.writeInt(mgc.getGuildId());
  4307.         mplew.writeInt(mgc.getId());
  4308.         mplew.write(mgc.getGuildRank());
  4309.  
  4310.         return mplew.getPacket();
  4311.     }
  4312.  
  4313.     public static MaplePacket guildNotice(int gid, String notice) {
  4314.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4315.  
  4316.         mplew.writeShort(SendPacketOpcode.GUILD_OPERATION.getValue());
  4317.         mplew.write(0x44);
  4318.  
  4319.         mplew.writeInt(gid);
  4320.         mplew.writeMapleAsciiString(notice);
  4321.  
  4322.         return mplew.getPacket();
  4323.     }
  4324.  
  4325.     public static MaplePacket guildMemberLevelJobUpdate(MapleGuildCharacter mgc) {
  4326.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4327.  
  4328.         mplew.writeShort(SendPacketOpcode.GUILD_OPERATION.getValue());
  4329.         mplew.write(0x3C);
  4330.  
  4331.         mplew.writeInt(mgc.getGuildId());
  4332.         mplew.writeInt(mgc.getId());
  4333.         mplew.writeInt(mgc.getLevel());
  4334.         mplew.writeInt(mgc.getJobId());
  4335.  
  4336.         return mplew.getPacket();
  4337.     }
  4338.  
  4339.     public static MaplePacket rankTitleChange(int gid, String[] ranks) {
  4340.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4341.  
  4342.         mplew.writeShort(SendPacketOpcode.GUILD_OPERATION.getValue());
  4343.         mplew.write(0x3e);
  4344.         mplew.writeInt(gid);
  4345.  
  4346.         for (int i = 0; i < 5; i++) {
  4347.             mplew.writeMapleAsciiString(ranks[i]);
  4348.         }
  4349.         return mplew.getPacket();
  4350.     }
  4351.  
  4352.     public static MaplePacket guildDisband(int gid) {
  4353.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4354.  
  4355.         mplew.writeShort(SendPacketOpcode.GUILD_OPERATION.getValue());
  4356.         mplew.write(0x32);
  4357.         mplew.writeInt(gid);
  4358.         mplew.write(1);
  4359.  
  4360.         return mplew.getPacket();
  4361.     }
  4362.  
  4363.     public static MaplePacket guildEmblemChange(int gid, short bg, byte bgcolor, short logo, byte logocolor) {
  4364.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4365.  
  4366.         mplew.writeShort(SendPacketOpcode.GUILD_OPERATION.getValue());
  4367.         mplew.write(0x42);
  4368.         mplew.writeInt(gid);
  4369.         mplew.writeShort(bg);
  4370.         mplew.write(bgcolor);
  4371.         mplew.writeShort(logo);
  4372.         mplew.write(logocolor);
  4373.  
  4374.         return mplew.getPacket();
  4375.     }
  4376.  
  4377.     public static MaplePacket guildCapacityChange(int gid, int capacity) {
  4378.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4379.  
  4380.         mplew.writeShort(SendPacketOpcode.GUILD_OPERATION.getValue());
  4381.         mplew.write(0x3a);
  4382.         mplew.writeInt(gid);
  4383.         mplew.write(capacity);
  4384.  
  4385.         return mplew.getPacket();
  4386.     }
  4387.  
  4388.     public static void addThread(MaplePacketLittleEndianWriter mplew, ResultSet rs) throws SQLException {
  4389.         mplew.writeInt(rs.getInt("localthreadid"));
  4390.         mplew.writeInt(rs.getInt("postercid"));
  4391.         mplew.writeMapleAsciiString(rs.getString("name"));
  4392.         mplew.writeLong(MaplePacketCreator.getKoreanTimestamp(rs.getLong("timestamp")));
  4393.         mplew.writeInt(rs.getInt("icon"));
  4394.         mplew.writeInt(rs.getInt("replycount"));
  4395.     }
  4396.  
  4397.     public static MaplePacket BBSThreadList(ResultSet rs, int start) throws SQLException {
  4398.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4399.  
  4400.         mplew.writeShort(SendPacketOpcode.BBS_OPERATION.getValue());
  4401.         mplew.write(0x06);
  4402.  
  4403.         if (!rs.last()) //no result at all
  4404.         {
  4405.             mplew.write(0);
  4406.             mplew.writeInt(0);
  4407.             mplew.writeInt(0);
  4408.             return mplew.getPacket();
  4409.         }
  4410.  
  4411.         int threadCount = rs.getRow();
  4412.         if (rs.getInt("localthreadid") == 0) //has a notice
  4413.         {
  4414.             mplew.write(1);
  4415.             addThread(mplew, rs);
  4416.             threadCount--; //one thread didn't count (because it's a notice)
  4417.  
  4418.         } else {
  4419.             mplew.write(0);
  4420.         }
  4421.         if (!rs.absolute(start + 1)) //seek to the thread before where we start
  4422.         {
  4423.             rs.first(); //uh, we're trying to start at a place past possible
  4424.  
  4425.             start = 0;
  4426.             // System.out.println("Attempting to start past threadCount");
  4427.         }
  4428.  
  4429.         mplew.writeInt(threadCount);
  4430.         mplew.writeInt(Math.min(10, threadCount - start));
  4431.  
  4432.         for (int i = 0; i < Math.min(10, threadCount - start); i++) {
  4433.             addThread(mplew, rs);
  4434.             rs.next();
  4435.         }
  4436.  
  4437.         return mplew.getPacket();
  4438.     }
  4439.  
  4440.     public static MaplePacket showThread(int localthreadid, ResultSet threadRS, ResultSet repliesRS)
  4441.             throws SQLException,
  4442.             RuntimeException {
  4443.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4444.  
  4445.         mplew.writeShort(SendPacketOpcode.BBS_OPERATION.getValue());
  4446.         mplew.write(0x07);
  4447.  
  4448.         mplew.writeInt(localthreadid);
  4449.         mplew.writeInt(threadRS.getInt("postercid"));
  4450.         mplew.writeLong(getKoreanTimestamp(threadRS.getLong("timestamp")));
  4451.         mplew.writeMapleAsciiString(threadRS.getString("name"));
  4452.         mplew.writeMapleAsciiString(threadRS.getString("startpost"));
  4453.         mplew.writeInt(threadRS.getInt("icon"));
  4454.  
  4455.         if (repliesRS != null) {
  4456.             int replyCount = threadRS.getInt("replycount");
  4457.             mplew.writeInt(replyCount);
  4458.  
  4459.             int i;
  4460.             for (i = 0; i < replyCount && repliesRS.next(); i++) {
  4461.                 mplew.writeInt(repliesRS.getInt("replyid"));
  4462.                 mplew.writeInt(repliesRS.getInt("postercid"));
  4463.                 mplew.writeLong(getKoreanTimestamp(repliesRS.getLong("timestamp")));
  4464.                 mplew.writeMapleAsciiString(repliesRS.getString("content"));
  4465.             }
  4466.  
  4467.             if (i != replyCount || repliesRS.next()) {
  4468.                 //in the unlikely event that we lost count of replyid
  4469.                 throw new RuntimeException(String.valueOf(threadRS.getInt("threadid")));
  4470.                 //we need to fix the database and stop the packet sending
  4471.                 //or else it'll probably error 38 whoever tries to read it
  4472.  
  4473.                 //there is ONE case not checked, and that's when the thread
  4474.                 //has a replycount of 0 and there is one or more replies to the
  4475.                 //thread in bbs_replies
  4476.             }
  4477.         } else {
  4478.             mplew.writeInt(0); //0 replies
  4479.  
  4480.         }
  4481.         return mplew.getPacket();
  4482.     }
  4483.  
  4484.     public static MaplePacket showGuildRanks(int npcid, ResultSet rs) throws SQLException {
  4485.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4486.  
  4487.         mplew.writeShort(SendPacketOpcode.GUILD_OPERATION.getValue());
  4488.         mplew.write(0x49);
  4489.         mplew.writeInt(npcid);
  4490.         if (!rs.last()) //no guilds o.o
  4491.         {
  4492.             mplew.writeInt(0);
  4493.             return mplew.getPacket();
  4494.         }
  4495.  
  4496.         mplew.writeInt(rs.getRow());        //number of entries
  4497.  
  4498.         rs.beforeFirst();
  4499.         while (rs.next()) {
  4500.             mplew.writeMapleAsciiString(rs.getString("name"));
  4501.             mplew.writeInt(rs.getInt("GP"));
  4502.             mplew.writeInt(rs.getInt("logo"));
  4503.             mplew.writeInt(rs.getInt("logoColor"));
  4504.             mplew.writeInt(rs.getInt("logoBG"));
  4505.             mplew.writeInt(rs.getInt("logoBGColor"));
  4506.         }
  4507.  
  4508.         return mplew.getPacket();
  4509.     }
  4510.  
  4511.     public static MaplePacket updateGP(int gid, int GP) {
  4512.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4513.  
  4514.         mplew.writeShort(SendPacketOpcode.GUILD_OPERATION.getValue());
  4515.         mplew.write(0x48);
  4516.         mplew.writeInt(gid);
  4517.         mplew.writeInt(GP);
  4518.  
  4519.         return mplew.getPacket();
  4520.     }
  4521.  
  4522.     public static MaplePacket skillEffect(MapleCharacter from, int skillId, byte flags) {
  4523.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4524.         mplew.writeShort(SendPacketOpcode.SKILL_EFFECT.getValue());
  4525.         mplew.writeInt(from.getId());
  4526.         mplew.writeInt(skillId);
  4527.         mplew.write(0x01); // unknown at this point
  4528.  
  4529.         mplew.write(flags);
  4530.         mplew.write(0x04); // unknown at this point
  4531.  
  4532.         return mplew.getPacket();
  4533.     }
  4534.  
  4535.     public static MaplePacket skillCancel(MapleCharacter from, int skillId) {
  4536.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4537.         mplew.writeShort(SendPacketOpcode.CANCEL_SKILL_EFFECT.getValue());
  4538.         mplew.writeInt(from.getId());
  4539.         mplew.writeInt(skillId);
  4540.         return mplew.getPacket();
  4541.     }
  4542.  
  4543.     public static MaplePacket showMagnet(int mobid, byte success) {  // Monster Magnet
  4544.  
  4545.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4546.         mplew.writeShort(SendPacketOpcode.SHOW_MAGNET.getValue());
  4547.         mplew.writeInt(mobid);
  4548.         mplew.write(success);
  4549.         return mplew.getPacket();
  4550.     }
  4551.  
  4552.     /**
  4553.      * Sends a Player Hint, something that pops up above your character!
  4554.      *
  4555.      * @return The packet.
  4556.      */
  4557.     public static MaplePacket sendHint(String hint) {
  4558.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(16);
  4559.         mplew.writeShort(SendPacketOpcode.PLAYER_HINT.getValue());
  4560.         mplew.writeMapleAsciiString(hint);
  4561.         mplew.write(HexTool.getByteArrayFromHexString("FA 00 05 00 01"));
  4562.  
  4563.         return mplew.getPacket();
  4564.     }
  4565.  
  4566.     public static MaplePacket messengerInvite(String from, int messengerid) {
  4567.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4568.         mplew.writeShort(SendPacketOpcode.MESSENGER.getValue());
  4569.         mplew.write(0x03);
  4570.         mplew.writeMapleAsciiString(from);
  4571.         mplew.write(0x00);
  4572.         mplew.writeInt(messengerid);
  4573.         mplew.write(0x00);
  4574.         return mplew.getPacket();
  4575.     }
  4576.  
  4577.     public static MaplePacket addMessengerPlayer(String from, MapleCharacter chr, int position, int channel) {
  4578.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4579.         mplew.writeShort(SendPacketOpcode.MESSENGER.getValue());
  4580.         mplew.write(0x00);
  4581.         mplew.write(position);
  4582.         addCharLook(mplew, chr, true);
  4583.         mplew.writeMapleAsciiString(from);
  4584.         mplew.write(channel);
  4585.         mplew.write(0x00);
  4586.         return mplew.getPacket();
  4587.     }
  4588.  
  4589.     public static MaplePacket removeMessengerPlayer(int position) {
  4590.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4591.         mplew.writeShort(SendPacketOpcode.MESSENGER.getValue());
  4592.         mplew.write(0x02);
  4593.         mplew.write(position);
  4594.         return mplew.getPacket();
  4595.     }
  4596.  
  4597.     public static MaplePacket updateMessengerPlayer(String from, MapleCharacter chr, int position, int channel) {
  4598.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4599.         mplew.writeShort(SendPacketOpcode.MESSENGER.getValue());
  4600.         mplew.write(0x07);
  4601.         mplew.write(position);
  4602.         addCharLook(mplew, chr, true);
  4603.         mplew.writeMapleAsciiString(from);
  4604.         mplew.write(channel);
  4605.         mplew.write(0x00);
  4606.         return mplew.getPacket();
  4607.     }
  4608.  
  4609.     public static MaplePacket joinMessenger(int position) {
  4610.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4611.         mplew.writeShort(SendPacketOpcode.MESSENGER.getValue());
  4612.         mplew.write(0x01);
  4613.         mplew.write(position);
  4614.         return mplew.getPacket();
  4615.     }
  4616.  
  4617.     public static MaplePacket messengerChat(String text) {
  4618.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4619.         mplew.writeShort(SendPacketOpcode.MESSENGER.getValue());
  4620.         mplew.write(0x06);
  4621.         mplew.writeMapleAsciiString(text);
  4622.         return mplew.getPacket();
  4623.     }
  4624.  
  4625.     public static MaplePacket messengerNote(String text, int mode, int mode2) {
  4626.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4627.         mplew.writeShort(SendPacketOpcode.MESSENGER.getValue());
  4628.         mplew.write(mode);
  4629.         mplew.writeMapleAsciiString(text);
  4630.         mplew.write(mode2);
  4631.         return mplew.getPacket();
  4632.     }
  4633.  
  4634.         public static MaplePacket warpCS(MapleClient c) {
  4635.  
  4636.                 MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4637.  
  4638.                 MapleCharacter chr = c.getPlayer();
  4639.  
  4640.                 mplew.writeShort(SendPacketOpcode.CS_OPEN.getValue());
  4641.                 mplew.writeLong(-1);
  4642.  
  4643.                 addCharStats(mplew, chr);
  4644.  
  4645.                 mplew.write(20); // ???
  4646.  
  4647.                 mplew.writeInt(chr.getMeso()); // mesos
  4648.  
  4649.                 mplew.write(100); // Equip slots
  4650.                 mplew.write(100); // Use slots
  4651.                 mplew.write(100); // Setup slots
  4652.                 mplew.write(100); // Etc slots
  4653.                 mplew.write(100); // Storage slots
  4654.  
  4655.                 MapleInventory iv = chr.getInventory(MapleInventoryType.EQUIPPED);
  4656.                 Collection<IItem> equippedC = iv.list();
  4657.                 List<Item> equipped = new ArrayList<Item>(equippedC.size());
  4658.                 for (IItem item : equippedC) {
  4659.                     equipped.add((Item) item);
  4660.                 }
  4661.                 Collections.sort(equipped);
  4662.  
  4663.                 for (Item item : equipped) {
  4664.                     addItemInfo(mplew, item);
  4665.                 }
  4666.                 mplew.writeShort(0); // start of equip inventory
  4667.  
  4668.                 iv = chr.getInventory(MapleInventoryType.EQUIP);
  4669.                 for (IItem item : iv.list()) {
  4670.                     addItemInfo(mplew, item);
  4671.                 }
  4672.                 mplew.write(0); // start of use inventory
  4673.  
  4674.                 iv = chr.getInventory(MapleInventoryType.USE);
  4675.                 for (IItem item : iv.list()) {
  4676.                     addItemInfo(mplew, item);
  4677.                 }
  4678.                 mplew.write(0); // start of set-up inventory
  4679.  
  4680.                 iv = chr.getInventory(MapleInventoryType.SETUP);
  4681.                 for (IItem item : iv.list()) {
  4682.                     addItemInfo(mplew, item);
  4683.                 }
  4684.                 mplew.write(0); // start of etc inventory
  4685.  
  4686.                 iv = chr.getInventory(MapleInventoryType.ETC);
  4687.                 for (IItem item : iv.list()) {
  4688.                     addItemInfo(mplew, item);
  4689.                 }
  4690.                 mplew.write(0); // start of cash inventory
  4691.  
  4692.                 iv = chr.getInventory(MapleInventoryType.CASH);
  4693.                 for (IItem item : iv.list()) {
  4694.                     addItemInfo(mplew, item);
  4695.                 }
  4696.  
  4697.                 mplew.write(0);
  4698.  
  4699.                 Map<ISkill, MapleCharacter.SkillEntry> skills = chr.getSkills();
  4700.                 mplew.writeShort(skills.size());
  4701.                 for (Entry<ISkill, MapleCharacter.SkillEntry> skill : skills.entrySet()) {
  4702.                     mplew.writeInt(skill.getKey().getId());
  4703.                     mplew.writeInt(skill.getValue().skillevel);
  4704.                     if (skill.getKey().isFourthJob()) {
  4705.                         mplew.writeInt(skill.getValue().masterlevel);
  4706.                     }
  4707.                 }
  4708.  
  4709.                 mplew.writeShort(0);
  4710.  
  4711.                 mplew.writeShort(1);
  4712.                 mplew.writeInt(662990);
  4713.                 mplew.write(HexTool.getByteArrayFromHexString("5A 42 43 44 45 46 47 48 49 4A 00 00"));
  4714.                 mplew.writeLong(0);
  4715.                 for (int i = 0; i < 15; i++) {
  4716.                     mplew.write(CHAR_INFO_MAGIC);
  4717.                 }
  4718.  
  4719.                 mplew.writeInt(0);
  4720.                 mplew.writeInt(0);//v72
  4721.                 mplew.writeInt(0);//v72
  4722.                 mplew.write(0);
  4723.                 mplew.write(1);
  4724.  
  4725.                 mplew.writeMapleAsciiString(chr.getClient().getAccountName());
  4726.                 mplew.write(HexTool.getByteArrayFromHexString("00 00 00 00 38 00 01 9F 98 00 00 04 00 00 00 02 9F 98 00 00 04 00 00 00 03 9F 98 00 00 04 00 00 00 04 9F 98 00 00 04 00 00 00 05 9F 98 00 00 04 00 00 00 06 9F 98 00 00 04 00 00 00 07 9F 98 00 00 04 00 00 00 08 9F 98 00 00 04 00 00 00 09 9F 98 00 00 04 00 00 00 0A 9F 98 00 00 04 00 00 00 0B 9F 98 00 00 04 00 00 00 0C 9F 98 00 00 04 00 00 00 0D 9F 98 00 00 04 00 00 00 0E 9F 98 00 00 04 00 00 00 0F 9F 98 00 00 04 00 00 00 6F 24 9A 00 00 04 00 00 00 70 24 9A 00 00 04 00 00 00 71 24 9A 00 00 04 00 00 00 72 24 9A 00 00 04 00 00 00 73 24 9A 00 00 08 00 00 FF 74 24 9A 00 00 08 00 00 FF 78 24 9A 00 00 04 00 00 00 79 24 9A 00 00 04 00 00 00 53 2F 31 01 10 00 00 00 0D 54 2F 31 01 00 04 00 00 00 9B 3A 34 01 00 04 00 00 00 9C 3A 34 01 00 04 00 00 00 11 C2 35 01 14 08 00 00 0C 92 09 00 00 01 42 C2 35 01 10 00 00 00 0B 44 C2 35 01 00 04 00 00 00 45 C2 35 01 00 0C 00 00 00 03 46 C2 35 01 00 0C 00 00 00 03 69 48 37 01 14 08 00 00 0C 92 09 00 00 01 8A 48 37 01 00 04 00 00 00 D3 CE 38 01 14 08 00 00 0C 04 06 00 00 01 07 CF 38 01 00 04 00 00 00 AD 55 3A 01 00 04 00 00 00 AE 55 3A 01 00 04 00 00 00 AF 55 3A 01 00 04 00 00 00 98 62 3D 01 06 08 00 00 0C 00 4E 0C 00 00 01 1B 63 3D 01 10 08 00 00 0B 02 1E 63 3D 01 00 04 00 00 00 1F 63 3D 01 00 04 00 00 00 20 63 3D 01 00 04 00 00 00 FF F5 41 01 14 08 00 00 0C 92 09 00 00 01 3A F6 41 01 00 04 00 00 00 3B F6 41 01 00 0C 00 00 00 03 AE C3 C9 01 00 04 00 00 00 47 77 FC 02 00 08 00 00 FF 48 77 FC 02 00 08 00 00 FF 3C FE FD 02 00 0C 00 00 00 FF 40 FE FD 02 00 04 00 00 00 E7 91 02 03 00 0C 00 00 00 03 4E 87 93 03 00 04 00 00 01 DB 1E 2C 04 00 04 00 00 00 DC 1E 2C 04 00 04 00 00 00 00 68 00 65 00 20 00 6D 00 6F 00 6E 00 73 00 74 00 65 00 72 00 20 00 62 00 65 00 63 00 6F 00 6D 00 65 00 73 00 20 00 70 00 61 00 6E 00 69 00 63 00 6B 00 65 00 64 00 2E 00 20 00 54 00 68 00 69 00 73 00 20 00 73 00 6B 00 69 00 6C 00 6C 00 20 00 63 00 61 00 6E 00 20 00 6F 00 6E 00 6C 00 79 00 20 00 62 00 65 00 20 00 75 00 73 00 65 00 64 00 20 00 77 00 68 00 65 00 01 00 00 00 00 00 00 00 E6 91 02 03 01 00 00 00 00 00 00 00 FB E8 3E 01 01 00 00 00 00 00 00 00 4F 2F 31 01 01 00 00 00 00 00 00 00 75 24 9A 00 01 00 00 00 00 00 00 00 76 24 9A 00 01 00 00 00 01 00 00 00 E6 91 02 03 01 00 00 00 01 00 00 00 FB E8 3E 01 01 00 00 00 01 00 00 00 4F 2F 31 01 01 00 00 00 01 00 00 00 75 24 9A 00 01 00 00 00 01 00 00 00 76 24 9A 00 02 00 00 00 00 00 00 00 E6 91 02 03 02 00 00 00 00 00 00 00 FB E8 3E 01 02 00 00 00 00 00 00 00 4F 2F 31 01 02 00 00 00 00 00 00 00 75 24 9A 00 02 00 00 00 00 00 00 00 76 24 9A 00 02 00 00 00 01 00 00 00 E6 91 02 03 02 00 00 00 01 00 00 00 FB E8 3E 01 02 00 00 00 01 00 00 00 4F 2F 31 01 02 00 00 00 01 00 00 00 75 24 9A 00 02 00 00 00 01 00 00 00 76 24 9A 00 03 00 00 00 00 00 00 00 E6 91 02 03 03 00 00 00 00 00 00 00 FB E8 3E 01 03 00 00 00 00 00 00 00 4F 2F 31 01 03 00 00 00 00 00 00 00 75 24 9A 00 03 00 00 00 00 00 00 00 76 24 9A 00 03 00 00 00 01 00 00 00 E6 91 02 03 03 00 00 00 01 00 00 00 FB E8 3E 01 03 00 00 00 01 00 00 00 4F 2F 31 01 03 00 00 00 01 00 00 00 75 24 9A 00 03 00 00 00 01 00 00 00 76 24 9A 00 04 00 00 00 00 00 00 00 E6 91 02 03 04 00 00 00 00 00 00 00 FB E8 3E 01 04 00 00 00 00 00 00 00 4F 2F 31 01 04 00 00 00 00 00 00 00 75 24 9A 00 04 00 00 00 00 00 00 00 76 24 9A 00 04 00 00 00 01 00 00 00 E6 91 02 03 04 00 00 00 01 00 00 00 FB E8 3E 01 04 00 00 00 01 00 00 00 4F 2F 31 01 04 00 00 00 01 00 00 00 75 24 9A 00 04 00 00 00 01 00 00 00 76 24 9A 00 05 00 00 00 00 00 00 00 E6 91 02 03 05 00 00 00 00 00 00 00 FB E8 3E 01 05 00 00 00 00 00 00 00 4F 2F 31 01 05 00 00 00 00 00 00 00 75 24 9A 00 05 00 00 00 00 00 00 00 76 24 9A 00 05 00 00 00 01 00 00 00 E6 91 02 03 05 00 00 00 01 00 00 00 FB E8 3E 01 05 00 00 00 01 00 00 00 4F 2F 31 01 05 00 00 00 01 00 00 00 75 24 9A 00 05 00 00 00 01 00 00 00 76 24 9A 00 06 00 00 00 00 00 00 00 E6 91 02 03 06 00 00 00 00 00 00 00 FB E8 3E 01 06 00 00 00 00 00 00 00 4F 2F 31 01 06 00 00 00 00 00 00 00 75 24 9A 00 06 00 00 00 00 00 00 00 76 24 9A 00 06 00 00 00 01 00 00 00 E6 91 02 03 06 00 00 00 01 00 00 00 FB E8 3E 01 06 00 00 00 01 00 00 00 4F 2F 31 01 06 00 00 00 01 00 00 00 75 24 9A 00 06 00 00 00 01 00 00 00 76 24 9A 00 07 00 00 00 00 00 00 00 E6 91 02 03 07 00 00 00 00 00 00 00 FB E8 3E 01 07 00 00 00 00 00 00 00 4F 2F 31 01 07 00 00 00 00 00 00 00 75 24 9A 00 07 00 00 00 00 00 00 00 76 24 9A 00 07 00 00 00 01 00 00 00 E6 91 02 03 07 00 00 00 01 00 00 00 FB E8 3E 01 07 00 00 00 01 00 00 00 4F 2F 31 01 07 00 00 00 01 00 00 00 75 24 9A 00 07 00 00 00 01 00 00 00 76 24 9A 00 08 00 00 00 00 00 00 00 E6 91 02 03 08 00 00 00 00 00 00 00 FB E8 3E 01 08 00 00 00 00 00 00 00 4F 2F 31 01 08 00 00 00 00 00 00 00 75 24 9A 00 08 00 00 00 00 00 00 00 76 24 9A 00 08 00 00 00 01 00 00 00 E6 91 02 03 08 00 00 00 01 00 00 00 FB E8 3E 01 08 00 00 00 01 00 00 00 4F 2F 31 01 08 00 00 00 01 00 00 00 75 24 9A 00 08 00 00 00 01 00 00 00 76 24 9A 00 00 00 00 00 00 00 00 33 00 00 00"));
  4727.                 return mplew.getPacket();
  4728.             }
  4729.  
  4730.  
  4731.             public static void toCashItem(MaplePacketLittleEndianWriter mplew, int sn, int type1, int type2) {
  4732.                     // E1 9C 98 00 00 06 00 00 00 - Globe Cap
  4733.                     mplew.writeInt(sn);
  4734.                     mplew.write(0);
  4735.                     mplew.write(type1);
  4736.                     mplew.writeShort(0);
  4737.                     mplew.write(type2);
  4738.             }
  4739.  
  4740.             public static void toCashItem(MaplePacketLittleEndianWriter mplew, int sn, int type0, int type1, int type2) {
  4741.                     mplew.writeInt(sn);
  4742.                     mplew.write(type0);
  4743.                     mplew.write(type1);
  4744.                     mplew.writeShort(0);
  4745.                     mplew.write(type2);
  4746.             }
  4747.  
  4748.             public static MaplePacket showNXMapleTokens(MapleCharacter chr) {
  4749.                 MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4750.                 mplew.writeShort(SendPacketOpcode.CS_UPDATE.getValue());
  4751.                 for (int i = 1; i < 5; i *= 2)
  4752.                     mplew.writeInt(chr.getCSPoints(i));
  4753.                 return mplew.getPacket();
  4754.             }
  4755.            
  4756.             public static MaplePacket updateDojoStats(int points, int belt, boolean tut) {
  4757.                 MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4758.  
  4759.                 mplew.writeShort(SendPacketOpcode.SHOW_STATUS_INFO.getValue());
  4760.                 mplew.write(0x0a);
  4761.                 mplew.write(HexTool.getByteArrayFromHexString("B7 04")); //?
  4762.                 mplew.writeMapleAsciiString("pt=" + points + ";belt=" + belt + ";tuto=" + (tut ? "1" : "0"));
  4763.  
  4764.                 return mplew.getPacket();
  4765.             }
  4766.  
  4767.             /**
  4768.             *
  4769.             * @param type - (0:Light&Long 1:Heavy&Short)
  4770.             * @param delay - seconds
  4771.             * @return
  4772.             */
  4773.             public static MaplePacket trembleEffect(int type, int delay) {
  4774.                 MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4775.                 mplew.writeShort(SendPacketOpcode.BOSS_ENV.getValue());
  4776.                 mplew.write(1);
  4777.                 mplew.write(type);
  4778.                 mplew.writeInt(delay);
  4779.                 return mplew.getPacket();
  4780.             }
  4781.  
  4782.             public static MaplePacket getEnergy(int level) {
  4783.                 MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4784.                 mplew.writeShort(SendPacketOpcode.ENERGY.getValue());
  4785.                 mplew.writeMapleAsciiString("energy");
  4786.                 mplew.writeMapleAsciiString(Integer.toString(level));
  4787.                 return mplew.getPacket();
  4788.             }
  4789.  
  4790.             public static MaplePacket Mulung_DojoUp2() {
  4791.                 MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4792.  
  4793.                 mplew.writeShort(SendPacketOpcode.SHOW_ITEM_GAIN_INCHAT.getValue());
  4794.                 mplew.write(7);
  4795.  
  4796.                 return mplew.getPacket();
  4797.             }
  4798.  
  4799.             public static MaplePacket dojoWarpUp() {
  4800.                 MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4801.  
  4802.                 mplew.writeShort(SendPacketOpcode.DOJO_WARP_UP.getValue());
  4803.                 mplew.write(0);
  4804.                 mplew.write(6);
  4805.  
  4806.                 return mplew.getPacket();
  4807.             }
  4808.  
  4809.             public static MaplePacket showBoughtCSItem(MapleClient c, CashItemInfo item) {
  4810.                 MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4811.                 mplew.writeShort(SendPacketOpcode.CS_OPERATION.getValue());
  4812.                 mplew.write(0x4A);
  4813.                 mplew.write(HexTool.getByteArrayFromHexString("FA 96 C1 00"));
  4814.                 mplew.writeInt(0);
  4815.                 mplew.writeInt(c.getAccID());
  4816.                 mplew.writeInt(0);
  4817.                 mplew.writeInt(item.getId());
  4818.                 mplew.write(HexTool.getByteArrayFromHexString("15 2D 31 01"));
  4819.                 mplew.writeShort(item.getCount());
  4820.                 mplew.write(HexTool.getByteArrayFromHexString("00 00 50 4C 40 00 B4 F9 78"));
  4821.                 mplew.writeInt(0);
  4822.                 mplew.write(HexTool.getByteArrayFromHexString("C0 1E CC C5 A4 73 CA 01"));
  4823.                 mplew.writeLong(0);
  4824.                 return mplew.getPacket();
  4825.             }
  4826.  
  4827.             public static MaplePacket showBoughtCSQuestItem(int itemid) {
  4828.                 MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4829.                 mplew.writeShort(SendPacketOpcode.CS_OPERATION.getValue());
  4830.                 mplew.writeInt(382);//7E 01 00 00
  4831.                 mplew.write(0);//00
  4832.                 mplew.writeShort(1);//01 00
  4833.                 mplew.write(19);//19
  4834.                 mplew.write(0);//00
  4835.                 mplew.writeInt(itemid);//D8 82 3D 00
  4836.                 return mplew.getPacket();
  4837.             }
  4838.  
  4839.  
  4840.     public static MaplePacket showCouponRedeemedItem(int itemid) {
  4841.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4842.  
  4843.         mplew.writeShort(SendPacketOpcode.CS_OPERATION.getValue());
  4844.         mplew.writeShort(0x3A);
  4845.         mplew.writeInt(0);
  4846.         mplew.writeInt(1);
  4847.         mplew.writeShort(1);
  4848.         mplew.writeShort(0x1A);
  4849.         mplew.writeInt(itemid);
  4850.         mplew.writeInt(0);
  4851.  
  4852.         return mplew.getPacket();
  4853.     }
  4854.  
  4855.         public static MaplePacket enableCSUse0() {
  4856.             MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4857.             mplew.write(HexTool.getByteArrayFromHexString("12 00 00 00 00 00 00"));
  4858.             return mplew.getPacket();
  4859.         }
  4860.  
  4861.         public static MaplePacket enableCSUse1() {
  4862.             MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4863.             mplew.writeShort(SendPacketOpcode.CS_OPERATION.getValue());
  4864.             mplew.write(0x40); //v75
  4865.             mplew.writeShort(0);
  4866.             return mplew.getPacket();
  4867.         }
  4868.  
  4869.         public static MaplePacket enableCSUse2() {
  4870.             MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4871.             mplew.writeShort(SendPacketOpcode.CS_OPERATION.getValue());
  4872.             mplew.writeShort(0x3e); //v75
  4873.             mplew.write(0);
  4874.             mplew.writeShort(4);
  4875.             mplew.writeShort(3);
  4876.             return mplew.getPacket();
  4877.         }
  4878.  
  4879.         public static MaplePacket enableCSUse3() {
  4880.             MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4881.             mplew.writeShort(SendPacketOpcode.CS_OPERATION.getValue());
  4882.             mplew.write(0x42); //v75
  4883.             mplew.write(new byte[40]);
  4884.             return mplew.getPacket();
  4885.         }
  4886.  
  4887.     // Decoding : Raz (Snow) | Author : Penguins (Acrylic)
  4888.     public static MaplePacket sendWishList(int characterid) {
  4889.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4890.         mplew.writeShort(0xEF);
  4891.         mplew.write(0x30);
  4892.  
  4893.         Connection con = DatabaseConnection.getConnection();
  4894.         int i = 10;
  4895.  
  4896.         try {
  4897.             PreparedStatement ps = con.prepareStatement("SELECT sn FROM wishlist WHERE charid = ? LIMIT 10");
  4898.             ps.setInt(1, characterid);
  4899.             ResultSet rs = ps.executeQuery();
  4900.             while (rs.next()) {
  4901.                 mplew.writeInt(rs.getInt("sn"));
  4902.             }
  4903.             rs.close();
  4904.             ps.close();
  4905.         } catch (SQLException se) {
  4906.             System.out.println("Sql Error with wishlists");
  4907.         }
  4908.  
  4909.         while (i > 0) {
  4910.             mplew.writeInt(0);
  4911.             i--;
  4912.         }
  4913.         return mplew.getPacket();
  4914.     }
  4915.  
  4916.     // Decoding : Raz (Snow) | Author : Penguins (Acrylic)
  4917.     /*public static MaplePacket updateWishList(int characterid) {
  4918.     MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4919.     mplew.writeShort(0xEF);
  4920.     mplew.write(0x36);
  4921.    
  4922.     Connection con = DatabaseConnection.getConnection();
  4923.     int i = 10;
  4924.    
  4925.     try {
  4926.     PreparedStatement ps = con.prepareStatement("SELECT sn FROM wishlist WHERE charid = ? LIMIT 10");
  4927.     ps.setInt(1, characterid);
  4928.     ResultSet rs = ps.executeQuery();
  4929.     while (rs.next()) {
  4930.     mplew.writeInt(rs.getInt("sn"));
  4931.     }
  4932.     rs.close();
  4933.     ps.close();
  4934.     } catch (SQLException se) {
  4935.     }
  4936.    
  4937.     while (i > 0) {
  4938.     mplew.writeInt(0);
  4939.     i--;
  4940.     }
  4941.     return mplew.getPacket();
  4942.     }*/
  4943.     public static MaplePacket wrongCouponCode() {
  4944.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4945.         // FE 00 40 87
  4946.         mplew.writeShort(SendPacketOpcode.CS_OPERATION.getValue());
  4947.         mplew.write(0x40);
  4948.         mplew.write(0x87);
  4949.  
  4950.         return mplew.getPacket();
  4951.     }
  4952.  
  4953.     public static MaplePacket getFindReplyWithCS(String target) {
  4954.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4955.         mplew.writeShort(SendPacketOpcode.WHISPER.getValue());
  4956.         mplew.write(9);
  4957.         mplew.writeMapleAsciiString(target);
  4958.         mplew.write(2);
  4959.         mplew.writeInt(-1);
  4960.         return mplew.getPacket();
  4961.     }
  4962.  
  4963.     public static MaplePacket updatePet(MaplePet pet, boolean alive) {
  4964.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  4965.         mplew.writeShort(SendPacketOpcode.MODIFY_INVENTORY_ITEM.getValue());
  4966.         mplew.write(0);
  4967.         mplew.write(2);
  4968.         mplew.write(3);
  4969.         mplew.write(5);
  4970.         mplew.write(pet.getPosition());
  4971.         mplew.writeShort(0);
  4972.         mplew.write(5);
  4973.         mplew.write(pet.getPosition());
  4974.         mplew.write(0);
  4975.         mplew.write(3);
  4976.         mplew.writeInt(pet.getItemId());
  4977.         mplew.write(1);
  4978.         mplew.writeInt(pet.getUniqueId());
  4979.         mplew.writeInt(0);
  4980.         mplew.write(0);
  4981.         mplew.write(ITEM_MAGIC);
  4982.         addExpirationTime(mplew, 0, false);
  4983.         String petname = pet.getName();
  4984.         if (petname.length() > 13) {
  4985.             petname = petname.substring(0, 13);
  4986.         }
  4987.         mplew.writeAsciiString(StringUtil.getRightPaddedStr(petname, '\0', 13));
  4988.         mplew.write(pet.getLevel());
  4989.         mplew.writeShort(pet.getCloseness());
  4990.         mplew.write(pet.getFullness());
  4991.         if (alive) {
  4992.             mplew.writeLong(getKoreanTimestamp((long) (System.currentTimeMillis() * 1.5)));
  4993.             mplew.writeInt(0);
  4994.         } else {
  4995.             mplew.write(0);
  4996.             mplew.write(ITEM_MAGIC);
  4997.             addExpirationTime(mplew, 0, false);
  4998.             mplew.writeInt(0);
  4999.         }
  5000.         mplew.writeInt(0);
  5001.         return mplew.getPacket();
  5002.     }
  5003.  
  5004.     public static MaplePacket showPet(MapleCharacter chr, MaplePet pet, boolean remove) {
  5005.         return showPet(chr, pet, remove, false);
  5006.     }
  5007.  
  5008.     public static MaplePacket showPet(MapleCharacter chr, MaplePet pet, boolean remove, boolean hunger) {
  5009.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  5010.  
  5011.         mplew.writeShort(SendPacketOpcode.SPAWN_PET.getValue());
  5012.  
  5013.         mplew.writeInt(chr.getId());
  5014.         mplew.write(chr.getPetIndex(pet));
  5015.         if (remove) {
  5016.             mplew.write(0);
  5017.             mplew.write(hunger ? 1 : 0);
  5018.         } else {
  5019.             mplew.write(1);
  5020.             mplew.write(0);
  5021.             mplew.writeInt(pet.getItemId());
  5022.             mplew.writeMapleAsciiString(pet.getName());
  5023.             mplew.writeInt(pet.getUniqueId());
  5024.             mplew.writeInt(0);
  5025.             mplew.writeShort(pet.getPos().x);
  5026.             mplew.writeShort(pet.getPos().y);
  5027.             mplew.write(pet.getStance());
  5028.             mplew.writeInt(pet.getFh());
  5029.         }
  5030.  
  5031.         return mplew.getPacket();
  5032.     }
  5033.  
  5034.     public static MaplePacket movePet(int cid, int pid, int slot, List<LifeMovementFragment> moves) {
  5035.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  5036.  
  5037.         mplew.writeShort(SendPacketOpcode.MOVE_PET.getValue());
  5038.         mplew.writeInt(cid);
  5039.         mplew.write(slot);
  5040.         mplew.writeInt(pid);
  5041.  
  5042.         serializeMovementList(mplew, moves);
  5043.  
  5044.         return mplew.getPacket();
  5045.     }
  5046.  
  5047.     public static MaplePacket petChat(int cid, int index, int act, String text) {
  5048.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  5049.  
  5050.         mplew.writeShort(SendPacketOpcode.PET_CHAT.getValue());
  5051.         mplew.writeInt(cid);
  5052.         mplew.write(index);
  5053.         mplew.write(0);
  5054.         mplew.write(act);
  5055.         mplew.writeMapleAsciiString(text);
  5056.         mplew.write(0);
  5057.  
  5058.         return mplew.getPacket();
  5059.     }
  5060.  
  5061.     public static MaplePacket commandResponse(int cid, int index, int animation, boolean success) {
  5062.         // 84 00 09 03 2C 00 00 00 19 00 00
  5063.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  5064.         // 84 00 E6 DC 17 00 00 01 00 00
  5065.         mplew.writeShort(SendPacketOpcode.PET_COMMAND.getValue());
  5066.         mplew.writeInt(cid);
  5067.         mplew.write(index);
  5068.         mplew.write((animation == 1 && success) ? 1 : 0);
  5069.         mplew.write(animation);
  5070.         if (animation == 1) {
  5071.             mplew.write(0);
  5072.         } else {
  5073.             mplew.writeShort(success ? 1 : 0);
  5074.         }
  5075.  
  5076.         return mplew.getPacket();
  5077.     }
  5078.  
  5079.     public static MaplePacket showOwnPetLevelUp(int index) {
  5080.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  5081.  
  5082.         mplew.writeShort(SendPacketOpcode.SHOW_ITEM_GAIN_INCHAT.getValue());
  5083.         mplew.write(4);
  5084.         mplew.write(0);
  5085.         mplew.write(index);//Pet Index
  5086.  
  5087.         return mplew.getPacket();
  5088.     }
  5089.  
  5090.     public static MaplePacket showPetLevelUp(MapleCharacter chr, int index) {
  5091.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  5092.  
  5093.         mplew.writeShort(SendPacketOpcode.SHOW_FOREIGN_EFFECT.getValue());
  5094.         mplew.writeInt(chr.getId());
  5095.         mplew.write(4);
  5096.         mplew.write(0);
  5097.         mplew.write(index);
  5098.  
  5099.         return mplew.getPacket();
  5100.     }
  5101.  
  5102.     public static MaplePacket changePetName(MapleCharacter chr, String newname, int slot) {
  5103.         // 82 00 E6 DC 17 00 00 04 00 4A 65 66 66 00
  5104.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  5105.  
  5106.         mplew.writeShort(SendPacketOpcode.PET_NAMECHANGE.getValue());
  5107.         mplew.writeInt(chr.getId());
  5108.         mplew.write(slot);
  5109.         mplew.writeMapleAsciiString(newname);
  5110.         mplew.write(0);
  5111.  
  5112.         return mplew.getPacket();
  5113.     }
  5114.  
  5115.     public static MaplePacket petStatUpdate(MapleCharacter chr) {
  5116.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  5117.  
  5118.         mplew.writeShort(SendPacketOpcode.UPDATE_STATS.getValue());
  5119.  
  5120.         int mask = 0;
  5121.         mask |= MapleStat.PET.getValue();
  5122.         mplew.write(0);
  5123.         mplew.writeInt(mask);
  5124.         MaplePet[] pets = chr.getPets();
  5125.         for (int i = 0; i < 3; i++) {
  5126.             if (pets[i] != null) {
  5127.                 mplew.writeInt(pets[i].getUniqueId());
  5128.             } else {
  5129.                 mplew.writeInt(0);
  5130.             }
  5131.             mplew.writeInt(0);
  5132.         }
  5133.         mplew.write(0);
  5134.  
  5135.         return mplew.getPacket();
  5136.     }
  5137.  
  5138.     public static MaplePacket showForcedEquip() {
  5139.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  5140.         mplew.writeShort(SendPacketOpcode.SHOW_FORCED_EQUIP.getValue());
  5141.         return mplew.getPacket();
  5142.     }
  5143.  
  5144.     public static MaplePacket skillCooldown(int sid, int time) {
  5145.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  5146.  
  5147.         mplew.writeShort(SendPacketOpcode.COOLDOWN.getValue());
  5148.  
  5149.         mplew.writeInt(sid);
  5150.         mplew.writeShort(time);
  5151.  
  5152.         return mplew.getPacket();
  5153.     }
  5154.  
  5155.     public static MaplePacket skillBookSuccess(MapleCharacter chr, int skillid,
  5156.             int maxlevel, boolean canuse, boolean success) {
  5157.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  5158.         mplew.writeShort(SendPacketOpcode.USE_SKILL_BOOK.getValue());
  5159.         mplew.writeInt(chr.getId()); // character id
  5160.  
  5161.         mplew.write(1);
  5162.         mplew.writeInt(skillid);
  5163.         mplew.writeInt(maxlevel);
  5164.         mplew.write(canuse ? 1 : 0);
  5165.         mplew.write(success ? 1 : 0);
  5166.         return mplew.getPacket();
  5167.     }
  5168.  
  5169.     public static MaplePacket getMacros(SkillMacro[] macros) {
  5170.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  5171.         mplew.writeShort(SendPacketOpcode.SKILL_MACRO.getValue());
  5172.         int count = 0;
  5173.         for (int i = 0; i < 5; i++) {
  5174.             if (macros[i] != null) {
  5175.                 count++;
  5176.             }
  5177.         }
  5178.         mplew.write(count); // number of macros
  5179.  
  5180.         for (int i = 0; i < 5; i++) {
  5181.             SkillMacro macro = macros[i];
  5182.             if (macro != null) {
  5183.                 mplew.writeMapleAsciiString(macro.getName());
  5184.                 mplew.write(macro.getShout());
  5185.                 mplew.writeInt(macro.getSkill1());
  5186.                 mplew.writeInt(macro.getSkill2());
  5187.                 mplew.writeInt(macro.getSkill3());
  5188.             }
  5189.         }
  5190.  
  5191.         return mplew.getPacket();
  5192.     }
  5193.  
  5194.     public static MaplePacket showNotes(ResultSet notes, int count) throws SQLException {
  5195.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  5196.         mplew.writeShort(SendPacketOpcode.SHOW_NOTES.getValue());
  5197.  
  5198.         mplew.write(2);
  5199.         mplew.write(count);
  5200.  
  5201.         for (int i = 0; i < count; i++) {
  5202.             mplew.writeInt(notes.getInt("id"));
  5203.             mplew.writeMapleAsciiString(notes.getString("from"));
  5204.             mplew.writeMapleAsciiString(notes.getString("message"));
  5205.             mplew.writeLong(getKoreanTimestamp(notes.getLong("timestamp")));
  5206.             mplew.write(0);
  5207.             notes.next();
  5208.         }
  5209.  
  5210.         return mplew.getPacket();
  5211.     }
  5212.  
  5213.     public static void sendUnkwnNote(String to, String msg, String from) throws SQLException {
  5214.         Connection con = DatabaseConnection.getConnection();
  5215.         PreparedStatement ps = con.prepareStatement("INSERT INTO notes (`to`, `from`, `message`, `timestamp`) VALUES (?, ?, ?, ?)");
  5216.         ps.setString(1, to);
  5217.         ps.setString(2, from);
  5218.         ps.setString(3, msg);
  5219.         ps.setLong(4, System.currentTimeMillis());
  5220.         ps.executeUpdate();
  5221.         ps.close();
  5222.     }
  5223.  
  5224.     /**
  5225.      * Gets a gm effect packet (ie. hide, banned, etc.)
  5226.      *
  5227.      * Possible values for <code>type</code>:<br>
  5228.      * 4: You have successfully blocked access.<br>
  5229.      * 5: The unblocking has been successful.<br>
  5230.      * 6 with Mode 0: You have successfully removed the name from the ranks.<br>
  5231.      * 6 with Mode 1: You have entered an invalid character name.<br>
  5232.      * 16: GM Hide, mode determines whether or not it is on.<br>
  5233.      * 26: Enables minimap<br>
  5234.      * 27: Disables minimap<br>
  5235.      * 29 with Mode 0: Unable to send the message. Please enter the user's name before warning.<br>
  5236.      * 29 with Mode 1: Your warning has been successfully sent.<br>
  5237.      *
  5238.      * @param type The type
  5239.      * @param mode The mode
  5240.      * @return The gm effect packet
  5241.      */
  5242.     public static MaplePacket sendGMOperation(int type, int mode) {
  5243.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  5244.         mplew.writeShort(SendPacketOpcode.GM_OPERATION.getValue());
  5245.         mplew.write(type);
  5246.         mplew.write(mode);
  5247.         return mplew.getPacket();
  5248.     }
  5249.  
  5250.     public static MaplePacket sendHammerSlot(int slot) {
  5251.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  5252.         mplew.writeShort(SendPacketOpcode.VICIOUS_HAMMER.getValue());
  5253.         mplew.write(0x34);
  5254.         mplew.writeInt(0);
  5255.         mplew.writeInt(slot);
  5256.         return mplew.getPacket();
  5257.     }
  5258.  
  5259.     public static MaplePacket sendHammerEnd() {
  5260.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  5261.         mplew.writeShort(SendPacketOpcode.VICIOUS_HAMMER.getValue());
  5262.         mplew.write(0x38);
  5263.         mplew.writeInt(0);
  5264.         return mplew.getPacket();
  5265.     }
  5266.  
  5267.     public static MaplePacket updateHammerItem(IItem item) {
  5268.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  5269.         mplew.writeShort(SendPacketOpcode.MODIFY_INVENTORY_ITEM.getValue());
  5270.         mplew.write(0);
  5271.         mplew.write(2);
  5272.         mplew.write(3);
  5273.         mplew.write(item.getType());
  5274.         mplew.writeShort(item.getPosition());
  5275.         mplew.write(0);
  5276.         mplew.write(1);
  5277.         addItemInfo(mplew, item, false, false, true);
  5278.         return mplew.getPacket();
  5279.     }
  5280.  
  5281.     public static MaplePacket sendCygnusCreation() {
  5282.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  5283.         mplew.writeShort(SendPacketOpcode.CREATE_CYGNUS.getValue());
  5284.         return mplew.getPacket();
  5285.     }
  5286.  
  5287.     /**
  5288.      *
  5289.      * @param type Success = 0 \r\n Name in Use = 1 \r\n All Character Slots Full = 2 \r\n This Name Cannot be Used = 3 \r\n
  5290.      * @return
  5291.      */
  5292.     public static MaplePacket sendCygnusMessage(int type) {
  5293.         MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
  5294.         mplew.writeShort(SendPacketOpcode.CYGNUS_RESPONSE.getValue());
  5295.         mplew.writeInt(type);
  5296.         return mplew.getPacket();
  5297.  
  5298.     }
  5299. }
  5300.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement