├── logs └── log.txt ├── WinPcap_4.1.3.exe ├── lib ├── jnetpcap.jar ├── mina-core.jar ├── slf4j-api.jar ├── slf4j-jdk14.jar ├── 32bit │ └── jnetpcap.dll └── 64bit │ └── jnetpcap.dll ├── blockOpcode.ini ├── dist ├── lib │ ├── jnetpcap.jar │ ├── mina-core.jar │ ├── slf4j-api.jar │ └── slf4j-jdk14.jar ├── MapleSnowSniffer.jar └── README.TXT ├── MapleSnowSniffer-32bit.bat ├── MapleSnowSniffer-64bit.bat ├── settings.ini ├── src └── org │ └── snow │ ├── odinms │ ├── IntValueHolder.java │ ├── WritableIntValueHolder.java │ ├── ByteInputStream.java │ ├── SaveFileFilter.java │ ├── SeekableLittleEndianAccessor.java │ ├── MapleSkinColor.java │ ├── SeekableInputStreamBytestream.java │ ├── MapleStat.java │ ├── PropertyTool.java │ ├── MapleWorld.java │ ├── GenericSeekableLittleEndianAccessor.java │ ├── LittleEndianAccessor.java │ ├── MapleJob.java │ ├── Pair.java │ ├── ByteArrayByteStream.java │ ├── MapleCustomEncryption.java │ ├── ExternalCodeTableGetter.java │ ├── StringUtil.java │ ├── BitTools.java │ ├── HexTool.java │ ├── GenericLittleEndianAccessor.java │ ├── RecvPacketOpcode.java │ ├── SendPacketOpcode.java │ └── MapleAESOFB.java │ └── maplesnowsniffer │ ├── Main.java │ ├── Lang.java │ ├── ListDevicesOld.java │ ├── PacketDataTree.form │ ├── PacketDataTree.java │ ├── GMSKeys.java │ ├── MaplePacketStructureViewer.form │ ├── EditOpcode.form │ ├── MaplePacketRecord.java │ ├── MakeLang.form │ ├── EditOpcode.java │ ├── MakeLang.java │ ├── MapleOpcodeView.form │ ├── MapleBlockedOpcodeViewer.form │ └── ListDevices.form ├── languages ├── lng_EN.ini └── lng_VI.ini ├── recvops.properties └── sendops.properties /logs/log.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /WinPcap_4.1.3.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tranleo148/snowsniffer/HEAD/WinPcap_4.1.3.exe -------------------------------------------------------------------------------- /lib/jnetpcap.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tranleo148/snowsniffer/HEAD/lib/jnetpcap.jar -------------------------------------------------------------------------------- /lib/mina-core.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tranleo148/snowsniffer/HEAD/lib/mina-core.jar -------------------------------------------------------------------------------- /lib/slf4j-api.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tranleo148/snowsniffer/HEAD/lib/slf4j-api.jar -------------------------------------------------------------------------------- /blockOpcode.ini: -------------------------------------------------------------------------------- 1 | #Tue Sep 03 14:22:13 ICT 2013 2 | S_CDE=1 3 | R_DEF=1 4 | R_CDE=1 5 | S_ABC=1 6 | -------------------------------------------------------------------------------- /lib/slf4j-jdk14.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tranleo148/snowsniffer/HEAD/lib/slf4j-jdk14.jar -------------------------------------------------------------------------------- /dist/lib/jnetpcap.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tranleo148/snowsniffer/HEAD/dist/lib/jnetpcap.jar -------------------------------------------------------------------------------- /dist/lib/mina-core.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tranleo148/snowsniffer/HEAD/dist/lib/mina-core.jar -------------------------------------------------------------------------------- /dist/lib/slf4j-api.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tranleo148/snowsniffer/HEAD/dist/lib/slf4j-api.jar -------------------------------------------------------------------------------- /lib/32bit/jnetpcap.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tranleo148/snowsniffer/HEAD/lib/32bit/jnetpcap.dll -------------------------------------------------------------------------------- /lib/64bit/jnetpcap.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tranleo148/snowsniffer/HEAD/lib/64bit/jnetpcap.dll -------------------------------------------------------------------------------- /dist/MapleSnowSniffer.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tranleo148/snowsniffer/HEAD/dist/MapleSnowSniffer.jar -------------------------------------------------------------------------------- /dist/lib/slf4j-jdk14.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tranleo148/snowsniffer/HEAD/dist/lib/slf4j-jdk14.jar -------------------------------------------------------------------------------- /MapleSnowSniffer-32bit.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | set CLASSPATH=.;dist/*; 3 | java -Djava.library.path=lib/32bit -Dnet.sf.odinms.recvops=recvops.properties -Dnet.sf.odinms.sendops=sendops.properties org.snow.maplesnowsniffer.ListDevices 4 | pause -------------------------------------------------------------------------------- /MapleSnowSniffer-64bit.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | set CLASSPATH=.;dist/*; 3 | java -Djava.library.path=lib/64bit -Dnet.sf.odinms.recvops=recvops.properties -Dnet.sf.odinms.sendops=sendops.properties org.snow.maplesnowsniffer.ListDevices 4 | pause -------------------------------------------------------------------------------- /settings.ini: -------------------------------------------------------------------------------- 1 | #Tue Sep 03 14:31:06 ICT 2013 2 | SHOW_ASCII=1 3 | CAPTURE_TYPE=PACKET 4 | LOGGING=1 5 | SERVER_TYPE=ODINMS 6 | USE_GUI=1 7 | LANGUAGE=EN 8 | APPEND_LOG=0 9 | BLOCK_DEF=0 10 | LOG_NAME=log.txt 11 | FILTER=TCP 12 | DEVICE=0 13 | SHOW_HEX=1 14 | -------------------------------------------------------------------------------- /src/org/snow/odinms/IntValueHolder.java: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the OdinMS Maple Story Server 3 | Copyright (C) 2008 Patrick Huy 4 | Matthias Butz 5 | Jan Christian Meyer 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU Affero General Public License version 3 9 | as published by the Free Software Foundation. You may not use, modify 10 | or distribute this program under any other version of the 11 | GNU Affero General Public License. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU Affero General Public License for more details. 17 | 18 | You should have received a copy of the GNU Affero General Public License 19 | along with this program. If not, see . 20 | */ 21 | 22 | package org.snow.odinms; 23 | 24 | public interface IntValueHolder { 25 | int getValue(); 26 | } 27 | -------------------------------------------------------------------------------- /src/org/snow/odinms/WritableIntValueHolder.java: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the OdinMS Maple Story Server 3 | Copyright (C) 2008 Patrick Huy 4 | Matthias Butz 5 | Jan Christian Meyer 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU Affero General Public License version 3 9 | as published by the Free Software Foundation. You may not use, modify 10 | or distribute this program under any other version of the 11 | GNU Affero General Public License. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU Affero General Public License for more details. 17 | 18 | You should have received a copy of the GNU Affero General Public License 19 | along with this program. If not, see . 20 | */ 21 | 22 | package org.snow.odinms; 23 | 24 | public interface WritableIntValueHolder extends IntValueHolder { 25 | public void setValue (int newval); 26 | } 27 | -------------------------------------------------------------------------------- /src/org/snow/maplesnowsniffer/Main.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this template, choose Tools | Templates 3 | * and open the template in the editor. 4 | */ 5 | 6 | package org.snow.maplesnowsniffer; 7 | 8 | /** 9 | * 10 | * @author Raz 11 | */ 12 | public class Main { 13 | 14 | /** 15 | * @param args the command line arguments 16 | */ 17 | public static void main(String[] args) { 18 | try { 19 | if (args.length > 0) { 20 | String program = args[0]; 21 | String[] argsNew = new String[args.length - 1]; 22 | for(int i = 1; i < args.length; i++) { 23 | argsNew[i - 1] = args[i]; 24 | } 25 | 26 | if (program.equals("sniffer")) { 27 | MaplePcapture.main(argsNew); 28 | } else if (program.equals("listdevices")) { 29 | //ListDevicesOld.main(argsNew); 30 | } else if (program.equals("opcodeview")) { 31 | MapleOpcodeView.main(argsNew); 32 | } else { 33 | System.out.println("Unknown starting argument"); 34 | } 35 | } 36 | } catch (Exception e) { 37 | e.printStackTrace(); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /dist/README.TXT: -------------------------------------------------------------------------------- 1 | ======================== 2 | BUILD OUTPUT DESCRIPTION 3 | ======================== 4 | 5 | When you build an Java application project that has a main class, the IDE 6 | automatically copies all of the JAR 7 | files on the projects classpath to your projects dist/lib folder. The IDE 8 | also adds each of the JAR files to the Class-Path element in the application 9 | JAR files manifest file (MANIFEST.MF). 10 | 11 | To run the project from the command line, go to the dist folder and 12 | type the following: 13 | 14 | java -jar "MapleSnowSniffer.jar" 15 | 16 | To distribute this project, zip up the dist folder (including the lib folder) 17 | and distribute the ZIP file. 18 | 19 | Notes: 20 | 21 | * If two JAR files on the project classpath have the same name, only the first 22 | JAR file is copied to the lib folder. 23 | * Only JAR files are copied to the lib folder. 24 | If the classpath contains other types of files or folders, these files (folders) 25 | are not copied. 26 | * If a library on the projects classpath also has a Class-Path element 27 | specified in the manifest,the content of the Class-Path element has to be on 28 | the projects runtime path. 29 | * To set a main class in a standard Java project, right-click the project node 30 | in the Projects window and choose Properties. Then click Run and enter the 31 | class name in the Main Class field. Alternatively, you can manually type the 32 | class name in the manifest Main-Class element. 33 | -------------------------------------------------------------------------------- /src/org/snow/maplesnowsniffer/Lang.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this template, choose Tools | Templates 3 | * and open the template in the editor. 4 | */ 5 | package org.snow.maplesnowsniffer; 6 | 7 | import java.io.FileReader; 8 | import java.io.InputStreamReader; 9 | import java.util.Properties; 10 | 11 | /** 12 | * 13 | * @author Administrator 14 | */ 15 | public class Lang { 16 | private static final Properties prop = new Properties(); 17 | private static String lang_name = null; 18 | 19 | static { 20 | reloadValues(); 21 | } 22 | 23 | public static void reloadValues() { 24 | load();//lang_name = MaplePcapture.getInstance().getSettings().getProperty("LANGUAGE"); 25 | try { 26 | InputStreamReader is = new FileReader("languages/lng_"+ lang_name +".ini"); 27 | prop.load(is); 28 | is.close(); 29 | } catch (Exception e) { 30 | System.out.println("File not found: " + e); 31 | } 32 | } 33 | 34 | public static String get(String msgid) { 35 | return prop.getProperty(msgid); 36 | } 37 | 38 | public static boolean load() { 39 | Properties prop = new Properties(); 40 | try { 41 | InputStreamReader is = new FileReader("settings.ini"); 42 | prop.load(is); 43 | is.close(); 44 | } catch (Exception e) { 45 | System.out.println(e); 46 | } 47 | lang_name = prop.getProperty("LANGUAGE"); 48 | return true; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/org/snow/odinms/ByteInputStream.java: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the OdinMS Maple Story Server 3 | Copyright (C) 2008 Patrick Huy 4 | Matthias Butz 5 | Jan Christian Meyer 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU Affero General Public License version 3 9 | as published by the Free Software Foundation. You may not use, modify 10 | or distribute this program under any other version of the 11 | GNU Affero General Public License. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU Affero General Public License for more details. 17 | 18 | You should have received a copy of the GNU Affero General Public License 19 | along with this program. If not, see . 20 | */ 21 | 22 | package org.snow.odinms; 23 | 24 | /** 25 | * Represents an abstract stream of bytes. 26 | * 27 | * @author Frz 28 | * @version 1.0 29 | * @since Revision 323 30 | */ 31 | public interface ByteInputStream { 32 | /** 33 | * Reads the next byte off the stream. 34 | * @return The next byte as an integer. 35 | */ 36 | int readByte(); 37 | /** 38 | * Gets the number of bytes read from the stream. 39 | * @return The number of bytes as a long integer. 40 | */ 41 | long getBytesRead(); 42 | /** 43 | * Gets the number of bytes still left for reading. 44 | * @return The number of bytes as a long integer. 45 | */ 46 | long available(); 47 | } 48 | -------------------------------------------------------------------------------- /src/org/snow/odinms/SaveFileFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the OdinMS Maple Story Server 3 | Copyright (C) 2008 Patrick Huy 4 | Matthias Butz 5 | Jan Christian Meyer 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU Affero General Public License version 3 9 | as published by the Free Software Foundation. You may not use, modify 10 | or distribute this program under any other version of the 11 | GNU Affero General Public License. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU Affero General Public License for more details. 17 | 18 | You should have received a copy of the GNU Affero General Public License 19 | along with this program. If not, see . 20 | */ 21 | 22 | package org.snow.odinms; 23 | 24 | import java.io.File; 25 | 26 | import javax.swing.filechooser.FileFilter; 27 | 28 | /** 29 | * 30 | * @author Raz 31 | */ 32 | public class SaveFileFilter extends FileFilter { 33 | 34 | public String desc = ""; 35 | 36 | public SaveFileFilter(String desc) { 37 | this.desc = desc; 38 | } 39 | 40 | public SaveFileFilter() { 41 | 42 | } 43 | 44 | public void setDescription(String desc) { 45 | this.desc = desc; 46 | } 47 | 48 | @Override 49 | public boolean accept(File file) { 50 | return true; 51 | } 52 | 53 | @Override 54 | public String getDescription() { 55 | return desc; 56 | } 57 | } -------------------------------------------------------------------------------- /src/org/snow/odinms/SeekableLittleEndianAccessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the OdinMS Maple Story Server 3 | Copyright (C) 2008 Patrick Huy 4 | Matthias Butz 5 | Jan Christian Meyer 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU Affero General Public License version 3 9 | as published by the Free Software Foundation. You may not use, modify 10 | or distribute this program under any other version of the 11 | GNU Affero General Public License. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU Affero General Public License for more details. 17 | 18 | You should have received a copy of the GNU Affero General Public License 19 | along with this program. If not, see . 20 | */ 21 | 22 | package org.snow.odinms; 23 | 24 | /** 25 | * This provides an interface to a seekable accessor to a stream of little 26 | * endian bytes. 27 | * 28 | * 29 | * @author Frz 30 | * @since Revision 299 31 | * @version 1.0 32 | */ 33 | public interface SeekableLittleEndianAccessor extends LittleEndianAccessor { 34 | /** 35 | * Seeks the stream by offset 36 | * 37 | * @param offset 38 | * Number of bytes to seek ahead. 39 | */ 40 | void seek(long offset); 41 | 42 | /** 43 | * Gets the current position of the stream pointer. 44 | * 45 | * @return The current position in the stream as a long integer. 46 | */ 47 | long getPosition(); 48 | } 49 | -------------------------------------------------------------------------------- /src/org/snow/odinms/MapleSkinColor.java: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the OdinMS Maple Story Server 3 | Copyright (C) 2008 Patrick Huy 4 | Matthias Butz 5 | Jan Christian Meyer 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU Affero General Public License version 3 9 | as published by the Free Software Foundation. You may not use, modify 10 | or distribute this program under any other version of the 11 | GNU Affero General Public License. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU Affero General Public License for more details. 17 | 18 | You should have received a copy of the GNU Affero General Public License 19 | along with this program. If not, see . 20 | */ 21 | 22 | package org.snow.odinms; 23 | 24 | public enum MapleSkinColor { 25 | NORMAL(0), DARK(1), BLACK(2), PALE(3), BLUE(4), WHITE(9); 26 | 27 | final int id; 28 | 29 | /** 30 | * Creates a new MapleSkinColor 31 | * @param id 32 | */ 33 | private MapleSkinColor(int id) { 34 | this.id = id; 35 | } 36 | 37 | /** 38 | * Get the skincolor's id 39 | * @return skincolor's id. 40 | */ 41 | public int getId() { 42 | return id; 43 | } 44 | 45 | /** 46 | * Get a MapleSkinColor by id 47 | * @param id 48 | * @return MapleSkinColor with the id 49 | */ 50 | public static MapleSkinColor getById(int id) { 51 | for (MapleSkinColor l : MapleSkinColor.values()) { 52 | if (l.getId() == id) { 53 | return l; 54 | } 55 | } 56 | return null; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/org/snow/odinms/SeekableInputStreamBytestream.java: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the OdinMS Maple Story Server 3 | Copyright (C) 2008 Patrick Huy 4 | Matthias Butz 5 | Jan Christian Meyer 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU Affero General Public License version 3 9 | as published by the Free Software Foundation. You may not use, modify 10 | or distribute this program under any other version of the 11 | GNU Affero General Public License. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU Affero General Public License for more details. 17 | 18 | You should have received a copy of the GNU Affero General Public License 19 | along with this program. If not, see . 20 | */ 21 | 22 | package org.snow.odinms; 23 | 24 | import java.io.IOException; 25 | 26 | /** 27 | * Provides an abstract interface to a stream of bytes. This stream can be 28 | * seeked. 29 | * 30 | * @author Frz 31 | * @version 1.0 32 | * @since 299 33 | */ 34 | public interface SeekableInputStreamBytestream extends ByteInputStream { 35 | /** 36 | * Seeks the stream by the specified offset. 37 | * 38 | * @param offset 39 | * Number of bytes to seek. 40 | * @throws IOException 41 | */ 42 | void seek(long offset) throws IOException; 43 | 44 | /** 45 | * Gets the current position of the stream. 46 | * 47 | * @return The stream position as a long integer. 48 | * @throws IOException 49 | */ 50 | long getPosition() throws IOException; 51 | } 52 | -------------------------------------------------------------------------------- /src/org/snow/maplesnowsniffer/ListDevicesOld.java: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the OdinMS Maple Story Server 3 | Copyright (C) 2008 Patrick Huy 4 | Matthias Butz 5 | Jan Christian Meyer 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU Affero General Public License version 3 9 | as published by the Free Software Foundation. You may not use, modify 10 | or distribute this program under any other version of the 11 | GNU Affero General Public License. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU Affero General Public License for more details. 17 | 18 | You should have received a copy of the GNU Affero General Public License 19 | along with this program. If not, see . 20 | 21 | 22 | package org.snow.maplesnowsniffer; 23 | 24 | import java.io.IOException; 25 | import jpcap.JpcapCaptor; 26 | import jpcap.NetworkInterface; 27 | import jpcap.NetworkInterfaceAddress; 28 | 29 | public class ListDevicesOld { 30 | 31 | private static NetworkInterface[] devices = JpcapCaptor.getDeviceList(); 32 | 33 | public static void main(String args[]) throws IOException { 34 | 35 | System.out.println("Snow's Packet Sniff Device Lister\r\n"); 36 | 37 | for (int i = 0; i < devices.length; i++) { 38 | System.out.println(i + ": " + devices[i].description + ")"); 39 | for (NetworkInterfaceAddress a : devices[i].addresses) { 40 | System.out.println(a.address.toString().substring(1)); 41 | } 42 | System.out.println("\n"); 43 | } 44 | } 45 | }*/ 46 | -------------------------------------------------------------------------------- /src/org/snow/odinms/MapleStat.java: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the OdinMS Maple Story Server 3 | Copyright (C) 2008 Patrick Huy 4 | Matthias Butz 5 | Jan Christian Meyer 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU Affero General Public License version 3 9 | as published by the Free Software Foundation. You may not use, modify 10 | or distribute this program under any other version of the 11 | GNU Affero General Public License. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU Affero General Public License for more details. 17 | 18 | You should have received a copy of the GNU Affero General Public License 19 | along with this program. If not, see . 20 | */ 21 | 22 | package org.snow.odinms; 23 | 24 | public enum MapleStat implements IntValueHolder { 25 | SKIN(0x1), 26 | FACE(0x2), 27 | HAIR(0x4), 28 | PET_1(0x8), 29 | LEVEL(0x10), 30 | JOB(0x20), 31 | STR(0x40), 32 | DEX(0x80), 33 | INT(0x100), 34 | LUK(0x200), 35 | HP(0x400), 36 | MAXHP(0x800), 37 | MP(0x1000), 38 | MAXMP(0x2000), 39 | AVAILABLEAP(0x4000), 40 | AVAILABLESP(0x8000), 41 | EXP(0x10000), 42 | FAME(0x20000), 43 | MESO(0x40000), 44 | PET_2(0x80000), 45 | PET_3(0x100000); 46 | 47 | private final int i; 48 | 49 | /** 50 | * Creates a new MapleStat 51 | * @param i 52 | */ 53 | private MapleStat(int i) { 54 | this.i = i; 55 | } 56 | 57 | /** 58 | * 59 | * @return the stat's mask value 60 | */ 61 | @Override 62 | public int getValue() { 63 | return i; 64 | } 65 | 66 | /** 67 | * Get a MapleStat by value 68 | * @param value 69 | * @return MapleStat with the value 70 | */ 71 | public static MapleStat getByValue (int value) { 72 | for (MapleStat stat : MapleStat.values()) { 73 | if (stat.getValue() == value) { 74 | return stat; 75 | } 76 | } 77 | return null; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /languages/lng_EN.ini: -------------------------------------------------------------------------------- 1 | #Fri Sep 06 22:59:52 ICT 2013 2 | main.notice.savedPacket=Successfully saved file\!\!\! 3 | main.menu.about.text=Snow's Packet Sniffer Upgrade Version\\r\\nOwner\: Snow \\r\\nUpgraded,Fixed\: anhtanh95 4 | blockTable.notice.save.ok=Successfully saved 5 | main.menu.about=About 6 | main.button.showBlock=Show Blocked Opcodes 7 | blockTable.button.add=Add 8 | main.menu.lang.eng=English 9 | blockTable.blocked=Blocked 10 | setting.button.close=Close 11 | setting.text=Wellcome To Maple Snow Sniffer 12 | main.menu.lang=Languages 13 | main.bar.status.setStatus=Status\: 14 | opcodeTable.total.update=Total\: 15 | main.button.lockPacket=Block Packet 16 | opcodeTable.button.edit=Edit 17 | blockTable.button.del=Delete 18 | opcodeTable.button.save=Save 19 | setting.checkBox.showASCII=Show ASCII 20 | main.bar.packetCount=Total Packet Count\: 0 21 | main.button.autoScroll=Auto-Scroll 22 | opcodeTable.notice.update.ok=Update Successful Packet Headers. 23 | main.menu.close=Close 24 | main.menu.save=Save 25 | main.bar.status.copiedPacket=Copied packet-data to clipboard 26 | main.menu.viewSetting=Show Setting Info 27 | main.button.copyPacket=Copy Packet Data 28 | setting.text2=Interface 29 | main.button.showHeader=Show Packet Headers 30 | blockTable.notice.del=Select A Line To Remove. 31 | opcodeTable.button.close=Close 32 | main.bar.status.blockedPacket=Packet Block Added 33 | blockTable.button.save=Save 34 | opcodeTable.notice.edit.error=Select A Line To Edit. 35 | main.button.resume=Resume Now 36 | main.bar.status=Status\: Waiting For MapleStory... 37 | main.menu.resetCount=Reset Packet Count 38 | main.notice.blockPacket=Select A Packet To Block 39 | setting.checkBox.showHEX=Show HEX 40 | main.menu.lang.viet=Vietnamese 41 | opcodeTable.total=Total\: 0 42 | main.bar.packetCount.set=Total Packet Count\: 43 | setting.checkBox.makelog=Make Log File 44 | opcodeTable.notice.update.error=Error Updating Packet Headers. 45 | main.bar.status.resetCount=Total packet count has been reset. 46 | main.menu.load=Load/Open File 47 | blockTable.button.close=Close 48 | notDone=This Function Is Being Complete\!\!\! 49 | opcodeTable.button.update=Update 50 | main.notice.copyPacket=Select A Packet To Copy 51 | blockTable.notice.save.error=Error Updating 52 | main.menu.lang.selected=Restart tool to see the changes 53 | main.button.stop=Stop Now 54 | -------------------------------------------------------------------------------- /src/org/snow/odinms/PropertyTool.java: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the OdinMS Maple Story Server 3 | Copyright (C) 2008 Patrick Huy 4 | Matthias Butz 5 | Jan Christian Meyer 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU Affero General public static License version 3 9 | as published by the Free Software Foundation. You may not use, modify 10 | or distribute this program under any other version of the 11 | GNU Affero General public static License. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU Affero General public static License for more details. 17 | 18 | You should have received a copy of the GNU Affero General public static License 19 | along with this program. If not, see . 20 | */ 21 | 22 | package org.snow.odinms; 23 | 24 | import java.util.Properties; 25 | 26 | /** 27 | * 28 | * @author Raz 29 | */ 30 | public class PropertyTool { 31 | 32 | private Properties props = new Properties(); 33 | 34 | public PropertyTool(Properties props) { 35 | this.props = props; 36 | } 37 | 38 | public byte getSettingByte(String key, byte def) { 39 | String property = props.getProperty(key); 40 | if (property != null) { 41 | return Byte.parseByte(property); 42 | } 43 | return def; 44 | } 45 | 46 | public short getSettingShort(String key, short def) { 47 | String property = props.getProperty(key); 48 | if (property != null) { 49 | return Short.parseShort(property); 50 | } 51 | return def; 52 | } 53 | 54 | public int getSettingInt(String key, int def) { 55 | String property = props.getProperty(key); 56 | if (property != null) { 57 | return Integer.parseInt(property); 58 | } 59 | return def; 60 | } 61 | 62 | public long getSettingLong(String key, long def) { 63 | String property = props.getProperty(key); 64 | if (property != null) { 65 | return Long.parseLong(property); 66 | } 67 | return def; 68 | } 69 | 70 | public String getSettingStr(String key, String def) { 71 | String property = props.getProperty(key); 72 | if (property != null) { 73 | return property; 74 | } 75 | return def; 76 | } 77 | 78 | public byte getSettingByte(String key) { 79 | return getSettingByte(key, (byte) -1); 80 | } 81 | 82 | public short getSettingShort(String key) { 83 | return getSettingShort(key, (short) -1); 84 | } 85 | 86 | public int getSettingInt(String key) { 87 | return getSettingInt(key, -1); 88 | } 89 | 90 | public long getSettingLong(String key) { 91 | return getSettingLong(key, -1); 92 | } 93 | 94 | public String getSettingStr(String key) { 95 | return getSettingStr(key, null); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/org/snow/odinms/MapleWorld.java: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the OdinMS Maple Story Server 3 | Copyright (C) 2008 Patrick Huy 4 | Matthias Butz 5 | Jan Christian Meyer 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU Affero General Public License version 3 9 | as published by the Free Software Foundation. You may not use, modify 10 | or distribute this program under any other version of the 11 | GNU Affero General Public License. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU Affero General Public License for more details. 17 | 18 | You should have received a copy of the GNU Affero General Public License 19 | along with this program. If not, see . 20 | */ 21 | 22 | package org.snow.odinms; 23 | 24 | /** 25 | * 26 | * @author Raz 27 | */ 28 | public class MapleWorld { 29 | 30 | private int id; 31 | private String name; 32 | private int maxCharacters; 33 | private WorldStatusType worldStatusType; 34 | 35 | /** 36 | * Creates a new instance of MapleWorld 37 | */ 38 | public MapleWorld() { 39 | } 40 | 41 | public int getId() { 42 | return id; 43 | } 44 | 45 | public String getName() { 46 | return name; 47 | } 48 | 49 | public int getMaxCharacters() { 50 | return maxCharacters; 51 | } 52 | 53 | public WorldStatusType getWorldStatusType() { 54 | return worldStatusType; 55 | } 56 | 57 | public void setId(int id) { 58 | this.id = id; 59 | } 60 | 61 | public void setName(String name) { 62 | this.name = name; 63 | } 64 | 65 | public void setMaxCharacters(int maxCharacters) { 66 | this.maxCharacters = maxCharacters; 67 | } 68 | 69 | public void setWorldStatusType(WorldStatusType worldStatusType) { 70 | this.worldStatusType = worldStatusType; 71 | } 72 | 73 | public static enum WorldStatusType implements IntValueHolder { 74 | 75 | NONE(0), 76 | EVENT(1), 77 | NEW(2), 78 | HOT(3); 79 | private int value; 80 | 81 | private WorldStatusType(int value) { 82 | this.value = value; 83 | } 84 | 85 | public static WorldStatusType getById(int id) { 86 | for (WorldStatusType statusType : WorldStatusType.values()) { 87 | if (statusType.getValue() == id) { 88 | return statusType; 89 | } 90 | } 91 | return NONE; 92 | } 93 | 94 | public static WorldStatusType getByName(String name) { 95 | for (WorldStatusType statusType : WorldStatusType.values()) { 96 | if (statusType.name().equalsIgnoreCase(name)) { 97 | return statusType; 98 | } 99 | } 100 | return NONE; 101 | } 102 | 103 | @Override 104 | public int getValue() { 105 | return value; 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /languages/lng_VI.ini: -------------------------------------------------------------------------------- 1 | #Fri Sep 06 22:58:35 ICT 2013 2 | main.notice.savedPacket=L\u01B0u file th\u00E0nh c\u00F4ng\!\!\! 3 | main.menu.about.text=Snow's Packet Sniffer Phi\u00EAn B\u1EA3n N\u00E2ng C\u1EA5p\\r\\nNg\u01B0\u1EDDi s\u00E1ng l\u1EADp\: Snow \\r\\nS\u1EEDa \u0111\u1ED5i, N\u00E2ng c\u1EA5p, D\u1ECBch thu\u1EADt\: anhtanh95 4 | blockTable.notice.save.ok=L\u01B0u Th\u00E0nh C\u00F4ng 5 | main.menu.about=Th\u00F4ng Tin 6 | main.button.showBlock=Xem Opcodes Kh\u00F3a 7 | blockTable.button.add=Th\u00EAm 8 | main.menu.lang.eng=Ti\u1EBFng Anh 9 | blockTable.blocked=\u0110\u00E3 Kh\u00F3a 10 | setting.button.close=Tho\u00E1t 11 | setting.text=Ch\u00E0o M\u1EEBng \u0110\u1EBFn V\u1EDBi Maple Snow Sniffer 12 | main.menu.lang=Ng\u00F4n Ng\u1EEF 13 | main.bar.status.setStatus=Tr\u1EA1ng Th\u00E1i\: 14 | opcodeTable.total.update=T\u1ED5ng\: 15 | main.button.lockPacket=Kh\u00F3a Packet 16 | opcodeTable.button.edit=S\u1EEDa 17 | blockTable.button.del=X\u00F3a 18 | opcodeTable.button.save=L\u01B0u L\u1EA1i 19 | setting.checkBox.showASCII=Hi\u1EC7n M\u00E3 ASCII 20 | main.bar.packetCount=T\u1ED5ng S\u1ED1 Packet\: 0 21 | main.button.autoScroll=T\u1EF1 Cu\u1ED9n 22 | opcodeTable.notice.update.ok=C\u1EADp Nh\u1EADt Th\u00E0nh C\u00F4ng Packet Headers. 23 | main.menu.close=\u0110\u00F3ng 24 | main.menu.save=L\u01B0u 25 | main.bar.status.copiedPacket=\u0110\u00E3 Copy D\u1EEF Li\u1EC7u Packet v\u00E0o Clipboard 26 | main.menu.viewSetting=Xem C\u00E0i \u0110\u1EB7t 27 | main.button.copyPacket=Copy D\u1EEF Li\u1EC7u Packet 28 | setting.text2=Ch\u1ECDn K\u1EBFt N\u1ED1i 29 | main.button.showHeader=Xem Packet Headers 30 | blockTable.notice.del=H\u00E3y Ch\u1ECDn M\u1ED9t D\u00F2ng \u0110\u1EC3 X\u00F3a. 31 | opcodeTable.button.close=\u0110\u00F3ng 32 | main.bar.status.blockedPacket=\u0110\u00E3 Th\u00EAm Packet Kh\u00F3a 33 | blockTable.button.save=L\u01B0u 34 | opcodeTable.notice.edit.error=H\u00E3y ch\u1ECDn d\u00F2ng c\u1EA7n s\u1EEDa\! 35 | main.button.resume=Ti\u1EBFp T\u1EE5c 36 | main.bar.status=Tr\u1EA1ng Th\u00E1i\: \u0110ang \u0111\u1EE3i MapleStory... 37 | main.menu.resetCount=Reset S\u1ED1 L\u01B0\u1EE3ng Packet 38 | main.notice.blockPacket=H\u00E3y ch\u1ECDn packet \u0111\u1EC3 kh\u00F3a 39 | setting.checkBox.showHEX=Hi\u1EC7n M\u00E3 HEX 40 | main.menu.lang.viet=Ti\u1EBFng Vi\u1EC7t 41 | opcodeTable.total=T\u1ED5ng\: 0 42 | main.bar.packetCount.set=T\u1ED5ng S\u1ED1 Packet\: 43 | setting.checkBox.makelog=T\u1EA1o File Log Packet 44 | opcodeTable.notice.update.error=L\u1ED7i C\u1EADp Nh\u1EADt Packet Headers. 45 | main.bar.status.resetCount=T\u1ED5ng S\u1ED1 Packet \u0110\u00E3 \u0110\u01B0\u1EE3c Reset. 46 | main.menu.load=Load/M\u1EDF File 47 | blockTable.button.close=\u0110\u00F3ng 48 | notDone=Ch\u1EE9c n\u0103ng n\u00E0y \u0111ang \u0111\u01B0\u1EE3c ho\u00E0n thi\u1EC7n\! 49 | opcodeTable.button.update=C\u1EADp Nh\u1EADt 50 | main.notice.copyPacket=H\u00E3y ch\u1ECDn packet \u0111\u1EC3 copy d\u1EEF li\u1EC7u 51 | blockTable.notice.save.error=C\u1EADp Nh\u1EADt Th\u1EA5t B\u1EA1i 52 | main.menu.lang.selected=Kh\u1EDFi \u0111\u1ED9ng l\u1EA1i \u0111\u1EC3 th\u1EA5y thay \u0111\u1ED5i 53 | main.button.stop=D\u1EEBng Ngay 54 | -------------------------------------------------------------------------------- /src/org/snow/odinms/GenericSeekableLittleEndianAccessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the OdinMS Maple Story Server 3 | Copyright (C) 2008 Patrick Huy 4 | Matthias Butz 5 | Jan Christian Meyer 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU Affero General Public License version 3 9 | as published by the Free Software Foundation. You may not use, modify 10 | or distribute this program under any other version of the 11 | GNU Affero General Public License. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU Affero General Public License for more details. 17 | 18 | You should have received a copy of the GNU Affero General Public License 19 | along with this program. If not, see . 20 | */ 21 | 22 | package org.snow.odinms; 23 | 24 | import java.io.IOException; 25 | 26 | import org.slf4j.Logger; 27 | import org.slf4j.LoggerFactory; 28 | /** 29 | * Provides an abstract accessor to a generic Little Endian byte stream. This 30 | * accessor is seekable. 31 | * 32 | * @author Frz 33 | * @version 1.0 34 | * @since Revision 323 35 | * @see net.sf.odinms.tools.data.input.GenericLittleEndianAccessor 36 | */ 37 | public class GenericSeekableLittleEndianAccessor extends 38 | GenericLittleEndianAccessor implements SeekableLittleEndianAccessor { 39 | 40 | private static Logger log = LoggerFactory.getLogger(GenericSeekableLittleEndianAccessor.class); 41 | private SeekableInputStreamBytestream bs; 42 | 43 | /** 44 | * Class constructor 45 | * Provide a seekable input stream to wrap this object around. 46 | * 47 | * @param bs The byte stream to wrap this around. 48 | */ 49 | public GenericSeekableLittleEndianAccessor(SeekableInputStreamBytestream bs) { 50 | super(bs); 51 | this.bs = bs; 52 | } 53 | 54 | /** 55 | * Seek the pointer to offset 56 | * 57 | * @param offset The offset to seek to. 58 | * @see net.sf.odinms.tools.data.input.SeekableInputStreamBytestream#seek 59 | */ 60 | @Override 61 | public void seek(long offset) { 62 | try { 63 | bs.seek(offset); 64 | } catch (IOException e) { 65 | log.error("Seek failed", e); 66 | } 67 | } 68 | 69 | /** 70 | * Get the current position of the pointer. 71 | * 72 | * @return The current position of the pointer as a long integer. 73 | * @see net.sf.odinms.tools.data.input.SeekableInputStreamBytestream#getPosition 74 | */ 75 | @Override 76 | public long getPosition() { 77 | try { 78 | return bs.getPosition(); 79 | } catch (IOException e) { 80 | log.error("getPosition failed", e); 81 | return -1; 82 | } 83 | } 84 | 85 | 86 | /** 87 | * Skip num number of bytes in the stream. 88 | * 89 | * @param num The number of bytes to skip. 90 | */ 91 | @Override 92 | public void skip(int num) { 93 | seek(getPosition() + num); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/org/snow/odinms/LittleEndianAccessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the OdinMS Maple Story Server 3 | Copyright (C) 2008 Patrick Huy 4 | Matthias Butz 5 | Jan Christian Meyer 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU Affero General Public License version 3 9 | as published by the Free Software Foundation. You may not use, modify 10 | or distribute this program under any other version of the 11 | GNU Affero General Public License. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU Affero General Public License for more details. 17 | 18 | You should have received a copy of the GNU Affero General Public License 19 | along with this program. If not, see . 20 | */ 21 | 22 | package org.snow.odinms; 23 | 24 | /** 25 | * Provides an abstract interface for a little-endian stream of bytes. 26 | * 27 | * @author Frz 28 | * @version 1.0 29 | * @since Revision 323 30 | */ 31 | public interface LittleEndianAccessor { 32 | /** 33 | * Reads a byte. 34 | * 35 | * @return The byte read. 36 | */ 37 | byte readByte(); 38 | /** 39 | * Reads a character. 40 | * 41 | * @return The character read. 42 | */ 43 | char readChar(); 44 | /** 45 | * Reads a short integer. 46 | * 47 | * @return The short integer read. 48 | */ 49 | short readShort(); 50 | /** 51 | * Reads a integer. 52 | * 53 | * @return The integer read. 54 | */ 55 | int readInt(); 56 | /** 57 | * Reads a long integer. 58 | * 59 | * @return The long integer read. 60 | */ 61 | long readLong(); 62 | /** 63 | * Skips ahead num bytes. 64 | * 65 | * @param num Number of bytes to skip ahead. 66 | */ 67 | void skip (int num); 68 | /** 69 | * Reads a number of bytes. 70 | * 71 | * @param num The number of bytes to read. 72 | * @return The bytes read. 73 | */ 74 | byte []read(int num); 75 | 76 | /** 77 | * Reads a floating point integer. 78 | * 79 | * @return The floating point integer read. 80 | */ 81 | float readFloat(); 82 | /** 83 | * Reads a double-precision integer. 84 | * 85 | * @return The double-precision integer read. 86 | */ 87 | double readDouble(); 88 | 89 | /** 90 | * Reads an ASCII string. 91 | * 92 | * @return The string read. 93 | */ 94 | String readAsciiString(int n); 95 | /** 96 | * Reads a null-terminated ASCII string. 97 | * 98 | * @return The string read. 99 | */ 100 | String readNullTerminatedAsciiString(); 101 | /** 102 | * Reads a MapleStory convention lengthed ASCII string. 103 | * 104 | * @return The string read. 105 | */ 106 | String readMapleAsciiString(); 107 | /** 108 | * Gets the number of bytes read so far. 109 | * 110 | * @return The number of bytes read as an long integer. 111 | */ 112 | long getBytesRead(); 113 | /** 114 | * Gets the number of bytes left for reading. 115 | * 116 | * @return The number of bytes left for reading as an long integer. 117 | */ 118 | long available(); 119 | } 120 | -------------------------------------------------------------------------------- /src/org/snow/odinms/MapleJob.java: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the OdinMS Maple Story Server 3 | Copyright (C) 2008 Patrick Huy 4 | Matthias Butz 5 | Jan Christian Meyer 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU Affero General Public License version 3 9 | as published by the Free Software Foundation. You may not use, modify 10 | or distribute this program under any other version of the 11 | GNU Affero General Public License. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU Affero General Public License for more details. 17 | 18 | You should have received a copy of the GNU Affero General Public License 19 | along with this program. If not, see . 20 | */ 21 | 22 | package org.snow.odinms; 23 | 24 | public enum MapleJob { 25 | BEGINNER(0), 26 | WARRIOR(100), 27 | FIGHTER(110), 28 | CRUSADER(111), 29 | HERO(112), 30 | PAGE(120), 31 | WHITEKNIGHT(121), 32 | PALADIN(122), 33 | SPEARMAN(130), 34 | DRAGONKNIGHT(131), 35 | DARKKNIGHT(132), 36 | MAGICIAN(200), 37 | FP_WIZARD(210), 38 | FP_MAGE(211), 39 | FP_ARCHMAGE(212), 40 | IL_WIZARD(220), 41 | IL_MAGE(221), 42 | IL_ARCHMAGE(222), 43 | CLERIC(230), 44 | PRIEST(231), 45 | BISHOP(232), 46 | BOWMAN(300), 47 | HUNTER(310), 48 | RANGER(311), 49 | BOWMASTER(312), 50 | CROSSBOWMAN(320), 51 | SNIPER(321), 52 | CROSSBOWMASTER(322), 53 | THIEF(400), 54 | ASSASSIN(410), 55 | HERMIT(411), 56 | NIGHTLORD(412), 57 | BANDIT(420), 58 | CHIEFBANDIT(421), 59 | SHADOWER(422), 60 | PIRATE(500), 61 | BRAWLER(510), 62 | MARAUDER(511), 63 | BUCCANEER(512), 64 | GUNSLINGER(520), 65 | OUTLAW(521), 66 | CORSAIR(522), 67 | GM(900), 68 | SUPERGM(910), 69 | ; 70 | 71 | final int jobid; 72 | 73 | private MapleJob(int id) { 74 | jobid = id; 75 | } 76 | 77 | public int getId() { 78 | return jobid; 79 | } 80 | 81 | public static MapleJob getById(int id) { 82 | for (MapleJob l : MapleJob.values()) { 83 | if (l.getId() == id) { 84 | return l; 85 | } 86 | } 87 | return null; 88 | } 89 | 90 | public static MapleJob getBy5ByteEncoding(int encoded) { 91 | switch (encoded) { 92 | case 2: 93 | return WARRIOR; 94 | case 4: 95 | return MAGICIAN; 96 | case 8: 97 | return BOWMAN; 98 | case 16: 99 | return THIEF; 100 | case 32: 101 | return PIRATE; 102 | default: 103 | return BEGINNER; 104 | } 105 | } 106 | 107 | public boolean isA (MapleJob basejob) { 108 | return getId() >= basejob.getId() && getId() / 100 == basejob.getId() / 100; 109 | } 110 | 111 | public MapleJob getBaseJob() { 112 | if (getId() == 0) { 113 | return MapleJob.BEGINNER; 114 | } 115 | switch(getId() / 100) { 116 | case 1: 117 | return WARRIOR; 118 | case 2: 119 | return MAGICIAN; 120 | case 3: 121 | return BOWMAN; 122 | case 4: 123 | return THIEF; 124 | case 5: 125 | return PIRATE; 126 | case 9: 127 | return GM; 128 | default: 129 | return null; 130 | } 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /src/org/snow/odinms/Pair.java: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the OdinMS Maple Story Server 3 | Copyright (C) 2008 Patrick Huy 4 | Matthias Butz 5 | Jan Christian Meyer 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU Affero General Public License version 3 9 | as published by the Free Software Foundation. You may not use, modify 10 | or distribute this program under any other version of the 11 | GNU Affero General Public License. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU Affero General Public License for more details. 17 | 18 | You should have received a copy of the GNU Affero General Public License 19 | along with this program. If not, see . 20 | */ 21 | 22 | package org.snow.odinms; 23 | 24 | import java.io.Serializable; 25 | /** 26 | * Represents a pair of values. 27 | * 28 | * @author Frz 29 | * @since Revision 333 30 | * @version 1.0 31 | * 32 | * @param The type of the left value. 33 | * @param The type of the right value. 34 | */ 35 | public class Pair implements Serializable { 36 | static final long serialVersionUID = 9179541993413738569L; 37 | private E left; 38 | private F right; 39 | 40 | /** 41 | * Class constructor - pairs two objects together. 42 | * 43 | * @param left The left object. 44 | * @param right The right object. 45 | */ 46 | public Pair(E left, F right) { 47 | this.left = left; 48 | this.right = right; 49 | } 50 | 51 | /** 52 | * Gets the left value. 53 | * 54 | * @return The left value. 55 | */ 56 | public E getLeft() { 57 | return left; 58 | } 59 | 60 | /** 61 | * Gets the right value. 62 | * 63 | * @return The right value. 64 | */ 65 | public F getRight() { 66 | return right; 67 | } 68 | 69 | /** 70 | * Turns the pair into a string. 71 | * 72 | * @return Each value of the pair as a string joined by a colon. 73 | */ 74 | @Override 75 | public String toString() { 76 | return left.toString() + ":" + right.toString(); 77 | } 78 | 79 | /** 80 | * Gets the hash code of this pair. 81 | */ 82 | @Override 83 | public int hashCode() { 84 | final int prime = 31; 85 | int result = 1; 86 | result = prime * result + ((left == null) ? 0 : left.hashCode()); 87 | result = prime * result + ((right == null) ? 0 : right.hashCode()); 88 | return result; 89 | } 90 | 91 | /** 92 | * Checks to see if two pairs are equal. 93 | */ 94 | @SuppressWarnings("unchecked") 95 | @Override 96 | public boolean equals(Object obj) { 97 | if (this == obj) 98 | return true; 99 | if (obj == null) 100 | return false; 101 | if (getClass() != obj.getClass()) 102 | return false; 103 | final Pair other = (Pair) obj; 104 | if (left == null) { 105 | if (other.left != null) 106 | return false; 107 | } else if (!left.equals(other.left)) 108 | return false; 109 | if (right == null) { 110 | if (other.right != null) 111 | return false; 112 | } else if (!right.equals(other.right)) 113 | return false; 114 | return true; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/org/snow/maplesnowsniffer/PacketDataTree.form: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 |
71 | -------------------------------------------------------------------------------- /src/org/snow/maplesnowsniffer/PacketDataTree.java: -------------------------------------------------------------------------------- 1 | package org.snow.maplesnowsniffer; 2 | 3 | import javax.swing.JTree; 4 | 5 | /** 6 | * 7 | * @author Raz 8 | */ 9 | public class PacketDataTree extends javax.swing.JFrame { 10 | 11 | private static final long serialVersionUID = 7209390318289886409L; 12 | /** Creates new form PacketDataTree */ 13 | public PacketDataTree() { 14 | initComponents(); 15 | } 16 | 17 | /** This method is called from within the constructor to 18 | * initialize the form. 19 | * WARNING: Do NOT modify this code. The content of this method is 20 | * always regenerated by the Form Editor. 21 | */ 22 | // //GEN-BEGIN:initComponents 23 | private void initComponents() { 24 | 25 | jScrollPane1 = new javax.swing.JScrollPane(); 26 | packetTree = new javax.swing.JTree(); 27 | closeButton = new javax.swing.JButton(); 28 | 29 | setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); 30 | 31 | jScrollPane1.setViewportView(packetTree); 32 | 33 | closeButton.setText("Đóng"); 34 | closeButton.addActionListener(new java.awt.event.ActionListener() { 35 | public void actionPerformed(java.awt.event.ActionEvent evt) { 36 | closeButtonActionPerformed(evt); 37 | } 38 | }); 39 | 40 | javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); 41 | getContentPane().setLayout(layout); 42 | layout.setHorizontalGroup( 43 | layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 44 | .addGroup(layout.createSequentialGroup() 45 | .addContainerGap() 46 | .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 264, javax.swing.GroupLayout.PREFERRED_SIZE) 47 | .addContainerGap(12, Short.MAX_VALUE)) 48 | .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() 49 | .addContainerGap(119, Short.MAX_VALUE) 50 | .addComponent(closeButton) 51 | .addGap(108, 108, 108)) 52 | ); 53 | layout.setVerticalGroup( 54 | layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 55 | .addGroup(layout.createSequentialGroup() 56 | .addContainerGap() 57 | .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 228, javax.swing.GroupLayout.PREFERRED_SIZE) 58 | .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) 59 | .addComponent(closeButton) 60 | .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) 61 | ); 62 | 63 | pack(); 64 | }// //GEN-END:initComponents 65 | private void closeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_closeButtonActionPerformed 66 | setVisible(false); 67 | }//GEN-LAST:event_closeButtonActionPerformed 68 | 69 | /** 70 | * @param args the command line arguments 71 | */ 72 | public static void main(String args[]) { 73 | java.awt.EventQueue.invokeLater(new Runnable() { 74 | 75 | public void run() { 76 | new PacketDataTree().setVisible(true); 77 | } 78 | }); 79 | } 80 | 81 | public JTree getJTree1() { 82 | return packetTree; 83 | } 84 | 85 | public void setJTree1(JTree jTree1) { 86 | this.packetTree = jTree1; 87 | } 88 | // Variables declaration - do not modify//GEN-BEGIN:variables 89 | private javax.swing.JButton closeButton; 90 | private javax.swing.JScrollPane jScrollPane1; 91 | private javax.swing.JTree packetTree; 92 | // End of variables declaration//GEN-END:variables 93 | } 94 | -------------------------------------------------------------------------------- /src/org/snow/odinms/ByteArrayByteStream.java: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the OdinMS Maple Story Server 3 | Copyright (C) 2008 Patrick Huy 4 | Matthias Butz 5 | Jan Christian Meyer 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU Affero General Public License version 3 9 | as published by the Free Software Foundation. You may not use, modify 10 | or distribute this program under any other version of the 11 | GNU Affero General Public License. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU Affero General Public License for more details. 17 | 18 | You should have received a copy of the GNU Affero General Public License 19 | along with this program. If not, see . 20 | */ 21 | 22 | package org.snow.odinms; 23 | 24 | import java.io.IOException; 25 | 26 | /** 27 | * Provides for an abstraction layer for an array of bytes. 28 | * 29 | * @author Frz 30 | * @version 1.0 31 | * @since Revision 326 32 | */ 33 | public class ByteArrayByteStream implements SeekableInputStreamBytestream { 34 | private int pos = 0; 35 | private long bytesRead = 0; 36 | private byte[] arr; 37 | 38 | /** 39 | * Class constructor. 40 | * 41 | * @param arr Array of bytes to wrap the stream around. 42 | */ 43 | public ByteArrayByteStream(byte[] arr) { 44 | this.arr = arr; 45 | } 46 | 47 | /** 48 | * Gets the current position of the stream. 49 | * 50 | * @return The current position of the stream. 51 | * @see net.sf.odinms.tools.data.input.SeekableInputStreamBytestream#getPosition() 52 | */ 53 | @Override 54 | public long getPosition() { 55 | return pos; 56 | } 57 | 58 | /** 59 | * Seeks the pointer the the specified position. 60 | * 61 | * @param offset The position you wish to seek to. 62 | * @see net.sf.odinms.tools.data.input.SeekableInputStreamBytestream#seek(long) 63 | */ 64 | @Override 65 | public void seek(long offset) throws IOException { 66 | pos = (int) offset; 67 | } 68 | 69 | /** 70 | * Returns the numbers of bytes read from the stream. 71 | * 72 | * @return The number of bytes read. 73 | * @see net.sf.odinms.tools.data.input.ByteInputStream#getBytesRead() 74 | */ 75 | @Override 76 | public long getBytesRead() { 77 | return bytesRead; 78 | } 79 | 80 | /** 81 | * Reads a byte from the current position. 82 | * 83 | * @return The byte as an integer. 84 | * @see net.sf.odinms.tools.data.input.ByteInputStream#readByte() 85 | */ 86 | @Override 87 | public int readByte() { 88 | bytesRead++; 89 | return ((int) arr[pos++]) & 0xFF; 90 | } 91 | 92 | /** 93 | * Returns the current stream as a hexadecimal string of values. 94 | * Shows the entire stream, and the remaining data at the current position. 95 | * 96 | * @return The current stream as a string. 97 | * @see java.lang.Object#toString() 98 | */ 99 | @Override 100 | public String toString() { 101 | String nows = ""; 102 | if (arr.length - pos > 0) { 103 | byte[] now = new byte[arr.length - pos]; 104 | System.arraycopy(arr, pos, now, 0, arr.length - pos); 105 | nows = HexTool.toString(now); 106 | } 107 | return "All: " + HexTool.toString(arr) + "\nNow: " + nows; 108 | } 109 | 110 | /** 111 | * Returns the number of bytes available from the stream. 112 | * 113 | * @return Number of bytes available as a long integer. 114 | * @see net.sf.odinms.tools.data.input.ByteInputStream#available() 115 | */ 116 | @Override 117 | public long available() { 118 | return arr.length - pos; 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/org/snow/maplesnowsniffer/GMSKeys.java: -------------------------------------------------------------------------------- 1 | package org.snow.maplesnowsniffer; 2 | 3 | import java.io.BufferedWriter; 4 | import java.io.File; 5 | import java.io.FileWriter; 6 | import java.io.IOException; 7 | import java.io.InputStreamReader; 8 | import java.net.URL; 9 | import java.util.HashMap; 10 | import java.util.Map; 11 | import java.util.Scanner; 12 | 13 | /** 14 | * 15 | * @author anhtanh95 16 | */ 17 | public class GMSKeys { 18 | 19 | public static Map MapleStoryGlobalKeys = new HashMap(); 20 | public static final String KeyURL = "http://direct.craftnet.nl/app_updates/get_keys.php"; 21 | public static byte[] GetKeyForVersion(short mapleVer) { 22 | if (MapleStoryGlobalKeys.isEmpty()){ 23 | Initialize(); 24 | } 25 | if (MapleStoryGlobalKeys.containsKey((int) mapleVer)) { 26 | byte[] key = MapleStoryGlobalKeys.get((int) mapleVer); 27 | byte[] ret = new byte[32]; 28 | for (int i = 0; i < 8; i++) { 29 | ret[i * 4] = key[i]; 30 | } 31 | return ret; 32 | } else { 33 | return null; 34 | } 35 | } 36 | 37 | public static void Initialize() { 38 | File f = new File("noupdate.txt");// Trigger offline file loading 39 | if (!f.exists()) { 40 | try { 41 | //Load keys from url 42 | URL url = new URL(KeyURL); 43 | String str = ""; 44 | Scanner sc = new Scanner(new InputStreamReader(url.openStream())); 45 | while (sc.hasNextLine()) { 46 | str = str + sc.nextLine() + "\r\n"; 47 | } 48 | InitByContents(str); 49 | sc.close(); 50 | //Save keys to text file 51 | File file = new File("cached_keys.txt"); 52 | if (!file.exists()) { 53 | file.createNewFile(); 54 | } 55 | FileWriter fw = new FileWriter(file.getAbsoluteFile()); 56 | BufferedWriter bw = new BufferedWriter(fw); 57 | bw.write(str); 58 | bw.close(); 59 | } catch (IOException ex) { 60 | System.out.println(ex); 61 | } 62 | } else { 63 | try { 64 | String text = ""; 65 | Scanner input = new Scanner(f); 66 | while (input.hasNextLine()) { 67 | text = text + input.nextLine() + "\r\n"; 68 | } 69 | InitByContents(text); 70 | input.close(); 71 | } catch (IOException ex) { 72 | System.out.println("Unable to load GMS Keys, because there were no cached keys stored and I failed retrieving them from the webserver! D:\r\nYou might want to check your internet connection and see if you can access http://direct.craftnet.nl/ directly."); 73 | } 74 | } 75 | // v118 Full key's lost 76 | MapleStoryGlobalKeys.put(118, new byte[]{ 77 | (byte) 0x5A, (byte) 0x22, (byte) 0xFB, (byte) 0xD1, 78 | (byte) 0x8F, (byte) 0x93, (byte) 0xCD, (byte) 0xE6,}); 79 | 80 | } 81 | 82 | private static void InitByContents(String str) { 83 | String[] lines = str.split("\r\n"); 84 | for (int i = 0; i < lines.length; i += 2) { 85 | int version = Integer.parseInt(lines[i]); 86 | String tmpkey = lines[i + 1]; 87 | String[] TMPkey = tmpkey.split(""); 88 | byte[] realkey = new byte[8]; 89 | int tmp = 0; 90 | for (int j = 1; j < 4 * 2 * 8; j += 4 * 2) // j = 1 because: if j = 0 => TMPkey[0] = "" 91 | { 92 | realkey[tmp++] = (byte) Integer.parseInt(TMPkey[j] + "" + TMPkey[j + 1], 16); 93 | } 94 | MapleStoryGlobalKeys.put(version, realkey); 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/org/snow/odinms/MapleCustomEncryption.java: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the OdinMS Maple Story Server 3 | Copyright (C) 2008 Patrick Huy 4 | Matthias Butz 5 | Jan Christian Meyer 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU Affero General Public License version 3 9 | as published by the Free Software Foundation. You may not use, modify 10 | or distribute this program under any other version of the 11 | GNU Affero General Public License. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU Affero General Public License for more details. 17 | 18 | You should have received a copy of the GNU Affero General Public License 19 | along with this program. If not, see . 20 | */ 21 | 22 | package org.snow.odinms; 23 | 24 | /** 25 | * Provides MapleStory's custom encryption routines. 26 | * 27 | * @author Frz 28 | * @since Revision 211 29 | * @version 1.0 30 | */ 31 | public class MapleCustomEncryption { 32 | 33 | /** 34 | * Encrypts data with Maple's encryption routines. 35 | * 36 | * @param data The data to encrypt. 37 | * @return The encrypted data. 38 | */ 39 | public static byte[] encryptData(byte data[]) { 40 | 41 | for (int j = 0; j < 6; j++) { 42 | byte remember = 0; 43 | byte dataLength = (byte) (data.length & 0xFF); 44 | // printByteArray(data); 45 | if (j % 2 == 0) { 46 | for (int i = 0; i < data.length; i++) { 47 | byte cur = data[i]; 48 | cur = BitTools.rollLeft(cur, 3); 49 | cur += dataLength; 50 | cur ^= remember; 51 | remember = cur; 52 | cur = BitTools.rollRight(cur, (int)dataLength & 0xFF); 53 | cur = ((byte) ((~cur) & 0xFF)); 54 | cur += 0x48; 55 | dataLength--; 56 | data[i] = cur; 57 | } 58 | } else { 59 | for (int i = data.length - 1; i >= 0; i--) { 60 | byte cur = data[i]; 61 | cur = BitTools.rollLeft(cur, 4); 62 | cur += dataLength; 63 | cur ^= remember; 64 | remember = cur; 65 | cur ^= 0x13; 66 | cur = BitTools.rollRight(cur, 3); 67 | dataLength--; 68 | data[i] = cur; 69 | } 70 | } 71 | //System.out.println("enc after iteration " + j + ": " + HexTool.toString(data) + " al: " + al); 72 | } 73 | return data; 74 | } 75 | 76 | /** 77 | * Decrypts data with Maple's encryption routines. 78 | * 79 | * @param data The data to decrypt. 80 | * @return The decrypted data. 81 | */ 82 | public static byte[] decryptData(byte data[]) { 83 | for (int j = 1; j <= 6; j++) { 84 | byte remember = 0; 85 | byte dataLength = (byte) (data.length & 0xFF); 86 | byte nextRemember = 0; 87 | 88 | if (j % 2 == 0) { 89 | for (int i = 0; i < data.length; i++) { 90 | byte cur = data[i]; 91 | cur -= 0x48; 92 | cur = ((byte) ((~cur) & 0xFF)); 93 | cur = BitTools.rollLeft(cur, (int)dataLength & 0xFF); 94 | nextRemember = cur; 95 | cur ^= remember; 96 | remember = nextRemember; 97 | cur -= dataLength; 98 | cur = BitTools.rollRight(cur, 3); 99 | data[i] = cur; 100 | dataLength--; 101 | } 102 | } else { 103 | for (int i = data.length - 1; i >= 0; i--) { 104 | byte cur = data[i]; 105 | cur = BitTools.rollLeft(cur, 3); 106 | cur ^= 0x13; 107 | nextRemember = cur; 108 | cur ^= remember; 109 | remember = nextRemember; 110 | cur -= dataLength; 111 | cur = BitTools.rollRight(cur, 4); 112 | data[i] = cur; 113 | dataLength--; 114 | } 115 | } 116 | //System.out.println("dec after iteration " + j + ": " + HexTool.toString(data)); 117 | } 118 | return data; 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/org/snow/odinms/ExternalCodeTableGetter.java: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the OdinMS Maple Story Server 3 | Copyright (C) 2008 Patrick Huy 4 | Matthias Butz 5 | Jan Christian Meyer 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU Affero General Public License version 3 9 | as published by the Free Software Foundation. You may not use, modify 10 | or distribute this program under any other version of the 11 | GNU Affero General Public License. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU Affero General Public License for more details. 17 | 18 | You should have received a copy of the GNU Affero General Public License 19 | along with this program. If not, see . 20 | */ 21 | 22 | package org.snow.odinms; 23 | 24 | import java.util.ArrayList; 25 | import java.util.Arrays; 26 | import java.util.Collections; 27 | import java.util.Comparator; 28 | import java.util.List; 29 | import java.util.Properties; 30 | 31 | import org.slf4j.Logger; 32 | import org.slf4j.LoggerFactory; 33 | 34 | public class ExternalCodeTableGetter { 35 | Properties props; 36 | 37 | public ExternalCodeTableGetter(Properties properties) { 38 | props = properties; 39 | } 40 | 41 | private static & IntValueHolder> T valueOf(String name, T[] values) { 42 | for (T val : values) { 43 | if (val.name().equals(name)) { 44 | return val; 45 | } 46 | } 47 | return null; 48 | } 49 | 50 | private & IntValueHolder> int getValue(String name, T[] values, int def) { 51 | String prop = props.getProperty(name); 52 | if (prop != null && prop.length() > 0) { 53 | String trimmed = prop.trim(); 54 | String[] args = trimmed.split(" "); 55 | int base = 0; 56 | String offset; 57 | if (args.length == 2) { 58 | base = valueOf (args[0], values).getValue(); 59 | if (base == def) { 60 | base = getValue(args[0], values, def); 61 | } 62 | offset = args[1]; 63 | } else { 64 | offset = args[0]; 65 | } 66 | if (offset.length() > 2 && offset.substring(0, 2).equals("0x")) { 67 | return Integer.parseInt(offset.substring(2), 16) + base; 68 | } else { 69 | return Integer.parseInt(offset) + base; 70 | } 71 | } 72 | return def; 73 | } 74 | 75 | public static & WritableIntValueHolder> 76 | String getOpcodeTable(T[] enumeration) 77 | { 78 | StringBuilder enumVals = new StringBuilder(); 79 | List all = new ArrayList(); // need a mutable list plawks 80 | all.addAll(Arrays.asList(enumeration)); 81 | Collections.sort(all, new Comparator() { 82 | @Override 83 | public int compare(IntValueHolder o1, IntValueHolder o2) { 84 | return Integer.valueOf(o1.getValue()).compareTo(o2.getValue()); 85 | } 86 | }); 87 | for (T code : all) { 88 | enumVals.append(code.name()); 89 | enumVals.append(" = "); 90 | enumVals.append("0x"); 91 | enumVals.append(HexTool.toString(code.getValue())); 92 | enumVals.append(" ("); 93 | enumVals.append(code.getValue()); 94 | enumVals.append(")\n"); 95 | } 96 | return enumVals.toString(); 97 | } 98 | 99 | public static & WritableIntValueHolder> 100 | void populateValues(Properties properties, T[] values) 101 | { 102 | ExternalCodeTableGetter exc = new ExternalCodeTableGetter(properties); 103 | for (T code : values) { 104 | code.setValue(exc.getValue(code.name(), values, -2)); 105 | } 106 | Logger log = LoggerFactory.getLogger(ExternalCodeTableGetter.class); 107 | if (log.isTraceEnabled()) { // generics - copy pasted between send and recv current? 108 | log.trace(getOpcodeTable(values)); 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /recvops.properties: -------------------------------------------------------------------------------- 1 | # GENERAL # 2 | PONG = 0x1A 3 | 4 | # LOGIN # 5 | LOGIN_PASSWORD = 0x01 6 | GUEST_LOGIN = 0x02 7 | SERVERLIST_REREQUEST = 0x04 8 | CHARLIST_REQUEST = 0x05 9 | SERVERSTATUS_REQUEST = 0x06 10 | SET_GENDER = 0x08 11 | AFTER_LOGIN = 0x09 12 | REGISTER_PIN = 0x0A 13 | SERVERLIST_REQUEST = 0x0B 14 | PLAYER_DC = 0x0C 15 | VIEW_ALL_CHAR = 0x0D 16 | PICK_ALL_CHAR = 0x0E 17 | DC_TO_LOGIN = 0x0F 18 | PLAYER_LOGGEDIN = 0x14 19 | CHECK_CHAR_NAME = 0x15 20 | CREATE_CHAR = 0x16 21 | CREATE_CYGNUS = 0x17 22 | CREATE_ULTIMATE = 0x18 23 | DELETE_CHAR = 0x19 24 | ERROR = 0x1A 25 | RELOG = 0x1B 26 | STRANGE_DATA = 0x1C 27 | CHAR_SELECT = 0x1E 28 | CLIENT_START = 0x23 29 | CLIENT_AUTH = 0x24 30 | CLIENT_ERROR = 0x25 31 | 32 | # CHANNEL # 33 | 34 | # + 1 35 | SKILL_USED = 0xDF 36 | CHANGE_MAP = 0x2A 37 | CHANGE_CHANNEL = 0x2B 38 | ENTER_CASH_SHOP = 0x2C 39 | MOVE_PLAYER = 0x2D 40 | CANCEL_CHAIR = 0x2E 41 | USE_CHAIR = 0x2F 42 | CLOSE_RANGE_ATTACK = 0x30 43 | RANGED_ATTACK = 0x31 44 | MAGIC_ATTACK = 0x32 45 | ENERGY_ORB_ATTACK = 0x33 46 | TAKE_DAMAGE = 0x35 47 | GENERAL_CHAT = 0x37 48 | CLOSE_CHALKBOARD = 0x38 49 | FACE_EXPRESSION = 0x39 50 | USE_ITEMEFFECT = 0x3A 51 | USE_DEATHITEM = 0x3B 52 | MONSTER_BOOK_COVER = 0x3C 53 | NPC_TALK = 0x40 54 | NPC_TALK_MORE = 0x42 55 | NPC_SHOP = 0x43 56 | STORAGE = 0x44 57 | HIRED_MERCHANT_REQUEST = 0x45 58 | FREDRICK_OPERATION = 0x46 59 | CANCEL_SKILL = 0x48 60 | MINERVA = 0x49 61 | MINERVA_GO = 0x4A 62 | DUEY_ACTION = 0x4B 63 | ITEM_SORT = 0x4C 64 | ITEM_SORT2 = 0x4D 65 | ITEM_MOVE = 0x4E 66 | # 67 | 68 | # + 2 69 | USE_ITEM = 0x50 70 | CANCEL_ITEM_EFFECT = 0x51 71 | USE_SUMMON_BAG = 0x53 72 | PET_FOOD = 0x54 73 | USE_MOUNT_FOOD = 0x55 74 | SCRIPTED_ITEM = 0x56 75 | USE_CASH_ITEM = 0x57 76 | USE_CATCH_ITEM = 0x59 77 | USE_SKILL_BOOK = 0x5A 78 | USE_TELEPORT_ROCK = 0x5C 79 | USE_RETURN_SCROLL = 0x5E 80 | USE_UPGRADE_SCROLL = 0x5F 81 | USE_ENHANCEMENT_SCROLL = 0x60 82 | USE_POTENTIAL_SCROLL = 0x61 83 | USE_MAGNIFYING_GLASS = 0x64 84 | # 85 | 86 | # + 3 87 | DISTRIBUTE_AP = 0x65 88 | AUTO_DISTRIBUTE_AP = 0x66 89 | HEAL_OVER_TIME = 0x67 90 | DISTRIBUTE_SP = 0x69 91 | SPECIAL_MOVE = 0x6A 92 | CANCEL_BUFF = 0x6B 93 | SKILL_EFFECT = 0x6C 94 | MESO_DROP = 0x6D 95 | GIVE_FAME = 0x6E 96 | CHAR_INFO_REQUEST = 0x70 97 | SPAWN_PET = 0x71 98 | CANCEL_DEBUFF = 0x72 99 | CHANGE_MAP_SPECIAL = 0x73 100 | USE_INNER_PORTAL = 0x74 101 | REPORT = 0x75 102 | TROCK_ADD_MAP = 0x76 103 | QUEST_ACTION = 0x7B 104 | POISON_BOMB = 0x7D 105 | SKILL_MACRO = 0x7E 106 | SPOUSE_CHAT = 0x7F 107 | MWLB_LIE_DETECTOR = 0x78 108 | USE_REWARD_ITEM = 0x80 109 | SILVER_BOX = 0x83 110 | USE_REMOTE = 0x84 111 | PARTYCHAT = 0x90 112 | WHISPER = 0x91 113 | #MESSENGER = 0x93 114 | PLAYER_INTERACTION = 0x94 115 | PARTY_OPERATION = 0x95 116 | DENY_PARTY_REQUEST = 0x96 117 | # 118 | 119 | # + 4 120 | GUILD_OPERATION = 0x99 121 | DENY_GUILD_REQUEST = 0x9A 122 | ADMIN_COMMAND = 0x9B 123 | ADMIN_LOG = 0x9C 124 | BUDDYLIST_MODIFY = 0x9D 125 | NOTE_ACTION = 0x93 126 | # was 0x9F 127 | USE_DOOR = 0xA0 128 | CHANGE_KEYMAP = 0xA3 129 | RPS_ACTION = 0xA4 130 | RING_ACTION = 0xA5 131 | OPEN_FAMILY = 0xAD 132 | ADD_FAMILY = 0xAE 133 | ACCEPT_FAMILY = 0xAF 134 | USE_FAMILY = 0xB0 135 | ALLIANCE_OPERATION = 0xB1 136 | BBS_OPERATION = 0xB7 137 | ENTER_MTS = 0xB8 138 | USE_SOLOMON_ITEM = 0xB9 139 | PET_TALK = 0xBA 140 | CASH_SURPRISE = 0xBD 141 | # 142 | 143 | # + 4 144 | ARAN_COMBO = 0xC1 145 | # 146 | 147 | # +6 148 | MOVE_PET = 0xCD 149 | PET_CHAT = 0xCE 150 | PET_COMMAND = 0xCF 151 | PET_LOOT = 0xD0 152 | PET_AUTO_POT = 0xD1 153 | PET_EXCLUDE_ITEMS = 0xD2 154 | MOVE_SUMMON = 0xD5 155 | SUMMON_ATTACK = 0xD6 156 | DAMAGE_SUMMON = 0xD7 157 | BEHOLDER = 0xD8 158 | REMOVE_SPECIAL_OBJECT = 0xD9 159 | MOVE_DRAGON = 0xDC 160 | PLAYER_UPDATE = 0xDD 161 | UI_ACTION = 0xDE 162 | MOVE_LIFE = 0xE9 163 | AUTO_AGGRO = 0xEA 164 | MOB_DAMAGE_MOB_FRIENDLY = 0xEB 165 | MONSTER_EXPLOSION = 0xEC 166 | MOB_DAMAGE_MOB = 0xED 167 | # 168 | 169 | # + 7 170 | NPC_ACTION = 0xF8 171 | ITEM_PICKUP = 0xFD 172 | DAMAGE_REACTOR = 0x100 173 | TOUCHING_REACTOR = 0x101 174 | # 175 | 176 | MONSTER_BOMB = 0xE0 177 | SNOWBALL = 0x107 178 | LEFT_KNOCKBACK = 0x108 179 | #MONSTER_CARNIVAL = 0xFB 180 | PARTY_SEARCH_REGISTER = 0xFE 181 | PARTY_SEARCH_START = 0xFF 182 | MAPLETV = 0x222FF 183 | 184 | # +10 185 | TOUCHING_CS = 0x11C 186 | BUY_CS_ITEM = 0x11D 187 | COUPON_CODE = 0x11E 188 | OPEN_ITEMUI = 0x127 189 | # 190 | 191 | CLOSE_ITEMUI = 0xE2FF 192 | USE_ITEMUI = 0xE3FF 193 | MTS_OP = 0xF1FF 194 | 195 | # +11 196 | USE_HAMMER = 0x133 197 | USE_MAPLELIFE = 0x142 198 | # -------------------------------------------------------------------------------- /src/org/snow/odinms/StringUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the OdinMS Maple Story Server 3 | Copyright (C) 2008 Patrick Huy 4 | Matthias Butz 5 | Jan Christian Meyer 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU Affero General Public License version 3 9 | as published by the Free Software Foundation. You may not use, modify 10 | or distribute this program under any other version of the 11 | GNU Affero General Public License. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU Affero General Public License for more details. 17 | 18 | You should have received a copy of the GNU Affero General Public License 19 | along with this program. If not, see . 20 | */ 21 | 22 | package org.snow.odinms; 23 | 24 | /** 25 | * Provides a suite of utilities for manipulating strings. 26 | * 27 | * @author Frz 28 | * @since Revision 336 29 | * @version 1.0 30 | * 31 | */ 32 | public class StringUtil { 33 | /** 34 | * Gets a string padded from the left to length by 35 | * padchar. 36 | * 37 | * @param in The input string to be padded. 38 | * @param padchar The character to pad with. 39 | * @param length The length to pad to. 40 | * @return The padded string. 41 | */ 42 | public static String getLeftPaddedStr(String in, char padchar, int length) { 43 | StringBuilder builder = new StringBuilder(length); 44 | for (int x = in.length(); x < length; x++) { 45 | builder.append(padchar); 46 | } 47 | builder.append(in); 48 | return builder.toString(); 49 | } 50 | 51 | /** 52 | * Gets a string padded from the right to length by 53 | * padchar. 54 | * 55 | * @param in The input string to be padded. 56 | * @param padchar The character to pad with. 57 | * @param length The length to pad to. 58 | * @return The padded string. 59 | */ 60 | public static String getRightPaddedStr(String in, char padchar, int length) { 61 | StringBuilder builder = new StringBuilder(in); 62 | for (int x = in.length(); x < length; x++) { 63 | builder.append(padchar); 64 | } 65 | return builder.toString(); 66 | } 67 | 68 | /** 69 | * Joins an array of strings starting from string start with 70 | * a space. 71 | * 72 | * @param arr The array of strings to join. 73 | * @param start Starting from which string. 74 | * @return The joined strings. 75 | */ 76 | public static String joinStringFrom(String arr[], int start) { 77 | return joinStringFrom(arr, start, " "); 78 | } 79 | 80 | /** 81 | * Joins an array of strings starting from string start with 82 | * sep as a seperator. 83 | * 84 | * @param arr The array of strings to join. 85 | * @param start Starting from which string. 86 | * @return The joined strings. 87 | */ 88 | public static String joinStringFrom(String arr[], int start, String sep) { 89 | StringBuilder builder = new StringBuilder(); 90 | for (int i = start; i < arr.length; i++) { 91 | builder.append(arr[i]); 92 | if (i != arr.length - 1) { 93 | builder.append(sep); 94 | } 95 | } 96 | return builder.toString(); 97 | } 98 | 99 | /** 100 | * Makes an enum name human readable (fixes spaces, capitalization, etc) 101 | * 102 | * @param enumName The name of the enum to neaten up. 103 | * @return The human-readable enum name. 104 | */ 105 | public static String makeEnumHumanReadable(String enumName) { 106 | StringBuilder builder = new StringBuilder(enumName.length() + 1); 107 | String[] words = enumName.split("_"); 108 | for (String word : words) { 109 | if (word.length() <= 2) { 110 | builder.append(word); // assume that it's an abbrevation 111 | } else { 112 | builder.append(word.charAt(0)); 113 | builder.append(word.substring(1).toLowerCase()); 114 | } 115 | builder.append(' '); 116 | } 117 | return builder.substring(0, enumName.length()); 118 | } 119 | 120 | /** 121 | * Counts the number of chr's in str. 122 | * 123 | * @param s The string to check for instances of chr. 124 | * @param chr The character to check for. 125 | * @return The number of times chr occurs in str. 126 | */ 127 | public static int countCharacters(String s, char chr) { 128 | int ret = 0; 129 | for(char sChr : s.toCharArray()) { 130 | if (sChr == chr) { 131 | ret++; 132 | } 133 | } 134 | return ret; 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /src/org/snow/odinms/BitTools.java: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the OdinMS Maple Story Server 3 | Copyright (C) 2008 Patrick Huy 4 | Matthias Butz 5 | Jan Christian Meyer 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU Affero General Public License version 3 9 | as published by the Free Software Foundation. You may not use, modify 10 | or distribute this program under any other version of the 11 | GNU Affero General Public License. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU Affero General Public License for more details. 17 | 18 | You should have received a copy of the GNU Affero General Public License 19 | along with this program. If not, see . 20 | */ 21 | 22 | package org.snow.odinms; 23 | 24 | /** 25 | * Provides static methods for working with raw byte sequences. 26 | * 27 | * @author Frz 28 | * @since Revision 206 29 | * @version 1.0 30 | */ 31 | public class BitTools { 32 | /** 33 | * Static class dummy constructor. 34 | */ 35 | private BitTools() { 36 | } 37 | 38 | /** 39 | * Reads a short from array at index 40 | * 41 | * @param array The byte array to read the short integer from. 42 | * @param index Where reading begins. 43 | * @return The short integer value. 44 | */ 45 | public static int getShort(byte array[], int index) { 46 | int ret = array[index]; 47 | ret &= 0xFF; 48 | ret |= ((int) (array[index + 1]) << 8) & 0xFF00; 49 | return ret; 50 | } 51 | 52 | /** 53 | * Reads a string from array at 54 | * index length in length. 55 | * 56 | * @param array The array to read the string from. 57 | * @param index Where reading begins. 58 | * @param length The number of bytes to read. 59 | * @return The string read. 60 | */ 61 | public static String getString(byte array[], int index, int length) { 62 | char[] cret = new char[length]; 63 | for (int x = 0; x < length; x++) { 64 | cret[x] = (char) array[x + index]; 65 | } 66 | return String.valueOf(cret); 67 | } 68 | 69 | /** 70 | * Reads a maplestory-convention string from array at 71 | * index 72 | * 73 | * @param array The byte array to read from. 74 | * @param index Where reading begins. 75 | * @return The string read. 76 | */ 77 | public static String getMapleString(byte array[], int index) { 78 | int length = ((int) (array[index]) & 0xFF) | ((int) (array[index + 1] << 8) & 0xFF00); 79 | return BitTools.getString(array, index + 2, length); 80 | } 81 | 82 | /** 83 | * Rotates the bits of in count places to the 84 | * left. 85 | * 86 | * @param in The byte to rotate the bits 87 | * @param count Number of times to rotate. 88 | * @return The rotated byte. 89 | */ 90 | public static byte rollLeft(byte in, int count) { 91 | /* 92 | * in: 11001101 count: 3 out: 0110 1110 93 | */ 94 | int tmp = (int) in & 0xFF; 95 | tmp = tmp << (count % 8); 96 | return (byte) ((tmp & 0xFF) | (tmp >> 8)); 97 | } 98 | 99 | /** 100 | * Rotates the bits of in count places to the 101 | * right. 102 | * 103 | * @param in The byte to rotate the bits 104 | * @param count Number of times to rotate. 105 | * @return The rotated byte. 106 | */ 107 | public static byte rollRight(byte in, int count) { 108 | /* 109 | * in: 11001101 count: 3 out: 1011 10011 110 | * 111 | * 0000 1011 1011 0000 0101 1000 112 | * 113 | */ 114 | int tmp = (int) in & 0xFF; 115 | tmp = (tmp << 8) >>> (count % 8); 116 | 117 | return (byte) ((tmp & 0xFF) | (tmp >>> 8)); 118 | } 119 | 120 | /** 121 | * Repeats count bytes of in mul times. 122 | * 123 | * @param in The array of bytes containing the bytes to multiply. 124 | * @param count The number of bytes to repeat. 125 | * @param mul The number of times to repeat. 126 | * @return The repeated bytes. 127 | */ 128 | public static byte[] multiplyBytes(byte[] in, int count, int mul) { 129 | byte[] ret = new byte[count * mul]; 130 | for (int x = 0; x < count * mul; x++) { 131 | ret[x] = in[x % count]; 132 | } 133 | return ret; 134 | } 135 | 136 | /** 137 | * Turns a double-precision floating point integer into an integer. 138 | * 139 | * @param d The double to transform. 140 | * @return The converted integer. 141 | */ 142 | public static int doubleToShortBits(double d) { 143 | long l = Double.doubleToLongBits(d); 144 | return (int) (l >> 48); 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /src/org/snow/maplesnowsniffer/MaplePacketStructureViewer.form: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 |
105 | -------------------------------------------------------------------------------- /src/org/snow/odinms/HexTool.java: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the OdinMS Maple Story Server 3 | Copyright (C) 2008 Patrick Huy 4 | Matthias Butz 5 | Jan Christian Meyer 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU Affero General Public License version 3 9 | as published by the Free Software Foundation. You may not use, modify 10 | or distribute this program under any other version of the 11 | GNU Affero General Public License. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU Affero General Public License for more details. 17 | 18 | You should have received a copy of the GNU Affero General Public License 19 | along with this program. If not, see . 20 | */ 21 | 22 | package org.snow.odinms; 23 | 24 | import java.io.ByteArrayOutputStream; 25 | import java.nio.ByteBuffer; 26 | /** 27 | * Provides a class for manipulating hexadecimal numbers. 28 | * 29 | * @author Frz 30 | * @since Revision 206 31 | * @version 1.0 32 | */ 33 | public class HexTool { 34 | static private char[] HEX = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; 35 | 36 | /** 37 | * Static class dummy constructor. 38 | */ 39 | private HexTool() { 40 | } 41 | 42 | /** 43 | * Turns a byte into a hexadecimal string. 44 | * 45 | * @param byteValue The byte to convert. 46 | * @return The hexadecimal representation of byteValue 47 | */ 48 | public static String toString(byte byteValue) { 49 | int tmp = byteValue << 8; 50 | char[] retstr = new char[] { HEX[(tmp >> 12) & 0x0F], HEX[(tmp >> 8) & 0x0F] }; 51 | return String.valueOf(retstr); 52 | } 53 | 54 | /** 55 | * Turns a org.apache.mina.common.ByteBuffer into a 56 | * hexadecimal string. 57 | * 58 | * @param buf The org.apache.mina.common.ByteBuffer to 59 | * convert. 60 | * @return The hexadecimal representation of buf 61 | */ 62 | public static String toString(ByteBuffer buf) { 63 | buf.flip(); 64 | byte arr[] = new byte[buf.remaining()]; 65 | buf.get(arr); 66 | String ret = toString(arr); 67 | buf.flip(); 68 | buf.put(arr); 69 | return ret; 70 | } 71 | 72 | /** 73 | * Turns an integer into a hexadecimal string. 74 | * 75 | * @param intValue The integer to transform. 76 | * @return The hexadecimal representation of intValue. 77 | */ 78 | public static String toString(int intValue) { 79 | return Integer.toHexString(intValue); 80 | } 81 | 82 | /** 83 | * Turns an array of bytes into a hexadecimal string. 84 | * 85 | * @param bytes The bytes to convert. 86 | * @return The hexadecimal representation of bytes 87 | */ 88 | public static String toString(byte[] bytes) { 89 | if (bytes == null || bytes.length < 1) { 90 | return ""; 91 | } 92 | StringBuilder hexed = new StringBuilder(); 93 | for (int i = 0; i < bytes.length; i++) { 94 | hexed.append(toString(bytes[i])); 95 | hexed.append(' '); 96 | } 97 | return hexed.substring(0, hexed.length() - 1); 98 | } 99 | 100 | /** 101 | * Turns an array of bytes into a ASCII string. Any non-printable characters 102 | * are replaced by a period (.) 103 | * 104 | * @param bytes The bytes to convert. 105 | * @return The ASCII hexadecimal representation of bytes 106 | */ 107 | public static String toStringFromAscii(byte[] bytes) { 108 | char[] ret = new char[bytes.length]; 109 | for (int x = 0; x < bytes.length; x++) { 110 | if (bytes[x] < 32 && bytes[x] >= 0) { 111 | ret[x] = '.'; 112 | } else { 113 | int chr = ((short) bytes[x]) & 0xFF; 114 | ret[x] = (char) chr; 115 | } 116 | } 117 | return String.valueOf(ret); 118 | } 119 | 120 | public static String toPaddedStringFromAscii(byte[] bytes) { 121 | String str = toStringFromAscii(bytes); 122 | StringBuilder ret = new StringBuilder(str.length() * 3); 123 | for (int i = 0; i < str.length(); i++) { 124 | ret.append(str.charAt(i)); 125 | ret.append(" "); 126 | } 127 | return ret.toString(); 128 | } 129 | 130 | /** 131 | * Turns an hexadecimal string into a byte array. 132 | * 133 | * @param hex The string to convert. 134 | * @return The byte array representation of hex 135 | */ 136 | public static byte[] getByteArrayFromHexString(String hex) { 137 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 138 | int nexti = 0; 139 | int nextb = 0; 140 | boolean highoc = true; 141 | outer: for (;;) { 142 | int number = -1; 143 | while (number == -1) { 144 | if (nexti == hex.length()) { 145 | break outer; 146 | } 147 | char chr = hex.charAt(nexti); 148 | if (chr >= '0' && chr <= '9') { 149 | number = chr - '0'; 150 | } else if (chr >= 'a' && chr <= 'f') { 151 | number = chr - 'a' + 10; 152 | } else if (chr >= 'A' && chr <= 'F') { 153 | number = chr - 'A' + 10; 154 | } else { 155 | number = -1; 156 | } 157 | nexti++; 158 | } 159 | if (highoc) { 160 | nextb = number << 4; 161 | highoc = false; 162 | } else { 163 | nextb |= number; 164 | highoc = true; 165 | baos.write(nextb); 166 | } 167 | } 168 | return baos.toByteArray(); 169 | } 170 | 171 | public static String getIpStringFromBytes(byte[] bytes) { 172 | if (bytes.length != 4) { 173 | return null; 174 | } 175 | String ip = ""; 176 | int segment = 1; 177 | for(byte b : bytes) { 178 | ip += (b & 0xFF); 179 | if (segment != 4) { 180 | ip += "."; 181 | } 182 | segment++; 183 | } 184 | return ip; 185 | } 186 | 187 | public static byte[] xorBytes(byte[] a, byte[] b) { 188 | byte[] retbytes = new byte[a.length]; 189 | for (int i = 0; i < a.length; i++) { 190 | retbytes[i] = (byte) (a[i] ^ b[i]); 191 | } 192 | return retbytes; 193 | } 194 | 195 | public static String getOpcodeToString(short op) { 196 | String ret = "0x"; 197 | ret += StringUtil.getLeftPaddedStr(Integer.toHexString(op).toUpperCase(), '0', 4); 198 | return ret; 199 | } 200 | } 201 | -------------------------------------------------------------------------------- /src/org/snow/maplesnowsniffer/EditOpcode.form: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 |
118 | -------------------------------------------------------------------------------- /src/org/snow/maplesnowsniffer/MaplePacketRecord.java: -------------------------------------------------------------------------------- 1 | package org.snow.maplesnowsniffer; 2 | 3 | import java.text.SimpleDateFormat; 4 | import java.util.ArrayList; 5 | import java.util.Date; 6 | import java.util.List; 7 | import javax.swing.tree.DefaultMutableTreeNode; 8 | import javax.swing.tree.DefaultTreeModel; 9 | import javax.swing.tree.TreeModel; 10 | import org.jnetpcap.packet.PcapPacket; 11 | import org.snow.odinms.HexTool; 12 | import org.snow.odinms.StringUtil; 13 | 14 | /** 15 | * 16 | * @author Raz 17 | */ 18 | public class MaplePacketRecord { 19 | 20 | private int id; 21 | private PcapPacket packet; 22 | private long counter; 23 | private Date time; 24 | private String direction; 25 | private String header; 26 | private int opcode; 27 | private byte[] packetData; 28 | private String[] treeData; 29 | private boolean send; 30 | private boolean dataRecord = true; 31 | private boolean loadFromFile = false; 32 | protected static long count = 0; 33 | protected static List records = new ArrayList(); 34 | 35 | public MaplePacketRecord() { 36 | this.id = records.size(); 37 | records.add(this); 38 | } 39 | 40 | public static List getRecords() { 41 | return records; 42 | } 43 | 44 | public static MaplePacketRecord getById(int id) { 45 | return records.get(id); 46 | } 47 | 48 | public static void setRecords(List records) { 49 | MaplePacketRecord.records = records; 50 | } 51 | 52 | public int getId() { 53 | return id; 54 | } 55 | 56 | public void setId(int id) { 57 | this.id = id; 58 | } 59 | 60 | public static long getCountAndAdd() { 61 | count++; 62 | return count; 63 | } 64 | 65 | public static void setCount(int newCount) { 66 | count = newCount; 67 | } 68 | 69 | public long getCounter() { 70 | return counter; 71 | } 72 | 73 | public void setCounter(long counter) { 74 | this.counter = counter; 75 | } 76 | 77 | public String getDirection() { 78 | return direction; 79 | } 80 | 81 | public void setDirection(String direction) { 82 | this.direction = direction; 83 | } 84 | 85 | public String getHeader() { 86 | return header; 87 | } 88 | 89 | public void setHeader(String header) { 90 | this.header = header; 91 | } 92 | 93 | public Date getTime() { 94 | return time; 95 | } 96 | 97 | public void setTime(Date time) { 98 | this.time = time; 99 | } 100 | 101 | public String getTimeToString() { 102 | return new SimpleDateFormat("HH:mm:ss.SSS").format(getTime()); 103 | } 104 | 105 | public byte[] getPacketData() { 106 | return packetData; 107 | } 108 | 109 | public void setPacketData(byte[] packetData) { 110 | this.packetData = packetData; 111 | } 112 | 113 | public PcapPacket getPacket() { 114 | return packet; 115 | } 116 | 117 | public void setPacket(PcapPacket packet) { 118 | this.packet = packet; 119 | } 120 | 121 | public boolean isDataRecord() { 122 | return dataRecord; 123 | } 124 | 125 | public void setDataRecord(boolean dataRecord) { 126 | this.dataRecord = dataRecord; 127 | } 128 | 129 | public int getOpcode() { 130 | return opcode; 131 | } 132 | 133 | public void setOpcode(int opcode) { 134 | this.opcode = opcode; 135 | } 136 | 137 | public String getOpcodeHex(boolean includePrefix) { 138 | return (includePrefix ? "0x" : "") + StringUtil.getLeftPaddedStr(Integer.toHexString(opcode).toUpperCase(), '0', 4); 139 | } 140 | 141 | public boolean isSend() { 142 | return send; 143 | } 144 | 145 | public void setSend(boolean send) { 146 | this.send = send; 147 | } 148 | 149 | public void setLoadFromFile(boolean load) { 150 | this.loadFromFile = load; 151 | } 152 | 153 | public TreeModel getTreeModel() { 154 | DefaultMutableTreeNode root = new DefaultMutableTreeNode("Packet"); 155 | root.add(new DefaultMutableTreeNode("PacketType: TCP")); 156 | root.add(new DefaultMutableTreeNode("Length: " + packetData.length)); 157 | root.add(new DefaultMutableTreeNode("Date: " + getTimeToString())); 158 | root.add(new DefaultMutableTreeNode("Opcode: " + getOpcodeHex(true))); 159 | root.add(new DefaultMutableTreeNode("Header-Desc: " + getHeader())); 160 | /*DefaultMutableTreeNode ipNode = new DefaultMutableTreeNode("Network-Data"); 161 | root.add(ipNode); 162 | if (loadFromFile) { 163 | ipNode.add(new DefaultMutableTreeNode("Src-IP: " + treeData[0].toString().substring(1))); 164 | ipNode.add(new DefaultMutableTreeNode("Src-Port: " + treeData[1])); 165 | ipNode.add(new DefaultMutableTreeNode("Dst-IP: " + treeData[2].toString().substring(1))); 166 | ipNode.add(new DefaultMutableTreeNode("Dst-Port: " + treeData[3])); 167 | ipNode.add(new DefaultMutableTreeNode("Sec: " + treeData[4])); 168 | ipNode.add(new DefaultMutableTreeNode("USec: " + treeData[5])); 169 | } else { 170 | ipNode.add(new DefaultMutableTreeNode("Src-IP: " + getPacket().src_ip.toString().substring(1))); 171 | ipNode.add(new DefaultMutableTreeNode("Src-Port: " + getPacket().src_port)); 172 | ipNode.add(new DefaultMutableTreeNode("Dst-IP: " + getPacket().dst_ip.toString().substring(1))); 173 | ipNode.add(new DefaultMutableTreeNode("Dst-Port: " + getPacket().dst_port)); 174 | ipNode.add(new DefaultMutableTreeNode("Sec: " + getPacket().sec)); 175 | ipNode.add(new DefaultMutableTreeNode("USec: " + getPacket().usec)); 176 | }*/ 177 | return new DefaultTreeModel(root); 178 | } 179 | 180 | public void setTreeData(String[] data) { 181 | this.treeData = data; 182 | } 183 | 184 | public Object[] getRowData() { 185 | Object[] rowData = new Object[6]; 186 | rowData[0] = getCounter(); 187 | rowData[1] = getTimeToString(); 188 | rowData[2] = getDirection(); 189 | rowData[3] = getOpcodeHex(true); 190 | rowData[4] = getHeader(); 191 | rowData[5] = getPacketData().length; 192 | return rowData; 193 | } 194 | 195 | public List getHexRowData() { 196 | List ret = new ArrayList(); 197 | byte[] buffer = getPacketData(); 198 | int offset = 0; 199 | while (buffer.length > 15) { 200 | byte[] rowBuffer = new byte[16]; 201 | System.arraycopy(buffer, offset, rowBuffer, 0, 16); 202 | Object[] row = new Object[3]; 203 | row[0] = StringUtil.getLeftPaddedStr(Integer.toHexString(offset).toUpperCase(), '0', 8); 204 | row[1] = HexTool.toString(rowBuffer); 205 | row[2] = HexTool.toStringFromAscii(rowBuffer); 206 | offset += 16; 207 | } 208 | return ret; 209 | } 210 | } 211 | -------------------------------------------------------------------------------- /src/org/snow/odinms/GenericLittleEndianAccessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the OdinMS Maple Story Server 3 | Copyright (C) 2008 Patrick Huy 4 | Matthias Butz 5 | Jan Christian Meyer 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU Affero General Public License version 3 9 | as published by the Free Software Foundation. You may not use, modify 10 | or distribute this program under any other version of the 11 | GNU Affero General Public License. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU Affero General Public License for more details. 17 | 18 | You should have received a copy of the GNU Affero General Public License 19 | along with this program. If not, see . 20 | */ 21 | 22 | package org.snow.odinms; 23 | 24 | import java.io.ByteArrayOutputStream; 25 | 26 | /** 27 | * Provides a generic interface to a Little Endian stream of bytes. 28 | * 29 | * @version 1.0 30 | * @author Frz 31 | * @since Revision 323 32 | */ 33 | public class GenericLittleEndianAccessor implements LittleEndianAccessor { 34 | private ByteInputStream bs; 35 | 36 | /** 37 | * Class constructor - Wraps the accessor around a stream of bytes. 38 | * 39 | * @param bs The byte stream to wrap the accessor around. 40 | */ 41 | public GenericLittleEndianAccessor(ByteInputStream bs) { 42 | this.bs = bs; 43 | } 44 | 45 | /** 46 | * Read a single byte from the stream. 47 | * 48 | * @return The byte read. 49 | * @see net.sf.odinms.tools.data.input.ByteInputStream#readByte 50 | */ 51 | @Override 52 | public byte readByte() { 53 | return (byte) bs.readByte(); 54 | } 55 | 56 | /** 57 | * Reads an integer from the stream. 58 | * 59 | * @return The integer read. 60 | */ 61 | @Override 62 | public int readInt() { 63 | int byte1, byte2, byte3, byte4; 64 | 65 | byte1 = bs.readByte(); 66 | byte2 = bs.readByte(); 67 | byte3 = bs.readByte(); 68 | byte4 = bs.readByte(); 69 | return (byte4 << 24) + (byte3 << 16) + (byte2 << 8) + byte1; 70 | } 71 | 72 | /** 73 | * Reads a short integer from the stream. 74 | * 75 | * @return The short read. 76 | */ 77 | @Override 78 | public short readShort() { 79 | int byte1, byte2; 80 | byte1 = bs.readByte(); 81 | byte2 = bs.readByte(); 82 | return (short) ((byte2 << 8) + byte1); 83 | } 84 | 85 | /** 86 | * Reads a single character from the stream. 87 | * 88 | * @return The character read. 89 | */ 90 | @Override 91 | public char readChar() { 92 | return (char) readShort(); 93 | } 94 | 95 | /** 96 | * Reads a long integer from the stream. 97 | * 98 | * @return The long integer read. 99 | */ 100 | @Override 101 | public long readLong() { 102 | long byte1 = bs.readByte(); 103 | long byte2 = bs.readByte(); 104 | long byte3 = bs.readByte(); 105 | long byte4 = bs.readByte(); 106 | long byte5 = bs.readByte(); 107 | long byte6 = bs.readByte(); 108 | long byte7 = bs.readByte(); 109 | long byte8 = bs.readByte(); 110 | 111 | return (byte8 << 56) + (byte7 << 48) + (byte6 << 40) + (byte5 << 32) + (byte4 << 24) + (byte3 << 16) + 112 | (byte2 << 8) + byte1; 113 | } 114 | 115 | /** 116 | * Reads a floating point integer from the stream. 117 | * 118 | * @return The float-type integer read. 119 | */ 120 | @Override 121 | public float readFloat() { 122 | return Float.intBitsToFloat(readInt()); 123 | } 124 | 125 | /** 126 | * Reads a double-precision integer from the stream. 127 | * 128 | * @return The double-type integer read. 129 | */ 130 | @Override 131 | public double readDouble() { 132 | return Double.longBitsToDouble(readLong()); 133 | } 134 | 135 | /** 136 | * Reads an ASCII string from the stream with length n. 137 | * 138 | * @param n Number of characters to read. 139 | * @return The string read. 140 | */ 141 | @Override 142 | public final String readAsciiString(int n) { 143 | char ret[] = new char[n]; 144 | for (int x = 0; x < n; x++) { 145 | ret[x] = (char) readByte(); 146 | } 147 | return String.valueOf(ret); 148 | } 149 | 150 | /** 151 | * Reads a null-terminated string from the stream. 152 | * 153 | * @return The string read. 154 | */ 155 | @Override 156 | public final String readNullTerminatedAsciiString() { 157 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 158 | byte b = 1; 159 | while (b != 0) { 160 | b = readByte(); 161 | baos.write(b); 162 | } 163 | byte[] buf = baos.toByteArray(); 164 | char[] chrBuf = new char[buf.length]; 165 | for (int x = 0; x < buf.length; x++) { 166 | chrBuf[x] = (char) buf[x]; 167 | } 168 | return String.valueOf(chrBuf); 169 | } 170 | 171 | /** 172 | * Reads a MapleStory convention lengthed ASCII string. 173 | * This consists of a short integer telling the length of the string, 174 | * then the string itself. 175 | * 176 | * @return The string read. 177 | */ 178 | @Override 179 | public String readMapleAsciiString() { 180 | return readAsciiString(readShort()); 181 | } 182 | 183 | /** 184 | * Reads num bytes off the stream. 185 | * 186 | * @param num The number of bytes to read. 187 | * @return An array of bytes with the length of num 188 | */ 189 | @Override 190 | public byte[] read(int num) { 191 | byte[] ret = new byte[num]; 192 | for (int x = 0; x < num; x++) { 193 | ret[x] = readByte(); 194 | } 195 | return ret; 196 | } 197 | 198 | /** 199 | * Gets the number of bytes read from the stream so far. 200 | * 201 | * @return A long integer representing the number of bytes read. 202 | * @see net.sf.odinms.tools.data.input.ByteInputStream#getBytesRead() 203 | */ 204 | @Override 205 | public long getBytesRead() { 206 | return bs.getBytesRead(); 207 | } 208 | 209 | /** 210 | * Skips the current position of the stream num bytes ahead. 211 | * 212 | * @param num Number of bytes to skip. 213 | */ 214 | @Override 215 | public void skip(int num) { 216 | for (int x = 0; x < num; x++) { 217 | readByte(); 218 | } 219 | } 220 | 221 | /** 222 | * @see net.sf.odinms.tools.data.input.ByteInputStream#available 223 | */ 224 | @Override 225 | public long available() { 226 | return bs.available(); 227 | } 228 | 229 | /** 230 | * @see java.lang.Object#toString 231 | */ 232 | @Override 233 | public String toString() { 234 | return bs.toString(); 235 | } 236 | } 237 | -------------------------------------------------------------------------------- /src/org/snow/odinms/RecvPacketOpcode.java: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the OdinMS Maple Story Server 3 | Copyright (C) 2008 Patrick Huy 4 | Matthias Butz 5 | Jan Christian Meyer 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU Affero General Public License version 3 9 | as published by the Free Software Foundation. You may not use, modify 10 | or distribute this program under any other version of the 11 | GNU Affero General Public License. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU Affero General Public License for more details. 17 | 18 | You should have received a copy of the GNU Affero General Public License 19 | along with this program. If not, see . 20 | */ 21 | 22 | package org.snow.odinms; 23 | 24 | import java.io.FileInputStream; 25 | import java.io.FileNotFoundException; 26 | import java.io.IOException; 27 | import java.util.Properties; 28 | 29 | public enum RecvPacketOpcode implements WritableIntValueHolder { 30 | LOGIN_PASSWORD,//0x01 31 | GUEST_LOGIN,//0x02 32 | SERVERLIST_REREQUEST,//0x04 33 | CHARLIST_REQUEST,//0x05 34 | SERVERSTATUS_REQUEST,//0x06 35 | SET_GENDER,//0x08 36 | AFTER_LOGIN,//0x09 37 | REGISTER_PIN,//0x0A 38 | SERVERLIST_REQUEST,//0x0B 39 | PLAYER_DC,//0xC0 40 | VIEW_ALL_CHAR,//0x0D 41 | PICK_ALL_CHAR,//0x0E 42 | CHAR_SELECT,//0x13 43 | PLAYER_LOGGEDIN,//0x14 44 | CHECK_CHAR_NAME,//0x15 45 | PIC_ASSIGNED, //0x1E 46 | CREATE_CHAR,//0x16 47 | CREATE_CYGNUS,//0x17 48 | DELETE_CHAR,//0x18 49 | PONG,//0x19 50 | ERROR,//0x1A 51 | CLIENT_START,//0x1A 52 | CLIENT_ERROR,//0x1B 53 | STRANGE_DATA,//0x1C 54 | RELOG,//0x1D 55 | PACKET_ERROR, 56 | CHANGE_MAP,//0x25 57 | CHANGE_CHANNEL,//0x26 58 | ENTER_CASH_SHOP,//0x27 59 | MOVE_PLAYER,//0x28 60 | CANCEL_CHAIR,//0x29 61 | USE_CHAIR,//0x2A 62 | CLOSE_RANGE_ATTACK,//0x2B 63 | RANGED_ATTACK,//0x2C 64 | MAGIC_ATTACK,//0x2D 65 | ENERGY_ORB_ATTACK,//0x2E 66 | TAKE_DAMAGE,//0x2F 67 | GENERAL_CHAT,//0x30 68 | CLOSE_CHALKBOARD,//0x31 69 | FACE_EXPRESSION,//0x32 70 | USE_ITEMEFFECT,//0x33 71 | USE_DEATHITEM,//0x34 72 | MONSTER_BOOK_COVER,//0x38 73 | NPC_TALK,//0x39 74 | NPC_TALK_MORE,//0x3B 75 | NPC_SHOP,//0x3C 76 | STORAGE,//0x3D 77 | HIRED_MERCHANT_REQUEST,//0x3E 78 | DUEY_ACTION,//0x40 79 | ITEM_SORT,//0x44 80 | ITEM_SORT2,//0x45 81 | ITEM_MOVE,//0x46 82 | USE_ITEM,//0x47 83 | CANCEL_ITEM_EFFECT,//0x48 84 | USE_SUMMON_BAG,//0x4A 85 | USE_PET_FOOD,//0x4B 86 | USE_MOUNT_FOOD,//0x4C 87 | USE_SCRIPTED_ITEM,//0x4D 88 | USE_CASH_ITEM,//0x4E 89 | USE_CATCH_ITEM,//0x50 90 | USE_SKILL_BOOK,//0x51 91 | USE_TELEPORT_ROCK,//0x53 92 | USE_RETURN_SCROLL,//0x54 93 | USE_UPGRADE_SCROLL,//0x55 94 | DISTRIBUTE_AP,//0x56 95 | AUTO_DISTRIBUTE_AP,//0x57 96 | HEAL_OVER_TIME,//0x58 97 | DISTRIBUTE_SP,//0x59 98 | SPECIAL_MOVE,//0x5A 99 | CANCEL_BUFF,//0x5B 100 | SKILL_EFFECT,//0x5C 101 | MESO_DROP,//0x5D 102 | GIVE_FAME,//0x5E 103 | CHAR_INFO_REQUEST,//0x60 104 | SPAWN_PET,//0x61 105 | CANCEL_DEBUFF,//0x62 106 | CHANGE_MAP_SPECIAL,//0x63 107 | USE_INNER_PORTAL,//0x64 108 | TROCK_ADD_MAP,//0x65 109 | REPORT,//0x69 110 | QUEST_ACTION,//0x6A 111 | SKILL_MACRO,//0x6D 112 | SPOUSE_CHAT,//0x6E 113 | USE_FISHING_ITEM,//0x6F 114 | MAKER_SKILL,//0x70 115 | USE_REMOTE,//0x73 116 | PARTYCHAT,//0x75 117 | WHISPER,//0x76 118 | MESSENGER,//0x78 119 | PLAYER_INTERACTION,//0x79 120 | PARTY_OPERATION,//0x7A 121 | DENY_PARTY_REQUEST,//0x7B 122 | GUILD_OPERATION,//0x7C 123 | DENY_GUILD_REQUEST,//0x7D 124 | ADMIN_COMMAND,//0x7E 125 | ADMIN_LOG,//0x7F 126 | BUDDYLIST_MODIFY,//0x80 127 | NOTE_ACTION,//0x81 128 | USE_DOOR,//0x83 129 | CHANGE_KEYMAP,//0x85 130 | RING_ACTION,//0x87 #not sure 131 | OPEN_FAMILY,//0x90 132 | ADD_FAMILY,//0x91 133 | ACCEPT_FAMILY,//0x94 134 | USE_FAMILY,//0x95 135 | ALLIANCE_OPERATION,//0x96 136 | BBS_OPERATION,//0x99 137 | ENTER_MTS,//0x9A 138 | PET_TALK,//0x9B 139 | USE_SOLOMON_ITEM,//0x9C 140 | MOVE_PET,//0xA1 141 | PET_CHAT,//0xA2 142 | PET_COMMAND,//0xA3 143 | PET_LOOT,//0xA4 144 | PET_AUTO_POT,//0xA5 145 | PET_EXCLUDE_ITEMS,//0xA6 146 | MOVE_SUMMON,//0xA9 147 | MOVE_DRAGON,//0xA9 148 | SUMMON_ATTACK,//0xAA 149 | DAMAGE_SUMMON,//0xAB 150 | BEHOLDER,//0xAC 151 | MOVE_LIFE,//0xB2 152 | AUTO_AGGRO,//0xB3 153 | MOB_DAMAGE_MOB_FRIENDLY,//0xB6 154 | MONSTER_BOMB,//0xB7 155 | MOB_DAMAGE_MOB,//0xB8 156 | NPC_ACTION,//0xBB 157 | ITEM_PICKUP,//0xC0 158 | DAMAGE_REACTOR,//0xC3 159 | TOUCHING_REACTOR,//0xC4 160 | MONSTER_CARNIVAL,//0xCE 161 | PARTY_SEARCH_REGISTER,//0xD2 162 | PARTY_SEARCH_START,//0xD4 163 | MAPLETV,//0x222 164 | PLAYER_UPDATE,//0xD5 165 | TOUCHING_CS,//0xDA 166 | BUY_CS_ITEM,//0xDB 167 | COUPON_CODE,//0xDC #not sure 168 | OPEN_ITEMUI,//0xE1 169 | CLOSE_ITEMUI,//0xE2 170 | USE_ITEMUI,//0xE3 171 | MTS_OP,//0xF1 172 | USE_MAPLELIFE,//0xF4 173 | USE_HAMMER,//0xF8 174 | USE_MAGNIFING_GLASS, // 0x60 175 | USE_ENHANCEMENT_SCROLL, // 0x5E 176 | USE_POTENTIAL_SCROLL, 177 | UNKNOWN; 178 | private int code = -2; 179 | 180 | public void setValue(int code) { 181 | this.code = code; 182 | } 183 | 184 | @Override 185 | public int getValue() { 186 | return code; 187 | } 188 | 189 | public static Properties getDefaultProperties() throws FileNotFoundException, IOException { 190 | Properties props = new Properties(); 191 | FileInputStream fis = new FileInputStream(System.getProperty("net.sf.odinms.recvops")); 192 | props.load(fis); 193 | fis.close(); 194 | return props; 195 | } 196 | 197 | public static RecvPacketOpcode getByType(int type) { 198 | for (RecvPacketOpcode l : RecvPacketOpcode.values()) { 199 | if (l.getValue() == type) { 200 | return l; 201 | } 202 | } 203 | return UNKNOWN; 204 | } 205 | 206 | public static RecvPacketOpcode getByName(String name) { 207 | for (RecvPacketOpcode l : RecvPacketOpcode.values()) { 208 | if (l.name().equalsIgnoreCase(name)) { 209 | return l; 210 | } 211 | } 212 | return UNKNOWN; 213 | } 214 | 215 | 216 | static { 217 | try { 218 | ExternalCodeTableGetter.populateValues(getDefaultProperties(), values()); 219 | } catch (IOException e) { 220 | throw new RuntimeException("Failed to load recvops", e); 221 | } 222 | } 223 | } 224 | -------------------------------------------------------------------------------- /src/org/snow/maplesnowsniffer/MakeLang.form: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 |
137 | -------------------------------------------------------------------------------- /sendops.properties: -------------------------------------------------------------------------------- 1 | 2 | # GENERAL # 3 | PING = 0x11 4 | TESTING_PACKET = 0x0A 5 | 6 | # LOGIN # 7 | LOGIN_STATUS = 0x00 8 | SEND_LINK = 0x01 9 | LOGIN_COOKIE = 0x02 10 | SERVERSTATUS = 0x03 11 | GENDER_DONE = 0x04 12 | TOS = 0x05 13 | PIN_OPERATION = 0x06 14 | PIN_ASSIGNED = 0x07 15 | ALL_CHARLIST = 0x08 16 | SERVERLIST = 0x0A 17 | CHARLIST = 0x0B 18 | SERVER_IP = 0x0C 19 | CHAR_NAME_RESPONSE = 0x0D 20 | ADD_NEW_CHAR_ENTRY = 0x0E 21 | DELETE_CHAR_RESPONSE = 0x0F 22 | CHANGE_CHANNEL = 0x10 23 | ENABLE_CS_0 = 0x12 24 | CHANNEL_SELECTED = 0x14 25 | RELOG_RESPONSE = 0x16 26 | ENABLE_RECOMMENDED = 0x18 27 | SEND_RECOMMENDED = 0x19 28 | WRONG_PIC = 0x1A 29 | 30 | # CHANNEL # 31 | MODIFY_INVENTORY_ITEM = 0x1C 32 | UPDATE_INVENTORY_SLOTS = 0x1D 33 | UPDATE_STATS = 0x1E 34 | GIVE_BUFF = 0x1F 35 | CANCEL_BUFF = 0x20 36 | LOGIN_RESPONSE = 0x22 37 | UPDATE_SKILLS = 0x23 38 | FAME_RESPONSE = 0x25 39 | SHOW_STATUS_INFO = 0x26 40 | NEXON_SITE = 0x27 41 | SHOW_NOTES = 0x28 42 | TROCK_LOCATIONS = 0x29 43 | LIE_DETECTOR = 0x2A 44 | REPORT_RESPONSE = 0x2B 45 | ENABLE_REPORT = 0x2E 46 | MAP_MESSAGE = 0x7F 47 | UPDATE_MOUNT = 0x30 48 | SEND_TITLE_BOX = 0x31 49 | SHOW_QUEST_COMPLETION = 0x32 50 | USE_SKILL_BOOK = 0x34 51 | SHOW_EQUIP_EFFECT = 0x35 52 | FINISH_SORT = 0x35 53 | FINISH_SORT2 = 0x36 54 | REPORTREPLY = 0x38 55 | MESO_LIMIT = 0x39 56 | GENDER = 0x3A 57 | BBS_OPERATION = 0x3B 58 | CHAR_INFO = 0x3D 59 | PARTY_OPERATION = 0x3E 60 | BUDDYLIST = 0x41 61 | GUILD_OPERATION = 0x43 62 | ALLIANCE_OPERATION = 0x44 63 | SPAWN_PORTAL = 0x46 64 | SERVERMESSAGE = 0x47 65 | PIGMI_REWARD = 0x48 66 | OWL_OF_MINERVA = 0x4A 67 | OWL_OF_MINERVA_SELECT = 0x4B 68 | WEDDING_ACTION = 0x4C 69 | WEDDING_PROPOSAL = 0x4D 70 | WEDDING_MESSAGE = 0x4E 71 | YELLOW_TIP = 0x51 72 | PLAYER_NPC = 0x54 73 | CATCH_MESSAGE = 0x55 74 | MONSTERBOOK_ADD = 0x57 75 | MONSTER_BOOK_CHANGE_COVER = 0x58 76 | ENERGY = 0x5E 77 | SHOW_PEDIGREE = 0x5F 78 | #BAMBOO_USED = 0x5C 79 | #OPEN_FAMILY = 0x5C 80 | #FAMILY_MESSAGE = 0x5D 81 | #FAMILY_INVITE = 0x5E 82 | #FAMILY_MESSAGE2 = 0x5F 83 | #FAMILY_SENIOR_MESSAGE = 0x5C 84 | #FAMILY_GAIN_REP = 0x5E 85 | #LOAD_FAMILY = 0x69 86 | #PLAYER_LEVEL = 0x63 87 | #FAMILY_USE_REQUEST = 0x61 88 | #BLANK_MESSAGE = 0x65 89 | 90 | # + 0 91 | AVATAR_MEGA = 0x73 92 | REMOVE_TIGER = 0x74 93 | NAME_CHANGE_MESSAGE = 0x75 94 | NAME_CHANGE_2 = 0x76 95 | UNKNOWN_MESSAGE = 0x77 96 | GM_POLICE = 0x78 97 | SILVER_BOX_OPEN = 0x79 98 | NAME_CANCEL_WITHOUT_REQUEST = 0x7C 99 | INVENTORY_MESSAGE = 0x83 100 | UPDATE_JAGUAR = 0x84 101 | 102 | # + 2 103 | FISHING_CAUGHT = 0x8A 104 | PAMS_SONG = 0x8B 105 | CREATE_ULTIMATE = 0x8C 106 | SKILL_MACRO = 0x8E 107 | WARP_TO_MAP = 0x8F 108 | MTS_OPEN = 0x90 109 | CS_OPEN = 0x91 110 | RESET_SCREEN = 0x95 111 | CS_BLOCKED = 0x96 112 | FORCED_MAP_EQUIP = 0x97 113 | MULTICHAT = 0x98 114 | WHISPER = 0x99 115 | SPOUSE_CHAT = 0x9B 116 | MESSAGE_CANNOT_USE = 0x9B 117 | BOSS_ENV = 0x9C 118 | BLOCK_PORTAL = 0x9D 119 | BLOCK_PORTAL_SHOP = 0x9E 120 | COCONUT_EVENT_ENTER = 0x9F 121 | MAP_EFFECT = 0xA0 122 | HPQ_MOON = 0xA1 123 | GM_PACKET = 0xA2 124 | OX_QUIZ = 0xA3 125 | GMEVENT_INSTRUCTIONS = 0xA4 126 | CLOCK = 0xA5 127 | STOP_CLOCK = 0xA6 128 | BOAT_EFFECT = 0xA7 129 | GM_WARNING = 0xA8 130 | # 131 | 132 | #ARIANT_SCOREBOARD = 0x96 133 | #QUICK_SLOT_CHANGE = 0x9F 134 | 135 | # +3 136 | SPAWN_PLAYER = 0xB6 137 | REMOVE_PLAYER_FROM_MAP = 0xB7 138 | CHATTEXT = 0xB8 139 | CHATTEXT2 = 0xB9 140 | CHALKBOARD = 0xBA 141 | UPDATE_CHAR_BOX = 0xBB 142 | SHOW_SCROLL_EFFECT = 0xBD 143 | SHOW_ENHANCEMENT_EFFECT = 0xBE 144 | SHOW_POTENTIAL_EFFECT = 0xBF 145 | SHOW_MAGNIFYING_EFFECT = 0xC0 146 | SHOW_CUBE_EFFECT = 0xC1 147 | SHOW_TREASUREBOX_SELECT = 0xC6 148 | PAMS_SONG2 = 0xC9 149 | # 150 | 151 | # +4 152 | SPAWN_PET = 0xCA 153 | MOVE_PET = 0xCD 154 | PET_CHAT = 0xCE 155 | PET_NAMECHANGE = 0xCF 156 | PET_SHOW = 0xD0 157 | PET_COMMAND = 0xD1 158 | SPAWN_DRAGON = 0xD2 159 | MOVE_DRAGON = 0xD3 160 | REMOVE_DRAGON = 0xD4 161 | MOVE_PLAYER = 0xD6 162 | CLOSE_RANGE_ATTACK = 0xD7 163 | RANGED_ATTACK = 0xD8 164 | MAGIC_ATTACK = 0xD9 165 | SKILL_EFFECT = 0xDB 166 | CANCEL_SKILL_EFFECT = 0xDC 167 | DAMAGE_PLAYER = 0xDE 168 | FACIAL_EXPRESSION = 0xDF 169 | SHOW_ITEM_EFFECT = 0xE0 170 | SHOW_CHAIR = 0xE2 171 | UPDATE_CHAR_LOOK = 0xE3 172 | SHOW_FOREIGN_EFFECT = 0xE4 173 | GIVE_FOREIGN_BUFF = 0xE5 174 | CANCEL_FOREIGN_BUFF = 0xE6 175 | UPDATE_PARTYMEMBER_HP = 0xE7 176 | CHAR_GUILD_NAME = 0xE8 177 | CHAR_GUILD_INFO = 0xE9 178 | BOMB_EXPLOSION = 0xEA 179 | # 180 | 181 | # +5 182 | CANCEL_CHAIR = 0xEC 183 | SHOW_ITEM_GAIN_INCHAT = 0xEE 184 | DOJO_WARP_UP = 0xEF 185 | UPDATE_QUEST_INFO = 0xF0 186 | LUCKSACK_PASS = 0xF1 187 | LUCKSACK_FAIL = 0xF2 188 | MESO_BAG_MESSAGE = 0xF3 189 | LUCKSACK_EMPTY = 0xF4 190 | PLAYER_HINT = 0xFA 191 | # 192 | 193 | SOUND = 0xD8 194 | #KOREAN_EVENT = 0xDB 195 | #CYGNUS_INTRO_LOCK = 0xDD 196 | #CYGNUS_INTRO_DISABLE_UI = 0xDE 197 | CYGNUS_CHAR_CREATED = 0xCC 198 | FAMILY_ACTION = 0x45 199 | #TUTORIAL_INTRO_LOCK(0xDD), 200 | #TUTORIAL_INTRO_DISABLE_UI(0xDE), 201 | #TUTORIAL_SUMMON(0xDF), 202 | #TUTORIAL_GUIDE(0xE0), 203 | 204 | # +5 205 | CATCH_MONSTER = 0x105 206 | ARAN_COMBO_COUNTER = 0x106 207 | 208 | # 209 | 210 | # + 11 211 | ULTIMATE_MESSAGE = 0x11A 212 | COOLDOWN = 0x11F 213 | SPAWN_SPECIAL_MAPOBJECT = 0x121 214 | REMOVE_SPECIAL_MAPOBJECT = 0x122 215 | MOVE_SUMMON = 0x123 216 | SUMMON_ATTACK = 0x124 217 | DAMAGE_SUMMON = 0x125 218 | SUMMON_SKILL = 0x126 219 | SPAWN_MONSTER = 0x127 220 | KILL_MONSTER = 0x128 221 | SPAWN_MONSTER_CONTROL = 0x129 222 | MOVE_MONSTER = 0x12A 223 | MOVE_MONSTER_RESPONSE = 0x12B 224 | APPLY_MONSTER_STATUS = 0x12D 225 | CANCEL_MONSTER_STATUS = 0x12E 226 | DAMAGE_MONSTER = 0x131 227 | SHOW_MONSTER_HP = 0x135 228 | CATCH_MOUNT = 0x136 229 | CATCH_ARIANT = 0x137 230 | BOSS_YELLOW_TEXT = 0x138 231 | SHOW_MAGNET = 0x13A 232 | # 233 | 234 | # + 12 235 | SPAWN_NPC = 0x143 236 | REMOVE_NPC = 0x144 237 | SPAWN_NPC_REQUEST_CONTROLLER = 0x145 238 | NPC_ACTION = 0x146 239 | NPC_SPECIAL_ANIMATION = 0x147 240 | OBJECT_SPAWN = 0x148 241 | NPC_SPAWN = 0x149 242 | SPAWN_HIRED_MERCHANT = 0x14B 243 | DESTROY_HIRED_MERCHANT = 0x14C 244 | UPDATE_HIRED_MERCHANT = 0x14D 245 | DROP_ITEM_FROM_MAPOBJECT = 0x14E 246 | REMOVE_ITEM_FROM_MAP = 0x150 247 | KITE_MESSAGE = 0x151 248 | KITE = 0x152 249 | 250 | SPAWN_MIST = 0x154 251 | REMOVE_MIST = 0x155 252 | SPAWN_DOOR = 0x156 253 | REMOVE_DOOR = 0x157 254 | REACTOR_HIT = 0x15A 255 | REACTOR_SPAWN = 0x15C 256 | REACTOR_DESTROY = 0x15D 257 | # 258 | 259 | ROLL_SNOWBALL = 0x15E 260 | HIT_SNOWBALL = 0x15F 261 | SNOWBALL_MESSAGE = 0x160 262 | LEFT_KNOCK_BACK = 0x161 263 | UNABLE_TO_CONNECT = 0x166 264 | MONSTER_CARNIVAL_START = 0x168 265 | MONSTER_CARNIVAL_OBTAINED_CP = 0x169 266 | MONSTER_CARNIVAL_PARTY_CP = 0x16A 267 | MONSTER_CARNIVAL_SUMMON = 0x16B 268 | MONSTER_CARNIVAL_DIED = 0x16D 269 | SHOW_SCORE = 0x16E 270 | MONSTER_CARNIVAL_PLAYER_CP = 0x16F 271 | HT_SPAWN = 0x170 272 | ARIANT_PQ_START = 0x171 273 | 274 | # +20 275 | ZAKUM_SHRINE = 0x174 276 | HORNTAIL_CAVE = 0x175 277 | NPC_TALK = 0x17F 278 | OPEN_NPC_SHOP = 0x180 279 | CONFIRM_SHOP_TRANSACTION = 0x181 280 | OPEN_STORAGE = 0x184 281 | FREDRICK_MESSAGE = 0x185 282 | FREDRICK_OPERATION = 0x186 283 | RPS_GAME = 0x187 284 | MESSENGER = 0x188 285 | PLAYER_INTERACTION = 0x189 286 | CS_UPDATE = 0x193 287 | CS_OPERATION = 0x194 288 | CASH_SHOP_SURPRISE = 0x196 289 | CHARACTER_NAME_CHANGE = 0x198 290 | CHARACTER_TRANSFER = 0x19A 291 | GACHAPON_STAMP = 0x19B 292 | FREE_CASH_ITEM = 0x1A0 293 | KEYMAP = 0x1A2 294 | AUTO_HP_POT = 0x1A3 295 | AUTO_MP_POT = 0x1A4 296 | SEND_TV = 0x1A8 297 | REMOVE_TV = 0x1A9 298 | ENABLE_TV = 0x1AA 299 | MTS_OPERATION2 = 0x1AE 300 | MTS_OPERATION = 0x1AF 301 | MAPLE_LIFE = 0x1B0 302 | MAPLE_LIFE_SUBMIT = 0x1B1 303 | # 304 | 305 | # + 22 306 | VICIOUS_HAMMER = 0x1BF 307 | # 308 | 309 | UNKNOWN_MESSAGE2 = 0x6E 310 | QUICK_SLOT = 0x9F 311 | ARIANT_SCORE = 0xFF 312 | -------------------------------------------------------------------------------- /src/org/snow/odinms/SendPacketOpcode.java: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the OdinMS Maple Story Server 3 | Copyright (C) 2008 Patrick Huy 4 | Matthias Butz 5 | Jan Christian Meyer 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU Affero General Public License version 3 9 | as published by the Free Software Foundation. You may not use, modify 10 | or distribute this program under any other version of the 11 | GNU Affero General Public License. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU Affero General Public License for more details. 17 | 18 | You should have received a copy of the GNU Affero General Public License 19 | along with this program. If not, see . 20 | */ 21 | 22 | package org.snow.odinms; 23 | 24 | import java.io.FileInputStream; 25 | import java.io.FileNotFoundException; 26 | import java.io.IOException; 27 | import java.util.Properties; 28 | 29 | public enum SendPacketOpcode implements WritableIntValueHolder { 30 | LOGIN_STATUS, 31 | SEND_LINK, 32 | SERVERSTATUS, 33 | GENDER_DONE, 34 | TOS, 35 | PIN_OPERATION, 36 | PIN_ASSIGNED, 37 | ALL_CHARLIST, 38 | SERVERLIST, 39 | CHARLIST, 40 | SERVER_IP, 41 | PIC_ASSIGNED, 42 | CHAR_NAME_RESPONSE, 43 | ADD_NEW_CHAR_ENTRY, 44 | DELETE_CHAR_RESPONSE, 45 | CHANGE_CHANNEL, 46 | PING, // v99 47 | CHANNEL_SELECTED, 48 | RELOG_RESPONSE, 49 | ENABLE_RECOMMENDED, 50 | SEND_RECOMMENDED, 51 | MODIFY_INVENTORY_ITEM, 52 | CHARACTER_CREATION_EVENT, 53 | UPDATE_INVENTORY_SLOTS, 54 | UPDATE_STATS, 55 | GIVE_BUFF, 56 | CANCEL_BUFF, 57 | UPDATE_SKILLS, 58 | FAME_RESPONSE, 59 | SHOW_STATUS_INFO, 60 | SHOW_NOTES, 61 | TROCK_LOCATIONS, 62 | LIE_DETECTOR, 63 | REPORT_RESPONSE, 64 | ENABLE_REPORT, 65 | UPDATE_MOUNT, 66 | SHOW_QUEST_COMPLETION, 67 | SEND_TITLE_BOX, 68 | USE_SKILL_BOOK, 69 | SHOW_EQUIP_EFFECT, 70 | FINISH_SORT, 71 | FINISH_SORT2, 72 | REPORTREPLY, 73 | MESO_LIMIT, 74 | GENDER, 75 | BBS_OPERATION, 76 | CHAR_INFO, 77 | PARTY_OPERATION, 78 | EXPEDITION_OPERATION, 79 | BUDDYLIST, 80 | GUILD_OPERATION, 81 | ALLIANCE_OPERATION, 82 | SPAWN_PORTAL, 83 | SERVERMESSAGE, 84 | WEDDING_ACTION, 85 | YELLOW_TIP, 86 | PLAYER_NPC, 87 | MONSTERBOOK_ADD, 88 | MONSTER_BOOK_CHANGE_COVER, 89 | ENERGY, 90 | SHOW_PEDIGREE, 91 | OPEN_FAMILY, 92 | FAMILY_MESSAGE, 93 | FAMILY_INVITE, 94 | FAMILY_JOIN_RESPONSE, 95 | FAMILY_SENIOR_MESSAGE, 96 | LOAD_FAMILY, 97 | FAMILY_GAIN_REP, 98 | FAMILY_USE_REQUEST, 99 | BLANK_MESSAGE, 100 | AVATAR_MEGA, 101 | NAME_CHANGE_MESSAGE, 102 | GM_POLICE, 103 | SILVER_BOX, 104 | SKILL_MACRO, 105 | WARP_TO_MAP, // v99 106 | MTS_OPEN, 107 | CS_OPEN, 108 | RESET_SCREEN, 109 | CS_BLOCKED, 110 | FORCED_MAP_EQUIP, 111 | MULTICHAT, 112 | WHISPER, 113 | SPOUSE_CHAT, 114 | BOSS_ENV, 115 | BLOCK_PORTAL, 116 | BLOCK_PORTAL_SHOP, 117 | MAP_EFFECT, 118 | HPQ_MOON, 119 | GM_PACKET, 120 | OX_QUIZ, 121 | GMEVENT_INSTRUCTIONS, 122 | CLOCK, 123 | BOAT_EFFECT, 124 | STOP_CLOCK, 125 | ARIANT_SCOREBOARD, 126 | QUICK_SLOT, 127 | SPAWN_PLAYER, 128 | REMOVE_PLAYER_FROM_MAP, 129 | CHATTEXT, 130 | CHALKBOARD, 131 | UPDATE_CHAR_BOX, 132 | SHOW_SCROLL_EFFECT,//B4 before 133 | SHOW_ENHANCEMENT_EFFECT, 134 | SHOW_POTENTIAL_EFFECT, 135 | SHOW_MAGNIFYING_EFFECT, 136 | SHOW_CUBE_EFFECT, 137 | SPAWN_PET, 138 | MOVE_PET, 139 | PET_CHAT, 140 | PET_NAMECHANGE, 141 | PET_SHOW, 142 | PET_COMMAND, 143 | SPAWN_SPECIAL_MAPOBJECT, 144 | REMOVE_SPECIAL_MAPOBJECT, 145 | MOVE_SUMMON, 146 | SUMMON_ATTACK, 147 | DAMAGE_SUMMON, 148 | SUMMON_SKILL, 149 | SPAWN_DRAGON, 150 | MOVE_DRAGON, 151 | REMOVE_DRAGON, 152 | MOVE_PLAYER, 153 | CLOSE_RANGE_ATTACK, 154 | RANGED_ATTACK, 155 | MAGIC_ATTACK, 156 | SKILL_EFFECT, 157 | CANCEL_SKILL_EFFECT, 158 | DAMAGE_PLAYER, 159 | FACIAL_EXPRESSION, 160 | SHOW_ITEM_EFFECT, 161 | SHOW_CHAIR, 162 | UPDATE_CHAR_LOOK, 163 | SHOW_FOREIGN_EFFECT, 164 | GIVE_FOREIGN_BUFF, 165 | CANCEL_FOREIGN_BUFF, 166 | UPDATE_PARTYMEMBER_HP, 167 | CANCEL_CHAIR, 168 | SHOW_ITEM_GAIN_INCHAT, 169 | DOJO_WARP_UP, 170 | LUCKSACK_PASS, 171 | LUCKSACK_FAIL, 172 | MESO_BAG_MESSAGE, 173 | UPDATE_QUEST_INFO, 174 | PLAYER_HINT, 175 | KOREAN_EVENT, 176 | TUTORIAL_INTRO_LOCK, 177 | TUTORIAL_INTRO_DISABLE_UI, 178 | ARAN_COMBO_COUNTER, 179 | COOLDOWN, 180 | SPAWN_MONSTER, 181 | KILL_MONSTER, 182 | SPAWN_MONSTER_CONTROL, 183 | MOVE_MONSTER, 184 | MOVE_MONSTER_RESPONSE, 185 | APPLY_MONSTER_STATUS, 186 | CANCEL_MONSTER_STATUS, 187 | DAMAGE_MONSTER, 188 | ARIANT_THING, 189 | SHOW_MONSTER_HP, 190 | SHOW_DRAGGED, 191 | SHOW_MAGNET, 192 | CATCH_MONSTER, 193 | CATCH_ARIANT, 194 | SPAWN_NPC, 195 | REMOVE_NPC, 196 | SPAWN_NPC_REQUEST_CONTROLLER, 197 | NPC_ACTION, 198 | SPAWN_HIRED_MERCHANT, 199 | DESTROY_HIRED_MERCHANT, 200 | UPDATE_HIRED_MERCHANT, 201 | DROP_ITEM_FROM_MAPOBJECT, // used to be 0x14D o_o 202 | REMOVE_ITEM_FROM_MAP, // (always +2 up from DROP_ITEM_FROM_MAPOBJECT) 203 | KITE_MESSAGE, 204 | KITE, 205 | SPAWN_MIST, 206 | REMOVE_MIST, 207 | SPAWN_DOOR, 208 | REMOVE_DOOR, 209 | REACTOR_HIT,//used to be 159 210 | REACTOR_SPAWN,//used to be 15B 211 | REACTOR_DESTROY,//used to be 15C 212 | ROLL_SNOWBALL, 213 | HIT_SNOWBALL, 214 | SNOWBALL_MESSAGE, 215 | LEFT_KNOCK_BACK, 216 | UNABLE_TO_CONNECT, 217 | MONSTER_CARNIVAL_DIED, 218 | MONSTER_CARNIVAL_SUMMON, 219 | MONSTER_CARNIVAL_START, 220 | MONSTER_CARNIVAL_PARTY_CP, 221 | MONSTER_CARNIVAL_OBTAINED_CP, 222 | ARIANT_PQ_START, 223 | ZAKUM_SHRINE, 224 | NPC_TALK, 225 | OPEN_NPC_SHOP, 226 | CONFIRM_SHOP_TRANSACTION, 227 | OPEN_STORAGE, 228 | MESSENGER, 229 | PLAYER_INTERACTION, 230 | DONALD, 231 | CS_UPDATE, 232 | CS_OPERATION, 233 | KEYMAP, 234 | AUTO_HP_POT, 235 | AUTO_MP_POT, 236 | SEND_TV, 237 | REMOVE_TV, 238 | ENABLE_TV, 239 | MTS_OPERATION, 240 | MTS_OPERATION2, 241 | EARN_TITLE_MSG, 242 | VICIOUS_HAMMER, 243 | UNKNOWN; 244 | 245 | private int code = -2; 246 | 247 | public void setValue(int code) { 248 | this.code = code; 249 | } 250 | 251 | @Override 252 | public int getValue() { 253 | return code; 254 | } 255 | 256 | public static Properties getDefaultProperties() throws FileNotFoundException, IOException { 257 | Properties props = new Properties(); 258 | FileInputStream fileInputStream = new FileInputStream(System.getProperty("net.sf.odinms.sendops")); 259 | props.load(fileInputStream); 260 | fileInputStream.close(); 261 | return props; 262 | } 263 | 264 | public static SendPacketOpcode getByType(int type) { 265 | for (SendPacketOpcode l : SendPacketOpcode.values()) { 266 | if (l.getValue() == type) { 267 | return l; 268 | } 269 | } 270 | return UNKNOWN; 271 | } 272 | 273 | public static SendPacketOpcode getByName(String name) { 274 | for (SendPacketOpcode l : SendPacketOpcode.values()) { 275 | if (l.name().equalsIgnoreCase(name)) { 276 | return l; 277 | } 278 | } 279 | return UNKNOWN; 280 | } 281 | 282 | static { 283 | try { 284 | ExternalCodeTableGetter.populateValues(getDefaultProperties(), values()); 285 | } catch (IOException e) { 286 | throw new RuntimeException("Failed to load sendops", e); 287 | } 288 | } 289 | } 290 | -------------------------------------------------------------------------------- /src/org/snow/maplesnowsniffer/EditOpcode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this template, choose Tools | Templates 3 | * and open the template in the editor. 4 | */ 5 | package org.snow.maplesnowsniffer; 6 | 7 | import java.awt.event.KeyEvent; 8 | import javax.swing.JTable; 9 | 10 | /** 11 | * 12 | * @author TRAN 13 | */ 14 | public class EditOpcode extends javax.swing.JFrame { 15 | 16 | public static boolean isEditOpcode = false; 17 | JTable table; 18 | 19 | /** 20 | * Creates new form NewJFrame 21 | */ 22 | public EditOpcode(JTable opcodeTable, String name, String value) { 23 | // 24 | try { 25 | for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) { 26 | if ("Windows".equals(info.getName())) { 27 | javax.swing.UIManager.setLookAndFeel(info.getClassName()); 28 | break; 29 | } 30 | } 31 | } catch (ClassNotFoundException ex) { 32 | java.util.logging.Logger.getLogger(EditOpcode.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 33 | } catch (InstantiationException ex) { 34 | java.util.logging.Logger.getLogger(EditOpcode.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 35 | } catch (IllegalAccessException ex) { 36 | java.util.logging.Logger.getLogger(EditOpcode.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 37 | } catch (javax.swing.UnsupportedLookAndFeelException ex) { 38 | java.util.logging.Logger.getLogger(EditOpcode.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 39 | } 40 | // 41 | initComponents(); 42 | jTextField2.setText(name); 43 | jTextField3.setText(value); 44 | this.table = opcodeTable; 45 | setVisible(true); 46 | } 47 | 48 | /** 49 | * This method is called from within the constructor to initialize the form. 50 | * WARNING: Do NOT modify this code. The content of this method is always 51 | * regenerated by the Form Editor. 52 | */ 53 | @SuppressWarnings("unchecked") 54 | // //GEN-BEGIN:initComponents 55 | private void initComponents() { 56 | 57 | jLabel1 = new javax.swing.JLabel(); 58 | jLabel2 = new javax.swing.JLabel(); 59 | jButton1 = new javax.swing.JButton(); 60 | jTextField2 = new javax.swing.JTextField(); 61 | jTextField3 = new javax.swing.JTextField(); 62 | jButton2 = new javax.swing.JButton(); 63 | 64 | setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); 65 | setTitle("Edit Opcode"); 66 | setResizable(false); 67 | 68 | jLabel1.setText("OpCode Name:"); 69 | 70 | jLabel2.setText("OpCode Value:"); 71 | 72 | jButton1.setText("Save"); 73 | jButton1.addActionListener(new java.awt.event.ActionListener() { 74 | public void actionPerformed(java.awt.event.ActionEvent evt) { 75 | jButton1ActionPerformed(evt); 76 | } 77 | }); 78 | 79 | jTextField2.addKeyListener(new java.awt.event.KeyAdapter() { 80 | public void keyPressed(java.awt.event.KeyEvent evt) { 81 | jTextField2KeyPressed(evt); 82 | } 83 | }); 84 | 85 | jTextField3.addKeyListener(new java.awt.event.KeyAdapter() { 86 | public void keyPressed(java.awt.event.KeyEvent evt) { 87 | jTextField3KeyPressed(evt); 88 | } 89 | }); 90 | 91 | jButton2.setText("Cancel"); 92 | jButton2.addActionListener(new java.awt.event.ActionListener() { 93 | public void actionPerformed(java.awt.event.ActionEvent evt) { 94 | jButton2ActionPerformed(evt); 95 | } 96 | }); 97 | 98 | javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); 99 | getContentPane().setLayout(layout); 100 | layout.setHorizontalGroup( 101 | layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 102 | .addGroup(layout.createSequentialGroup() 103 | .addContainerGap() 104 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 105 | .addGroup(layout.createSequentialGroup() 106 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) 107 | .addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, 83, Short.MAX_VALUE) 108 | .addComponent(jLabel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) 109 | .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) 110 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 111 | .addComponent(jTextField3) 112 | .addComponent(jTextField2)) 113 | .addContainerGap()) 114 | .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() 115 | .addGap(0, 61, Short.MAX_VALUE) 116 | .addComponent(jButton1, javax.swing.GroupLayout.DEFAULT_SIZE, 83, Short.MAX_VALUE) 117 | .addGap(18, 18, 18) 118 | .addComponent(jButton2, javax.swing.GroupLayout.PREFERRED_SIZE, 85, javax.swing.GroupLayout.PREFERRED_SIZE) 119 | .addGap(70, 70, 70)))) 120 | ); 121 | layout.setVerticalGroup( 122 | layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 123 | .addGroup(layout.createSequentialGroup() 124 | .addContainerGap() 125 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) 126 | .addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) 127 | .addComponent(jTextField2)) 128 | .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) 129 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) 130 | .addComponent(jLabel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) 131 | .addComponent(jTextField3)) 132 | .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 18, Short.MAX_VALUE) 133 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) 134 | .addComponent(jButton1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) 135 | .addComponent(jButton2)) 136 | .addContainerGap()) 137 | ); 138 | 139 | pack(); 140 | }// //GEN-END:initComponents 141 | 142 | private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed 143 | setVisible(false);//CLOSE 144 | }//GEN-LAST:event_jButton2ActionPerformed 145 | 146 | private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed 147 | Save(); 148 | }//GEN-LAST:event_jButton1ActionPerformed 149 | 150 | private void jTextField2KeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_jTextField2KeyPressed 151 | if (evt.getKeyCode() == KeyEvent.VK_ENTER) { 152 | Save(); 153 | } 154 | }//GEN-LAST:event_jTextField2KeyPressed 155 | 156 | private void jTextField3KeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_jTextField3KeyPressed 157 | if (evt.getKeyCode() == KeyEvent.VK_ENTER) { 158 | Save(); 159 | } 160 | }//GEN-LAST:event_jTextField3KeyPressed 161 | 162 | private void Save() { 163 | MapleOpcodeView.name = jTextField2.getText(); 164 | MapleOpcodeView.value = jTextField3.getText(); 165 | isEditOpcode = true; 166 | setVisible(false); 167 | int selectedRow = table.getSelectedRow(); 168 | table.setValueAt(MapleOpcodeView.name, selectedRow, 0); 169 | table.setValueAt(MapleOpcodeView.value, selectedRow, 1); 170 | } 171 | 172 | /** 173 | * @param args the command line arguments 174 | */ 175 | public static void main(String args[]) { 176 | 177 | /* Create and display the form */ 178 | java.awt.EventQueue.invokeLater(new Runnable() { 179 | public void run() { 180 | new EditOpcode(null, MapleOpcodeView.name, MapleOpcodeView.value).setVisible(true); 181 | } 182 | }); 183 | } 184 | // Variables declaration - do not modify//GEN-BEGIN:variables 185 | private javax.swing.JButton jButton1; 186 | private javax.swing.JButton jButton2; 187 | private javax.swing.JLabel jLabel1; 188 | private javax.swing.JLabel jLabel2; 189 | private javax.swing.JTextField jTextField2; 190 | private javax.swing.JTextField jTextField3; 191 | // End of variables declaration//GEN-END:variables 192 | } 193 | -------------------------------------------------------------------------------- /src/org/snow/maplesnowsniffer/MakeLang.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this template, choose Tools | Templates 3 | * and open the template in the editor. 4 | */ 5 | package org.snow.maplesnowsniffer; 6 | 7 | import java.io.FileInputStream; 8 | import java.io.FileOutputStream; 9 | import java.io.IOException; 10 | import java.util.Map; 11 | import java.util.Properties; 12 | import javax.swing.JTable; 13 | 14 | /** 15 | * 16 | * @author TRAN 17 | */ 18 | public class MakeLang extends javax.swing.JFrame { 19 | 20 | private Properties settings = new Properties(); 21 | public static boolean isDevelop = true; 22 | public String lang_path = "languages/lng_VI.ini"; 23 | JTable table; 24 | 25 | /** 26 | * Creates new form NewJFrame 27 | */ 28 | public MakeLang() { 29 | // 30 | try { 31 | for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) { 32 | if ("Windows".equals(info.getName())) { 33 | javax.swing.UIManager.setLookAndFeel(info.getClassName()); 34 | break; 35 | } 36 | } 37 | } catch (ClassNotFoundException ex) { 38 | java.util.logging.Logger.getLogger(MakeLang.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 39 | } catch (InstantiationException ex) { 40 | java.util.logging.Logger.getLogger(MakeLang.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 41 | } catch (IllegalAccessException ex) { 42 | java.util.logging.Logger.getLogger(MakeLang.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 43 | } catch (javax.swing.UnsupportedLookAndFeelException ex) { 44 | java.util.logging.Logger.getLogger(MakeLang.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 45 | } 46 | // 47 | initComponents(); 48 | if (!isDevelop) {//Add and Delete function only for developer 49 | jTextField2.setEditable(false); 50 | jButton3.setEnabled(false); 51 | } 52 | loadLangData(); 53 | loadComboBox(); 54 | } 55 | 56 | public boolean loadComboBox() { 57 | jComboBox1.removeAllItems(); 58 | for (Map.Entry entry : settings.entrySet()) { 59 | String key = (String) entry.getKey(); 60 | jComboBox1.addItem(key); 61 | } 62 | return true; 63 | } 64 | 65 | public boolean loadLangData() { 66 | try { 67 | FileInputStream fis; 68 | fis = new FileInputStream(lang_path); 69 | settings.load(fis); 70 | fis.close(); 71 | } catch (IOException e) { 72 | System.out.println("Cannot find: " + lang_path); 73 | return false; 74 | } 75 | return true; 76 | } 77 | 78 | /** 79 | * This method is called from within the constructor to initialize the form. 80 | * WARNING: Do NOT modify this code. The content of this method is always 81 | * regenerated by the Form Editor. 82 | */ 83 | @SuppressWarnings("unchecked") 84 | // //GEN-BEGIN:initComponents 85 | private void initComponents() { 86 | 87 | jLabel1 = new javax.swing.JLabel(); 88 | jLabel2 = new javax.swing.JLabel(); 89 | jButton1 = new javax.swing.JButton(); 90 | jTextField2 = new javax.swing.JTextField(); 91 | jTextField3 = new javax.swing.JTextField(); 92 | jButton2 = new javax.swing.JButton(); 93 | jComboBox1 = new javax.swing.JComboBox(); 94 | jButton3 = new javax.swing.JButton(); 95 | 96 | setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); 97 | setTitle("Make Language File"); 98 | setResizable(false); 99 | 100 | jLabel1.setText("Name:"); 101 | 102 | jLabel2.setText("Value:"); 103 | 104 | jButton1.setText("Save"); 105 | jButton1.addActionListener(new java.awt.event.ActionListener() { 106 | public void actionPerformed(java.awt.event.ActionEvent evt) { 107 | jButton1ActionPerformed(evt); 108 | } 109 | }); 110 | 111 | jButton2.setText("Cancel"); 112 | jButton2.addActionListener(new java.awt.event.ActionListener() { 113 | public void actionPerformed(java.awt.event.ActionEvent evt) { 114 | jButton2ActionPerformed(evt); 115 | } 116 | }); 117 | 118 | jComboBox1.addPropertyChangeListener(new java.beans.PropertyChangeListener() { 119 | public void propertyChange(java.beans.PropertyChangeEvent evt) { 120 | jComboBox1PropertyChange(evt); 121 | } 122 | }); 123 | 124 | jButton3.setText("Delete"); 125 | jButton3.addActionListener(new java.awt.event.ActionListener() { 126 | public void actionPerformed(java.awt.event.ActionEvent evt) { 127 | jButton3ActionPerformed(evt); 128 | } 129 | }); 130 | 131 | javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); 132 | getContentPane().setLayout(layout); 133 | layout.setHorizontalGroup( 134 | layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 135 | .addGroup(layout.createSequentialGroup() 136 | .addContainerGap() 137 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 138 | .addGroup(layout.createSequentialGroup() 139 | .addComponent(jLabel1) 140 | .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) 141 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 142 | .addComponent(jComboBox1, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) 143 | .addComponent(jTextField2))) 144 | .addGroup(layout.createSequentialGroup() 145 | .addComponent(jLabel2) 146 | .addGap(5, 5, 5) 147 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 148 | .addGroup(layout.createSequentialGroup() 149 | .addComponent(jButton1, javax.swing.GroupLayout.PREFERRED_SIZE, 79, javax.swing.GroupLayout.PREFERRED_SIZE) 150 | .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) 151 | .addComponent(jButton3, javax.swing.GroupLayout.PREFERRED_SIZE, 81, javax.swing.GroupLayout.PREFERRED_SIZE) 152 | .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 50, Short.MAX_VALUE) 153 | .addComponent(jButton2)) 154 | .addComponent(jTextField3)))) 155 | .addContainerGap()) 156 | ); 157 | layout.setVerticalGroup( 158 | layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 159 | .addGroup(layout.createSequentialGroup() 160 | .addContainerGap() 161 | .addComponent(jComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) 162 | .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 7, Short.MAX_VALUE) 163 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) 164 | .addComponent(jLabel1) 165 | .addComponent(jTextField2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) 166 | .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) 167 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) 168 | .addComponent(jTextField3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) 169 | .addComponent(jLabel2)) 170 | .addGap(18, 18, 18) 171 | .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) 172 | .addComponent(jButton1) 173 | .addComponent(jButton2) 174 | .addComponent(jButton3)) 175 | .addContainerGap()) 176 | ); 177 | 178 | pack(); 179 | }// //GEN-END:initComponents 180 | 181 | private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed 182 | setVisible(false);//CLOSE 183 | dispose(); 184 | System.exit(0); 185 | }//GEN-LAST:event_jButton2ActionPerformed 186 | 187 | private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed 188 | try { 189 | String name = jTextField2.getText(); 190 | String value = jTextField3.getText(); 191 | if (settings.containsKey(name)) { 192 | //UPDATE 193 | settings.setProperty(name, value); 194 | } else { 195 | //ADD NEW 196 | settings.put(name, value); 197 | } 198 | settings.store(new FileOutputStream(lang_path), null); 199 | loadLangData(); 200 | loadComboBox(); 201 | } catch (IOException ex) { 202 | System.out.println("Cannot find: " + lang_path); 203 | } 204 | }//GEN-LAST:event_jButton1ActionPerformed 205 | 206 | private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton3ActionPerformed 207 | try { 208 | Object selected = jComboBox1.getSelectedItem(); 209 | settings.remove(selected); 210 | settings.store(new FileOutputStream(lang_path), null); 211 | loadLangData(); 212 | loadComboBox(); 213 | } catch (IOException ex) { 214 | System.out.println("Cannot find: " + lang_path); 215 | } 216 | }//GEN-LAST:event_jButton3ActionPerformed 217 | 218 | private void jComboBox1PropertyChange(java.beans.PropertyChangeEvent evt) {//GEN-FIRST:event_jComboBox1PropertyChange 219 | boolean selectRow = jComboBox1.getSelectedIndex() > -1; 220 | Object selected = jComboBox1.getSelectedItem(); 221 | if (selectRow) { 222 | jTextField2.setText(selected.toString()); 223 | jTextField3.setText(settings.get(selected).toString()); 224 | } 225 | }//GEN-LAST:event_jComboBox1PropertyChange 226 | 227 | /** 228 | * @param args the command line arguments 229 | */ 230 | public static void main(String args[]) { 231 | 232 | /* Create and display the form */ 233 | java.awt.EventQueue.invokeLater(new Runnable() { 234 | public void run() { 235 | new MakeLang().setVisible(true); 236 | } 237 | }); 238 | } 239 | // Variables declaration - do not modify//GEN-BEGIN:variables 240 | private javax.swing.JButton jButton1; 241 | private javax.swing.JButton jButton2; 242 | private javax.swing.JButton jButton3; 243 | private javax.swing.JComboBox jComboBox1; 244 | private javax.swing.JLabel jLabel1; 245 | private javax.swing.JLabel jLabel2; 246 | private javax.swing.JTextField jTextField2; 247 | private javax.swing.JTextField jTextField3; 248 | // End of variables declaration//GEN-END:variables 249 | } 250 | -------------------------------------------------------------------------------- /src/org/snow/maplesnowsniffer/MapleOpcodeView.form: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 |
122 |
123 | 124 | 125 | 126 | 127 | <Editor/> 128 | <Renderer/> 129 | </Column> 130 | <Column maxWidth="120" minWidth="120" prefWidth="-1" resizable="true"> 131 | <Title/> 132 | <Editor/> 133 | <Renderer/> 134 | </Column> 135 | </TableColumnModel> 136 | </Property> 137 | <Property name="tableHeader" type="javax.swing.table.JTableHeader" editor="org.netbeans.modules.form.editors2.JTableHeaderEditor"> 138 | <TableHeader reorderingAllowed="false" resizingAllowed="true"/> 139 | </Property> 140 | </Properties> 141 | <Events> 142 | <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="opcodeTableMouseClicked"/> 143 | <EventHandler event="mouseReleased" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="opcodeTableMouseReleased"/> 144 | </Events> 145 | </Component> 146 | </SubComponents> 147 | </Container> 148 | <Component class="javax.swing.JButton" name="closeButton"> 149 | <Properties> 150 | <Property name="text" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor"> 151 | <Connection code="Lang.get("opcodeTable.button.close")" type="code"/> 152 | </Property> 153 | </Properties> 154 | <Events> 155 | <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="closeButtonActionPerformed"/> 156 | </Events> 157 | </Component> 158 | <Component class="javax.swing.JButton" name="updateHeadersButton"> 159 | <Properties> 160 | <Property name="text" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor"> 161 | <Connection code="Lang.get("opcodeTable.button.update")" type="code"/> 162 | </Property> 163 | <Property name="toolTipText" type="java.lang.String" value="Update Headers"/> 164 | </Properties> 165 | <Events> 166 | <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="updateHeadersButtonActionPerformed"/> 167 | </Events> 168 | </Component> 169 | <Component class="javax.swing.JLabel" name="totalOpcodeLabel"> 170 | <Properties> 171 | <Property name="text" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor"> 172 | <Connection code="Lang.get("opcodeTable.total")" type="code"/> 173 | </Property> 174 | </Properties> 175 | </Component> 176 | <Component class="javax.swing.JButton" name="saveChangesButton"> 177 | <Properties> 178 | <Property name="text" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor"> 179 | <Connection code="Lang.get("opcodeTable.button.save")" type="code"/> 180 | </Property> 181 | <Property name="toolTipText" type="java.lang.String" value="Save Header Changes"/> 182 | </Properties> 183 | <Events> 184 | <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="saveChangesButtonActionPerformed"/> 185 | </Events> 186 | </Component> 187 | <Component class="javax.swing.JButton" name="jButton1"> 188 | <Properties> 189 | <Property name="text" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor"> 190 | <Connection code="Lang.get("opcodeTable.button.edit")" type="code"/> 191 | </Property> 192 | </Properties> 193 | <Events> 194 | <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButton1ActionPerformed"/> 195 | </Events> 196 | </Component> 197 | </SubComponents> 198 | </Form> 199 | -------------------------------------------------------------------------------- /src/org/snow/maplesnowsniffer/MapleBlockedOpcodeViewer.form: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8" ?> 2 | 3 | <Form version="1.6" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JFrameFormInfo"> 4 | <Properties> 5 | <Property name="defaultCloseOperation" type="int" value="2"/> 6 | <Property name="title" type="java.lang.String" value="Snow's Packet Header Viewer"/> 7 | <Property name="resizable" type="boolean" value="false"/> 8 | </Properties> 9 | <SyntheticProperties> 10 | <SyntheticProperty name="formSizePolicy" type="int" value="1"/> 11 | </SyntheticProperties> 12 | <Events> 13 | <EventHandler event="windowClosed" listener="java.awt.event.WindowListener" parameters="java.awt.event.WindowEvent" handler="formWindowClosed"/> 14 | </Events> 15 | <AuxValues> 16 | <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/> 17 | <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/> 18 | <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/> 19 | <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/> 20 | <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/> 21 | <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/> 22 | <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/> 23 | <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/> 24 | <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/> 25 | </AuxValues> 26 | 27 | <Layout> 28 | <DimensionLayout dim="0"> 29 | <Group type="103" groupAlignment="0" attributes="0"> 30 | <Group type="102" attributes="0"> 31 | <EmptySpace max="-2" attributes="0"/> 32 | <Group type="103" groupAlignment="0" attributes="0"> 33 | <Group type="102" attributes="0"> 34 | <Component id="jButton2" min="-2" pref="115" max="-2" attributes="0"/> 35 | <EmptySpace type="separate" max="-2" attributes="0"/> 36 | <Component id="deleteButton" min="-2" pref="116" max="-2" attributes="0"/> 37 | </Group> 38 | <Component id="jScrollPane1" min="-2" pref="249" max="-2" attributes="0"/> 39 | </Group> 40 | <EmptySpace type="unrelated" max="-2" attributes="0"/> 41 | <Group type="103" groupAlignment="0" attributes="0"> 42 | <Group type="102" attributes="0"> 43 | <Component id="jScrollPane2" min="-2" pref="249" max="-2" attributes="0"/> 44 | <EmptySpace min="0" pref="0" max="32767" attributes="0"/> 45 | </Group> 46 | <Group type="102" attributes="0"> 47 | <Component id="saveButton" min="-2" pref="112" max="-2" attributes="0"/> 48 | <EmptySpace type="separate" max="-2" attributes="0"/> 49 | <Component id="closeButton" max="32767" attributes="0"/> 50 | </Group> 51 | </Group> 52 | <EmptySpace max="-2" attributes="0"/> 53 | </Group> 54 | </Group> 55 | </DimensionLayout> 56 | <DimensionLayout dim="1"> 57 | <Group type="103" groupAlignment="0" attributes="0"> 58 | <Group type="102" alignment="0" attributes="0"> 59 | <EmptySpace max="-2" attributes="0"/> 60 | <Group type="103" groupAlignment="1" attributes="0"> 61 | <Component id="jScrollPane1" min="-2" pref="314" max="-2" attributes="0"/> 62 | <Component id="jScrollPane2" min="-2" pref="314" max="-2" attributes="0"/> 63 | </Group> 64 | <EmptySpace max="-2" attributes="0"/> 65 | <Group type="103" groupAlignment="3" attributes="0"> 66 | <Component id="closeButton" alignment="3" min="-2" max="-2" attributes="0"/> 67 | <Component id="deleteButton" alignment="3" min="-2" max="-2" attributes="0"/> 68 | <Component id="saveButton" alignment="3" min="-2" max="-2" attributes="0"/> 69 | <Component id="jButton2" alignment="3" min="-2" max="-2" attributes="0"/> 70 | </Group> 71 | <EmptySpace max="32767" attributes="0"/> 72 | </Group> 73 | </Group> 74 | </DimensionLayout> 75 | </Layout> 76 | <SubComponents> 77 | <Container class="javax.swing.JScrollPane" name="jScrollPane1"> 78 | <AuxValues> 79 | <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/> 80 | </AuxValues> 81 | 82 | <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/> 83 | <SubComponents> 84 | <Component class="javax.swing.JTable" name="opcodeTable"> 85 | <Properties> 86 | <Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor"> 87 | <Connection code="new javax.swing.table.DefaultTableModel( new Object [][] { }, new String [] { "Send Opcode", Lang.get("blockTable.blocked") } ) { Class[] types = new Class [] { java.lang.String.class, java.lang.Boolean.class }; boolean[] canEdit = new boolean [] { false, true }; public Class getColumnClass(int columnIndex) { return types [columnIndex]; } public boolean isCellEditable(int rowIndex, int columnIndex) { return canEdit [columnIndex]; } }" type="code"/> 88 | </Property> 89 | <Property name="columnModel" type="javax.swing.table.TableColumnModel" editor="org.netbeans.modules.form.editors2.TableColumnModelEditor"> 90 | <TableColumnModel selectionModel="0"> 91 | <Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="false"> 92 | <Title/> 93 | <Editor/> 94 | <Renderer/> 95 | </Column> 96 | <Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="false"> 97 | <Title/> 98 | <Editor/> 99 | <Renderer/> 100 | </Column> 101 | </TableColumnModel> 102 | </Property> 103 | <Property name="selectionModel" type="javax.swing.ListSelectionModel" editor="org.netbeans.modules.form.editors2.JTableSelectionModelEditor"> 104 | <JTableSelectionModel selectionMode="0"/> 105 | </Property> 106 | <Property name="showHorizontalLines" type="boolean" value="false"/> 107 | <Property name="tableHeader" type="javax.swing.table.JTableHeader" editor="org.netbeans.modules.form.editors2.JTableHeaderEditor"> 108 | <TableHeader reorderingAllowed="false" resizingAllowed="true"/> 109 | </Property> 110 | </Properties> 111 | </Component> 112 | </SubComponents> 113 | </Container> 114 | <Component class="javax.swing.JButton" name="closeButton"> 115 | <Properties> 116 | <Property name="text" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor"> 117 | <Connection code="Lang.get("blockTable.button.close")" type="code"/> 118 | </Property> 119 | </Properties> 120 | <Events> 121 | <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="closeButtonActionPerformed"/> 122 | </Events> 123 | </Component> 124 | <Component class="javax.swing.JButton" name="deleteButton"> 125 | <Properties> 126 | <Property name="text" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor"> 127 | <Connection code="Lang.get("blockTable.button.del")" type="code"/> 128 | </Property> 129 | </Properties> 130 | <Events> 131 | <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="deleteButtonActionPerformed"/> 132 | </Events> 133 | </Component> 134 | <Component class="javax.swing.JButton" name="saveButton"> 135 | <Properties> 136 | <Property name="text" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor"> 137 | <Connection code="Lang.get("blockTable.button.save")" type="code"/> 138 | </Property> 139 | </Properties> 140 | <Events> 141 | <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="saveButtonActionPerformed"/> 142 | </Events> 143 | </Component> 144 | <Component class="javax.swing.JButton" name="jButton2"> 145 | <Properties> 146 | <Property name="text" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor"> 147 | <Connection code="Lang.get("blockTable.button.add")" type="code"/> 148 | </Property> 149 | </Properties> 150 | <Events> 151 | <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButton2ActionPerformed"/> 152 | </Events> 153 | </Component> 154 | <Container class="javax.swing.JScrollPane" name="jScrollPane2"> 155 | <AuxValues> 156 | <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/> 157 | </AuxValues> 158 | 159 | <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/> 160 | <SubComponents> 161 | <Component class="javax.swing.JTable" name="opcodeTable1"> 162 | <Properties> 163 | <Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor"> 164 | <Connection code="new javax.swing.table.DefaultTableModel( new Object [][] { }, new String [] { "Recv Opcode", Lang.get("blockTable.blocked") } ) { Class[] types = new Class [] { java.lang.String.class, java.lang.Boolean.class }; boolean[] canEdit = new boolean [] { false, true }; public Class getColumnClass(int columnIndex) { return types [columnIndex]; } public boolean isCellEditable(int rowIndex, int columnIndex) { return canEdit [columnIndex]; } }" type="code"/> 165 | </Property> 166 | <Property name="columnModel" type="javax.swing.table.TableColumnModel" editor="org.netbeans.modules.form.editors2.TableColumnModelEditor"> 167 | <TableColumnModel selectionModel="1"> 168 | <Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="false"> 169 | <Title/> 170 | <Editor/> 171 | <Renderer/> 172 | </Column> 173 | <Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="false"> 174 | <Title/> 175 | <Editor/> 176 | <Renderer/> 177 | </Column> 178 | </TableColumnModel> 179 | </Property> 180 | <Property name="selectionModel" type="javax.swing.ListSelectionModel" editor="org.netbeans.modules.form.editors2.JTableSelectionModelEditor"> 181 | <JTableSelectionModel selectionMode="0"/> 182 | </Property> 183 | <Property name="showHorizontalLines" type="boolean" value="false"/> 184 | <Property name="tableHeader" type="javax.swing.table.JTableHeader" editor="org.netbeans.modules.form.editors2.JTableHeaderEditor"> 185 | <TableHeader reorderingAllowed="false" resizingAllowed="true"/> 186 | </Property> 187 | </Properties> 188 | </Component> 189 | </SubComponents> 190 | </Container> 191 | </SubComponents> 192 | </Form> 193 | -------------------------------------------------------------------------------- /src/org/snow/odinms/MapleAESOFB.java: -------------------------------------------------------------------------------- 1 | package org.snow.odinms; 2 | 3 | import java.security.InvalidKeyException; 4 | import java.security.NoSuchAlgorithmException; 5 | import javax.crypto.BadPaddingException; 6 | import javax.crypto.Cipher; 7 | import javax.crypto.IllegalBlockSizeException; 8 | import javax.crypto.NoSuchPaddingException; 9 | import javax.crypto.spec.SecretKeySpec; 10 | import org.snow.maplesnowsniffer.GMSKeys; 11 | 12 | /** 13 | * Provides a class for encrypting MapleStory packets with AES OFB encryption. 14 | */ 15 | public class MapleAESOFB { 16 | 17 | private byte iv[]; 18 | private Cipher cipher; 19 | private short mapleVersion; 20 | // KMS 21 | // {0x13, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x5B, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00} 22 | private static final byte[] funnyBytes = new byte[]{(byte) 0xEC, (byte) 0x3F, (byte) 0x77, (byte) 0xA4, (byte) 0x45, (byte) 0xD0, (byte) 0x71, (byte) 0xBF, (byte) 0xB7, (byte) 0x98, (byte) 0x20, (byte) 0xFC, 23 | (byte) 0x4B, (byte) 0xE9, (byte) 0xB3, (byte) 0xE1, (byte) 0x5C, (byte) 0x22, (byte) 0xF7, (byte) 0x0C, (byte) 0x44, (byte) 0x1B, (byte) 0x81, (byte) 0xBD, (byte) 0x63, (byte) 0x8D, (byte) 0xD4, (byte) 0xC3, 24 | (byte) 0xF2, (byte) 0x10, (byte) 0x19, (byte) 0xE0, (byte) 0xFB, (byte) 0xA1, (byte) 0x6E, (byte) 0x66, (byte) 0xEA, (byte) 0xAE, (byte) 0xD6, (byte) 0xCE, (byte) 0x06, (byte) 0x18, (byte) 0x4E, (byte) 0xEB, 25 | (byte) 0x78, (byte) 0x95, (byte) 0xDB, (byte) 0xBA, (byte) 0xB6, (byte) 0x42, (byte) 0x7A, (byte) 0x2A, (byte) 0x83, (byte) 0x0B, (byte) 0x54, (byte) 0x67, (byte) 0x6D, (byte) 0xE8, (byte) 0x65, (byte) 0xE7, 26 | (byte) 0x2F, (byte) 0x07, (byte) 0xF3, (byte) 0xAA, (byte) 0x27, (byte) 0x7B, (byte) 0x85, (byte) 0xB0, (byte) 0x26, (byte) 0xFD, (byte) 0x8B, (byte) 0xA9, (byte) 0xFA, (byte) 0xBE, (byte) 0xA8, (byte) 0xD7, 27 | (byte) 0xCB, (byte) 0xCC, (byte) 0x92, (byte) 0xDA, (byte) 0xF9, (byte) 0x93, (byte) 0x60, (byte) 0x2D, (byte) 0xDD, (byte) 0xD2, (byte) 0xA2, (byte) 0x9B, (byte) 0x39, (byte) 0x5F, (byte) 0x82, (byte) 0x21, 28 | (byte) 0x4C, (byte) 0x69, (byte) 0xF8, (byte) 0x31, (byte) 0x87, (byte) 0xEE, (byte) 0x8E, (byte) 0xAD, (byte) 0x8C, (byte) 0x6A, (byte) 0xBC, (byte) 0xB5, (byte) 0x6B, (byte) 0x59, (byte) 0x13, (byte) 0xF1, 29 | (byte) 0x04, (byte) 0x00, (byte) 0xF6, (byte) 0x5A, (byte) 0x35, (byte) 0x79, (byte) 0x48, (byte) 0x8F, (byte) 0x15, (byte) 0xCD, (byte) 0x97, (byte) 0x57, (byte) 0x12, (byte) 0x3E, (byte) 0x37, (byte) 0xFF, 30 | (byte) 0x9D, (byte) 0x4F, (byte) 0x51, (byte) 0xF5, (byte) 0xA3, (byte) 0x70, (byte) 0xBB, (byte) 0x14, (byte) 0x75, (byte) 0xC2, (byte) 0xB8, (byte) 0x72, (byte) 0xC0, (byte) 0xED, (byte) 0x7D, (byte) 0x68, 31 | (byte) 0xC9, (byte) 0x2E, (byte) 0x0D, (byte) 0x62, (byte) 0x46, (byte) 0x17, (byte) 0x11, (byte) 0x4D, (byte) 0x6C, (byte) 0xC4, (byte) 0x7E, (byte) 0x53, (byte) 0xC1, (byte) 0x25, (byte) 0xC7, (byte) 0x9A, 32 | (byte) 0x1C, (byte) 0x88, (byte) 0x58, (byte) 0x2C, (byte) 0x89, (byte) 0xDC, (byte) 0x02, (byte) 0x64, (byte) 0x40, (byte) 0x01, (byte) 0x5D, (byte) 0x38, (byte) 0xA5, (byte) 0xE2, (byte) 0xAF, (byte) 0x55, 33 | (byte) 0xD5, (byte) 0xEF, (byte) 0x1A, (byte) 0x7C, (byte) 0xA7, (byte) 0x5B, (byte) 0xA6, (byte) 0x6F, (byte) 0x86, (byte) 0x9F, (byte) 0x73, (byte) 0xE6, (byte) 0x0A, (byte) 0xDE, (byte) 0x2B, (byte) 0x99, 34 | (byte) 0x4A, (byte) 0x47, (byte) 0x9C, (byte) 0xDF, (byte) 0x09, (byte) 0x76, (byte) 0x9E, (byte) 0x30, (byte) 0x0E, (byte) 0xE4, (byte) 0xB2, (byte) 0x94, (byte) 0xA0, (byte) 0x3B, (byte) 0x34, (byte) 0x1D, 35 | (byte) 0x28, (byte) 0x0F, (byte) 0x36, (byte) 0xE3, (byte) 0x23, (byte) 0xB4, (byte) 0x03, (byte) 0xD8, (byte) 0x90, (byte) 0xC8, (byte) 0x3C, (byte) 0xFE, (byte) 0x5E, (byte) 0x32, (byte) 0x24, (byte) 0x50, 36 | (byte) 0x1F, (byte) 0x3A, (byte) 0x43, (byte) 0x8A, (byte) 0x96, (byte) 0x41, (byte) 0x74, (byte) 0xAC, (byte) 0x52, (byte) 0x33, (byte) 0xF0, (byte) 0xD9, (byte) 0x29, (byte) 0x80, (byte) 0xB1, (byte) 0x16, 37 | (byte) 0xD3, (byte) 0xAB, (byte) 0x91, (byte) 0xB9, (byte) 0x84, (byte) 0x7F, (byte) 0x61, (byte) 0x1E, (byte) 0xCF, (byte) 0xC5, (byte) 0xD1, (byte) 0x56, (byte) 0x3D, (byte) 0xCA, (byte) 0xF4, (byte) 0x05, 38 | (byte) 0xC6, (byte) 0xE5, (byte) 0x08, (byte) 0x49}; 39 | /** 40 | * Class constructor - Creates an instance of the MapleStory encryption 41 | * cipher. 42 | * 43 | * @param key The 256 bit AES key to use. 44 | * @param iv The 4-byte IV to use. 45 | */ 46 | private static byte[] secretKey = new byte[]{0x13, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, (byte) 0xB4, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00}; 47 | 48 | public MapleAESOFB(byte iv[], short mapleVer) { 49 | byte[] getKey = GMSKeys.GetKeyForVersion(mapleVer); 50 | try { 51 | if (mapleVer > 118 && getKey != null) {// GMS uses random keys since v118! 52 | secretKey = getKey; 53 | } 54 | SecretKeySpec skey = new SecretKeySpec(secretKey, "AES"); 55 | cipher = Cipher.getInstance("AES"); 56 | cipher.init(Cipher.ENCRYPT_MODE, skey); 57 | } catch (NoSuchPaddingException ex) { 58 | System.err.println("ERROR" + ex); 59 | } catch (NoSuchAlgorithmException e) { 60 | System.err.println("ERROR" + e); 61 | } catch (InvalidKeyException e) { 62 | System.err.println("Error initalizing the encryption cipher. Make sure you're using the Unlimited Strength cryptography jar files."); 63 | } 64 | 65 | this.setIv(iv); 66 | this.mapleVersion = (short) (((mapleVer >> 8) & 0xFF) | ((mapleVer << 8) & 0xFF00)); 67 | } 68 | 69 | /** 70 | * Sets the IV of this instance. 71 | * 72 | * @param iv The new IV. 73 | */ 74 | private void setIv(byte[] iv) { 75 | this.iv = iv; 76 | } 77 | 78 | /** 79 | * For debugging/testing purposes only. 80 | * 81 | * @return The IV. 82 | */ 83 | public byte[] getIv() { 84 | return this.iv; 85 | } 86 | 87 | /** 88 | * Encrypts 89 | * <code>data</code> and generates a new IV. 90 | * 91 | * @param data The bytes to encrypt. 92 | * @return The encrypted bytes. 93 | */ 94 | public byte[] crypt(byte[] data) { 95 | int remaining = data.length;//pBuffer.Length; 96 | int llength = 0x5B0; 97 | int start = 0; 98 | 99 | try { 100 | while (remaining > 0) { 101 | byte[] myIv = BitTools.multiplyBytes(this.iv, 4, 4); 102 | if (remaining < llength) { 103 | llength = remaining; 104 | } 105 | for (int x = start; x < (start + llength); x++) { 106 | if ((x - start) % myIv.length == 0) { 107 | byte[] newIv = cipher.doFinal(myIv);//newIv = tempIV 108 | System.arraycopy(newIv, 0, myIv, 0, myIv.length);//myIv = realIV 109 | } 110 | data[x] ^= myIv[(x - start) % myIv.length]; 111 | } 112 | start += llength; 113 | remaining -= llength; 114 | llength = 0x5B4; 115 | } 116 | this.iv = getNewIv(this.iv); 117 | } catch (BadPaddingException ex) { 118 | ex.printStackTrace(); 119 | } catch (IllegalBlockSizeException e) { 120 | e.printStackTrace(); 121 | } 122 | return data; 123 | } 124 | 125 | /** 126 | * Gets a new IV from 127 | * <code>oldIv</code> 128 | * 129 | * @param oldIv The old IV to get a new IV from. 130 | * @return The new IV. 131 | */ 132 | public static byte[] getNewIv(byte oldIv[]) { 133 | byte[] newIV = {(byte) 0xf2, 0x53, (byte) 0x50, (byte) 0xc6}; // magic 134 | for (int x = 0; x < 4; x++) { 135 | funnyShit(oldIv[x], newIV); 136 | } 137 | return newIV; 138 | } 139 | 140 | /** 141 | * Generates a packet header for a packet that is 142 | * <code>length</code> long. 143 | * 144 | * @param length How long the packet that this header is for is. 145 | * @return The header. 146 | */ 147 | public byte[] getPacketHeader(int length) { 148 | int iiv = (((iv[3]) & 0xFF) | ((iv[2] << 8) & 0xFF00)) ^ mapleVersion; 149 | int mlength = (((length << 8) & 0xFF00) | (length >>> 8)) ^ iiv; 150 | 151 | return new byte[]{(byte) ((iiv >>> 8) & 0xFF), (byte) (iiv & 0xFF), (byte) ((mlength >>> 8) & 0xFF), (byte) (mlength & 0xFF)}; 152 | } 153 | 154 | /** 155 | * Gets the packet length from a header. 156 | * 157 | * @param packetHeader The header as an integer. 158 | * @return The length of the packet. 159 | */ 160 | public static int getPacketLength(int packetHeader) { 161 | int packetLength = ((packetHeader >>> 16) ^ (packetHeader & 0xFFFF)); 162 | packetLength = ((packetLength << 8) & 0xFF00) | ((packetLength >>> 8) & 0xFF); // fix endianness 163 | return packetLength; 164 | } 165 | 166 | /** 167 | * Gets the packet length from a header. 168 | * 169 | * @param packetHeader The header as a byte array. 170 | * @return The length of the packet. 171 | */ 172 | public static int getPacketLength(byte[] packetHeader) { 173 | if (packetHeader.length < 4) { 174 | return -1; 175 | } 176 | return (((int) (packetHeader[0] ^ packetHeader[2]) & 0xFF) | (((int) (packetHeader[1] ^ packetHeader[3]) << 8) & 0xFF00)); 177 | } 178 | 179 | /** 180 | * Check the packet to make sure it has a header. 181 | * 182 | * @param packet The packet to check. 183 | * @return <code>True</code> if the packet has a correct header, 184 | * <code>false</code> otherwise. 185 | */ 186 | public boolean checkPacket(byte[] packet) { 187 | return ((((packet[0] ^ iv[2]) & 0xFF) == ((mapleVersion >> 8) & 0xFF)) && (((packet[1] ^ iv[3]) & 0xFF) == (mapleVersion & 0xFF))); 188 | } 189 | 190 | /** 191 | * Check the header for validity. 192 | * 193 | * @param packetHeader The packet header to check. 194 | * @return <code>True</code> if the header is correct, <code>false</code> 195 | * otherwise. 196 | */ 197 | public boolean checkPacket(int packetHeader) { 198 | return checkPacket(new byte[]{(byte) ((packetHeader >> 24) & 0xFF), (byte) ((packetHeader >> 16) & 0xFF)}); 199 | } 200 | 201 | /** 202 | * Returns the IV of this instance as a string. 203 | */ 204 | @Override 205 | public String toString() { 206 | return "IV: " + HexTool.toString(this.iv); 207 | } 208 | 209 | /** 210 | * Does funny stuff. 211 | * <code>this.OldIV</code> must not equal 212 | * <code>in</code> Modifies 213 | * <code>in</code> and returns it for convenience. 214 | * 215 | * @param inputByte The byte to apply the funny stuff to. 216 | * @param in Something needed for all this to occur. 217 | * @return The modified version of <code>in</code>. 218 | */ 219 | public static final void funnyShit(byte oldIv , byte[] newIV){//(byte inputByte, byte[] in) { 220 | byte elina = newIV[1];//in = newIV 221 | byte anna = oldIv;//pOldIV 222 | byte moritz = funnyBytes[(int) elina & 0xFF];//sShiftKey 223 | moritz -= oldIv; 224 | newIV[0] += moritz; 225 | moritz = newIV[2]; 226 | moritz ^= funnyBytes[(int) anna & 0xFF]; 227 | elina -= (int) moritz & 0xFF; 228 | newIV[1] = elina; 229 | elina = newIV[3]; 230 | moritz = elina; 231 | elina -= (int) newIV[0] & 0xFF; 232 | moritz = funnyBytes[(int) moritz & 0xFF]; 233 | moritz += oldIv; 234 | moritz ^= newIV[2]; 235 | newIV[2] = moritz; 236 | elina += (int) funnyBytes[(int) anna & 0xFF] & 0xFF; 237 | newIV[3] = elina; 238 | 239 | int merry = ((int) newIV[0]) & 0xFF; 240 | merry |= (newIV[1] << 8) & 0xFF00; 241 | merry |= (newIV[2] << 16) & 0xFF0000; 242 | merry |= (newIV[3] << 24) & 0xFF000000; 243 | int ret_value = merry >>> 0x1d; 244 | merry <<= 3; 245 | ret_value |= merry; 246 | 247 | newIV[0] = (byte) (ret_value & 0xFF); 248 | newIV[1] = (byte) ((ret_value >> 8) & 0xFF); 249 | newIV[2] = (byte) ((ret_value >> 16) & 0xFF); 250 | newIV[3] = (byte) ((ret_value >> 24) & 0xFF); 251 | } 252 | } 253 | -------------------------------------------------------------------------------- /src/org/snow/maplesnowsniffer/ListDevices.form: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8" ?> 2 | 3 | <Form version="1.3" maxVersion="1.8" type="org.netbeans.modules.form.forminfo.JFrameFormInfo"> 4 | <NonVisualComponents> 5 | <Container class="javax.swing.JPopupMenu" name="jPopupMenu1"> 6 | 7 | <Layout class="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout"> 8 | <Property name="useNullLayout" type="boolean" value="true"/> 9 | </Layout> 10 | </Container> 11 | <Component class="javax.swing.ButtonGroup" name="buttonGroup1"> 12 | </Component> 13 | <Component class="javax.swing.ButtonGroup" name="buttonGroup2"> 14 | </Component> 15 | <Component class="javax.swing.JLabel" name="jLabel3"> 16 | <Properties> 17 | <Property name="text" type="java.lang.String" value="jLabel3"/> 18 | </Properties> 19 | </Component> 20 | </NonVisualComponents> 21 | <Properties> 22 | <Property name="defaultCloseOperation" type="int" value="3"/> 23 | <Property name="title" type="java.lang.String" value="Maple Snow Sniffer [Upgrade Version 1.2]"/> 24 | <Property name="resizable" type="boolean" value="false"/> 25 | </Properties> 26 | <SyntheticProperties> 27 | <SyntheticProperty name="formSizePolicy" type="int" value="1"/> 28 | </SyntheticProperties> 29 | <AuxValues> 30 | <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/> 31 | <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/> 32 | <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/> 33 | <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/> 34 | <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/> 35 | <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/> 36 | <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/> 37 | <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/> 38 | <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/> 39 | </AuxValues> 40 | 41 | <Layout> 42 | <DimensionLayout dim="0"> 43 | <Group type="103" groupAlignment="0" attributes="0"> 44 | <Group type="102" attributes="0"> 45 | <EmptySpace max="-2" attributes="0"/> 46 | <Group type="103" groupAlignment="0" attributes="0"> 47 | <Group type="102" alignment="0" attributes="0"> 48 | <Group type="103" groupAlignment="0" attributes="0"> 49 | <Group type="102" alignment="0" attributes="0"> 50 | <Component id="jLabel1" min="-2" max="-2" attributes="0"/> 51 | <Group type="103" groupAlignment="0" attributes="0"> 52 | <Group type="102" attributes="0"> 53 | <EmptySpace min="-2" pref="19" max="-2" attributes="0"/> 54 | <Component id="jLabel4" min="-2" max="-2" attributes="0"/> 55 | <EmptySpace min="0" pref="0" max="32767" attributes="0"/> 56 | </Group> 57 | <Group type="102" attributes="0"> 58 | <EmptySpace type="separate" max="-2" attributes="0"/> 59 | <Component id="jComboBox1" max="32767" attributes="0"/> 60 | </Group> 61 | </Group> 62 | </Group> 63 | <Group type="102" attributes="0"> 64 | <Component id="jPanel2" min="-2" max="-2" attributes="0"/> 65 | <EmptySpace min="0" pref="0" max="32767" attributes="0"/> 66 | </Group> 67 | </Group> 68 | <EmptySpace max="-2" attributes="0"/> 69 | </Group> 70 | <Group type="102" alignment="0" attributes="0"> 71 | <EmptySpace min="-2" pref="67" max="-2" attributes="0"/> 72 | <Component id="jButton3" min="-2" pref="80" max="-2" attributes="0"/> 73 | <EmptySpace max="32767" attributes="0"/> 74 | <Component id="jButton4" min="-2" pref="80" max="-2" attributes="0"/> 75 | <EmptySpace min="-2" pref="81" max="-2" attributes="0"/> 76 | </Group> 77 | </Group> 78 | </Group> 79 | </Group> 80 | </DimensionLayout> 81 | <DimensionLayout dim="1"> 82 | <Group type="103" groupAlignment="0" attributes="0"> 83 | <Group type="102" alignment="0" attributes="0"> 84 | <EmptySpace min="-2" max="-2" attributes="0"/> 85 | <Component id="jLabel4" pref="17" max="32767" attributes="0"/> 86 | <EmptySpace type="unrelated" max="-2" attributes="0"/> 87 | <Group type="103" groupAlignment="3" attributes="0"> 88 | <Component id="jComboBox1" alignment="3" max="-2" attributes="0"/> 89 | <Component id="jLabel1" alignment="3" max="32767" attributes="0"/> 90 | </Group> 91 | <EmptySpace max="-2" attributes="0"/> 92 | <Component id="jPanel2" max="-2" attributes="0"/> 93 | <EmptySpace min="-2" pref="4" max="-2" attributes="0"/> 94 | <Group type="103" groupAlignment="3" attributes="0"> 95 | <Component id="jButton4" alignment="3" max="32767" attributes="0"/> 96 | <Component id="jButton3" alignment="3" min="-2" max="-2" attributes="0"/> 97 | </Group> 98 | <EmptySpace pref="15" max="32767" attributes="0"/> 99 | </Group> 100 | </Group> 101 | </DimensionLayout> 102 | </Layout> 103 | <SubComponents> 104 | <Component class="javax.swing.JLabel" name="jLabel1"> 105 | <Properties> 106 | <Property name="text" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor"> 107 | <Connection code="Lang.get("setting.text2")" type="code"/> 108 | </Property> 109 | </Properties> 110 | </Component> 111 | <Component class="javax.swing.JComboBox" name="jComboBox1"> 112 | <Properties> 113 | <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor"> 114 | <StringArray count="0"/> 115 | </Property> 116 | </Properties> 117 | </Component> 118 | <Component class="javax.swing.JButton" name="jButton3"> 119 | <Properties> 120 | <Property name="text" type="java.lang.String" value="OK"/> 121 | </Properties> 122 | <Events> 123 | <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButton3ActionPerformed"/> 124 | </Events> 125 | </Component> 126 | <Component class="javax.swing.JButton" name="jButton4"> 127 | <Properties> 128 | <Property name="text" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor"> 129 | <Connection code="Lang.get("setting.button.close")" type="code"/> 130 | </Property> 131 | </Properties> 132 | <Events> 133 | <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButton4ActionPerformed"/> 134 | </Events> 135 | </Component> 136 | <Component class="javax.swing.JLabel" name="jLabel4"> 137 | <Properties> 138 | <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor"> 139 | <Font name="Tahoma" size="12" style="1"/> 140 | </Property> 141 | <Property name="text" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor"> 142 | <Connection code="Lang.get("setting.text")" type="code"/> 143 | </Property> 144 | </Properties> 145 | </Component> 146 | <Container class="javax.swing.JPanel" name="jPanel2"> 147 | <Properties> 148 | <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor"> 149 | <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo"> 150 | <TitledBorder/> 151 | </Border> 152 | </Property> 153 | </Properties> 154 | 155 | <Layout> 156 | <DimensionLayout dim="0"> 157 | <Group type="103" groupAlignment="0" attributes="0"> 158 | <Group type="102" attributes="0"> 159 | <EmptySpace max="-2" attributes="0"/> 160 | <Group type="103" groupAlignment="0" max="-2" attributes="0"> 161 | <Component id="jCheckBox1" alignment="0" max="32767" attributes="0"/> 162 | <Component id="jCheckBox2" alignment="0" max="32767" attributes="0"/> 163 | <Component id="jCheckBox3" alignment="0" max="32767" attributes="0"/> 164 | </Group> 165 | <EmptySpace min="-2" pref="65" max="-2" attributes="0"/> 166 | <Group type="103" groupAlignment="0" max="-2" attributes="0"> 167 | <Component id="jLabel5" max="32767" attributes="0"/> 168 | <Component id="jLabel6" alignment="0" pref="75" max="32767" attributes="0"/> 169 | <Component id="jLabel2" alignment="0" max="32767" attributes="0"/> 170 | </Group> 171 | <EmptySpace min="-2" pref="31" max="-2" attributes="0"/> 172 | <Group type="103" groupAlignment="0" attributes="0"> 173 | <Component id="jComboBox4" alignment="1" max="32767" attributes="0"/> 174 | <Component id="jComboBox3" max="32767" attributes="0"/> 175 | <Component id="jComboBox2" alignment="1" max="32767" attributes="0"/> 176 | </Group> 177 | <EmptySpace max="-2" attributes="0"/> 178 | </Group> 179 | </Group> 180 | </DimensionLayout> 181 | <DimensionLayout dim="1"> 182 | <Group type="103" groupAlignment="0" attributes="0"> 183 | <Group type="102" alignment="0" attributes="0"> 184 | <EmptySpace max="-2" attributes="0"/> 185 | <Group type="103" groupAlignment="3" attributes="0"> 186 | <Component id="jCheckBox1" alignment="3" max="32767" attributes="0"/> 187 | <Component id="jLabel2" alignment="3" max="32767" attributes="0"/> 188 | <Component id="jComboBox2" alignment="3" max="32767" attributes="0"/> 189 | </Group> 190 | <EmptySpace max="-2" attributes="0"/> 191 | <Group type="103" groupAlignment="3" attributes="0"> 192 | <Component id="jCheckBox2" alignment="3" max="32767" attributes="0"/> 193 | <Component id="jLabel5" alignment="3" max="32767" attributes="0"/> 194 | <Component id="jComboBox3" alignment="3" max="32767" attributes="0"/> 195 | </Group> 196 | <EmptySpace max="-2" attributes="0"/> 197 | <Group type="103" groupAlignment="3" attributes="0"> 198 | <Component id="jCheckBox3" alignment="3" max="32767" attributes="0"/> 199 | <Component id="jLabel6" alignment="3" max="32767" attributes="0"/> 200 | <Component id="jComboBox4" alignment="3" max="32767" attributes="0"/> 201 | </Group> 202 | <EmptySpace max="32767" attributes="0"/> 203 | </Group> 204 | </Group> 205 | </DimensionLayout> 206 | </Layout> 207 | <SubComponents> 208 | <Component class="javax.swing.JCheckBox" name="jCheckBox1"> 209 | <Properties> 210 | <Property name="selected" type="boolean" value="true"/> 211 | <Property name="text" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor"> 212 | <Connection code="Lang.get("setting.checkBox.makelog")" type="code"/> 213 | </Property> 214 | </Properties> 215 | </Component> 216 | <Component class="javax.swing.JCheckBox" name="jCheckBox2"> 217 | <Properties> 218 | <Property name="selected" type="boolean" value="true"/> 219 | <Property name="text" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor"> 220 | <Connection code="Lang.get("setting.checkBox.showASCII")" type="code"/> 221 | </Property> 222 | </Properties> 223 | </Component> 224 | <Component class="javax.swing.JCheckBox" name="jCheckBox3"> 225 | <Properties> 226 | <Property name="selected" type="boolean" value="true"/> 227 | <Property name="text" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor"> 228 | <Connection code="Lang.get("setting.checkBox.showHEX")" type="code"/> 229 | </Property> 230 | </Properties> 231 | </Component> 232 | <Component class="javax.swing.JLabel" name="jLabel2"> 233 | <Properties> 234 | <Property name="text" type="java.lang.String" value="Filter Type"/> 235 | </Properties> 236 | </Component> 237 | <Component class="javax.swing.JLabel" name="jLabel5"> 238 | <Properties> 239 | <Property name="text" type="java.lang.String" value="Server Type"/> 240 | </Properties> 241 | </Component> 242 | <Component class="javax.swing.JLabel" name="jLabel6"> 243 | <Properties> 244 | <Property name="text" type="java.lang.String" value="Capture Type"/> 245 | </Properties> 246 | </Component> 247 | <Component class="javax.swing.JComboBox" name="jComboBox2"> 248 | <Properties> 249 | <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor"> 250 | <StringArray count="1"> 251 | <StringItem index="0" value="TCP"/> 252 | </StringArray> 253 | </Property> 254 | </Properties> 255 | </Component> 256 | <Component class="javax.swing.JComboBox" name="jComboBox3"> 257 | <Properties> 258 | <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor"> 259 | <StringArray count="3"> 260 | <StringItem index="0" value="ODINMS"/> 261 | <StringItem index="1" value="TITANMS"/> 262 | <StringItem index="2" value="VANA"/> 263 | </StringArray> 264 | </Property> 265 | </Properties> 266 | </Component> 267 | <Component class="javax.swing.JComboBox" name="jComboBox4"> 268 | <Properties> 269 | <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor"> 270 | <StringArray count="4"> 271 | <StringItem index="0" value="PACKET"/> 272 | <StringItem index="1" value="NPC"/> 273 | <StringItem index="2" value="SHOP"/> 274 | <StringItem index="3" value="SPEED_QUIZ"/> 275 | </StringArray> 276 | </Property> 277 | </Properties> 278 | </Component> 279 | </SubComponents> 280 | </Container> 281 | </SubComponents> 282 | </Form> 283 | --------------------------------------------------------------------------------