I know that it might not be too helpful to anyone but i'm known for sucking alot of cocks when that's not true at all and i'm able to update and i want to prove wrong to those faggots.
handler wise it should be easy. if i forgot anything that you wish to have tell me.
getServerList
getCharListPHP Code:public static MaplePacket getServerList(byte serverId, String serverName, Map<Integer, Integer> channelLoad) {
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.writeShort(SendOpcode.SERVERLIST.getValue());
mplew.write(serverId);
mplew.writeMapleAsciiString(serverName);
mplew.write(ServerConstants.FLAG);
mplew.writeMapleAsciiString(ServerConstants.EVENT_MESSAGE);
mplew.write(0x64); // rate modifier, don't ask O.O!
mplew.write(0x0); // event xp * 2.6 O.O!
mplew.write(0x64); // rate modifier, don't ask O.O!
mplew.writeShort(0); // drop rate * 2.6
int lastChannel = 1;
Set<Integer> channels = channelLoad.keySet();
for (int i = 30; i > 0; i--) {
if (channels.contains(i)) {
lastChannel = i;
break;
}
}
mplew.write(lastChannel);
int load;
for (int i = 1; i <= lastChannel; i++) {
if (channels.contains(i)) {
load = channelLoad.get(i);
} else {
load = 1200;
}
mplew.writeMapleAsciiString(serverName + "-" + i);
mplew.writeInt(load);
mplew.write(serverId);
mplew.writeShort(i - 1);
}
mplew.write0(6); //int + short whatever that is
return mplew.getPacket();
}
addCharEntryPHP Code:public static MaplePacket getCharList(final boolean secondpw, final List<MapleCharacter> chars, int charslots) {
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.writeShort(SendOpcode.CHARLIST.getValue());
mplew.write(0);
mplew.write((byte) chars.size());
for (final MapleCharacter chr : chars) {
addCharEntry(mplew, chr, false, false);
}
mplew.write(1);
mplew.write(0); //v109.2 (my guess: some black cipher related stuff since its all that was added in .2)
mplew.writeInt(charslots);
mplew.writeInt(0);
System.out.println(mplew.toString());
return mplew.getPacket();
}
addCharStatsPHP Code:private static void addCharEntry(final MaplePacketLittleEndianWriter mplew, final MapleCharacter chr, boolean ranking, boolean viewall) {
PacketHelper.addCharStats(mplew, chr);
PacketHelper.addCharLook(mplew, chr, false);
if (chr.getJob().getId() % 1000 >= 800) {
mplew.writeShort(0);
return;
}
if (!viewall) {
mplew.writeShort(0);
}
mplew.write(1);
mplew.writeLong(0); //useless ranking shit
mplew.writeLong(0); //useless ranking shit
/*if (ranking) {
mplew.writeInt(chr.getRank());
mplew.writeInt(chr.getRankMove());
mplew.writeInt(chr.getJobRank());
mplew.writeInt(chr.getJobRankMove());
}*/
}
addCharLookPHP Code:public static void addCharStats(MaplePacketLittleEndianWriter mplew, MapleCharacter chr) {
if (chr.isDemonSlayer()) {
mplew.writeInt(0);
}
mplew.writeInt(chr.getId());
mplew.writeAsciiString(chr.getName(), 13);
mplew.write(chr.getGender());
mplew.write(chr.getSkinColor().getId());
mplew.writeInt(chr.getFace());
mplew.writeInt(chr.getHair());
for (int i = 0; i < 3; i++) {
if (chr.getPet(i) != null) {
mplew.writeLong(chr.getPet(i).getUniqueId());
} else {
mplew.writeLong(0);
}
}
mplew.write(chr.getLevel());
mplew.writeShort(chr.getJob().getId());
mplew.writeShort(chr.getStr());
mplew.writeShort(chr.getDex());
mplew.writeShort(chr.getInt());
mplew.writeShort(chr.getLuk());
mplew.writeInt(chr.getHp());
mplew.writeInt(chr.getMaxHp());
mplew.writeInt(chr.getMp());
mplew.writeInt(chr.getMaxMp());
mplew.writeShort(chr.getRemainingAp());
if (MapleJob.isExtendSPJob(chr.getJobId())) {
chr.getSPTable().addSPData(mplew);
} else {
//mplew.writeShort(chr.getRemainingSp());
mplew.writeShort(0); //remaining sps. not needed in high rate with skill maxer :S
}
mplew.writeInt(chr.getExp());
mplew.writeInt(chr.getFame());
mplew.writeInt(0); //big penis
mplew.writeInt(chr.getMapId());
mplew.write(chr.getInitialSpawnpoint());
mplew.writeInt(0);//time played in seconds
mplew.writeShort(0);//chr.getSpecialJobType()); //1 = db, 2 = cannoneer
if (chr.isDemonSlayer()) {
mplew.writeInt(0);
}
mplew.write(0); //chr.getFatigue()
mplew.writeInt(Integer.parseInt(new SimpleDateFormat("yyyyMMddHH").format(Calendar.getInstance().getTime())));
//MapleTraits t = chr.getTraits();
mplew.writeInt(0); //t.getAmbition()
mplew.writeInt(0); //t.getInsight()
mplew.writeInt(0); //t.getWillpower());
mplew.writeInt(0); //t.getDiligence());
mplew.writeInt(0); //t.getEmpathy());
mplew.writeInt(0); //t.getCharm());
mplew.writeShort(0); //t.getTodaysAmbition());
mplew.writeShort(0); //t.getTodaysInsight());
mplew.writeShort(0); //t.getTodaysWillpower());
mplew.writeShort(0); //t.getTodaysDiligence());
mplew.writeShort(0); //t.getTodaysEmpathy());
mplew.writeShort(0); //t.getTodaysCharm());
mplew.writeInt(0); //chr.getbattleexp
mplew.write(0); //chr.getbattlerank
mplew.writeInt(0); //chr.getbattlepoints
mplew.write(5); //unk
mplew.writeInt(0); //unk
mplew.writeLong(0); //useless fuckery that has to do with time i think
}
getServerIpPHP Code:public static void addCharLook(final MaplePacketLittleEndianWriter mplew, final MapleCharacter chr, final boolean mega) {
mplew.write(chr.getGender());
mplew.write(chr.getSkinColor().getId());
mplew.writeInt(chr.getFace());
mplew.writeShort(chr.getJob().getId());
mplew.write(mega ? 1 : 0);
mplew.writeShort(0);
mplew.writeInt(chr.getHair());
final Map<Byte, Integer> myEquip = new LinkedHashMap<>();
final Map<Byte, Integer> maskedEquip = new LinkedHashMap<>();
MapleInventory equip = chr.getInventory(MapleInventoryType.EQUIPPED);
for (final IItem item : equip.list()) {
if (item.getPosition() < -128) { //not visible
continue;
}
byte pos = (byte) (item.getPosition() * -1);
if (pos < 100 && myEquip.get(pos) == null) {
myEquip.put(pos, item.getItemId());
} else if ((pos > 100 || pos == -128) && pos != 111) {
pos = (byte) (pos == -128 ? 28 : pos - 100);
if (myEquip.get(pos) != null) {
maskedEquip.put(pos, myEquip.get(pos));
}
myEquip.put(pos, item.getItemId());
} else if (myEquip.get(pos) != null) {
maskedEquip.put(pos, item.getItemId());
}
}
for (final Entry<Byte, Integer> entry : myEquip.entrySet()) {
mplew.write(entry.getKey());
mplew.writeInt(entry.getValue());
}
mplew.write(0xFF); // end of visible itens
// masked itens
for (final Entry<Byte, Integer> entry : maskedEquip.entrySet()) {
mplew.write(entry.getKey());
mplew.writeInt(entry.getValue());
}
mplew.write(0xFF); // ending markers
final IItem cWeapon = equip.getItem((byte) -111);
mplew.writeInt(cWeapon != null ? cWeapon.getItemId() : 0);
for (int i = 0; i < 3; i++) {
if (chr.getPet(i) != null) {
mplew.writeInt(chr.getPet(i).getPetId());
} else {
mplew.writeInt(0);
}
}
mplew.write(0); //mercedes ears o.o?
if (chr.isDemonSlayer()) {
mplew.writeInt(0);
}
}
now the interserver stuffPHP Code:public static MaplePacket getServerIP(InetAddress inetAddr, int port, int clientId) {
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.writeShort(SendOpcode.SERVER_IP.getValue());
mplew.writeShort(0);
byte[] addr = inetAddr.getAddress();
mplew.write(addr);
mplew.writeShort(port);
mplew.writeInt(clientId);
mplew.write0(10);
return mplew.getPacket();
}
getCharInfo
addCharacterInfoPHP Code:public static MaplePacket getCharInfo(MapleCharacter chr) {
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.writeShort(SendOpcode.WARP_TO_MAP.getValue());
mplew.writeShort(2);
mplew.writeLong(1);
mplew.writeLong(2);
mplew.writeInt(chr.getClient().getChannel() - 1);
mplew.writeInt(0);
mplew.write(0);
mplew.write(1);
mplew.writeShort(0); //unk
mplew.writeShort(0); //unk
mplew.write(1); //unk
mplew.writeShort(0); //unk
for (int i = 0; i < 3; i++) {
mplew.writeInt(Randomizer.nextInt());
}
addCharacterInfo(mplew, chr);
mplew.write0(70); //alot of unknow shit that doesn't matter
mplew.write(1); //don't ask. if its a 0, you get error 38...
mplew.write0(20);
mplew.writeLong(getTime(System.currentTimeMillis()));
mplew.write(100);
mplew.writeInt(0);
mplew.write(1);
return mplew.getPacket();
}
addInventoryInfoPHP Code:private static void addCharacterInfo(MaplePacketLittleEndianWriter mplew, MapleCharacter chr) {
mplew.writeInt(-1);
mplew.writeInt(-3);
mplew.write0(7);
PacketHelper.addCharStats(mplew, chr);
mplew.write(chr.getBuddylist().getCapacity());
mplew.write(0); //if null = 0 else byte 1 + mapleAsciiString
mplew.write(0); //if null = 0 else byte 1 + mapleAsciiString
mplew.write(0); //if null = 0 else byte 1 + mapleAsciiString
addInventoryInfo(mplew, chr);
mplew.writeInt(0);
addSkillInfo(mplew, chr);
addQuestInfo(mplew, chr);
mplew.writeShort(0);
addRingInfo(mplew, chr);
addTeleportInfo(mplew, chr);
addMonsterBookInfo(mplew, chr);
mplew.writeShort(0);
addAreaInfo(mplew, chr);
if (chr.getJob().isA(MapleJob.WILDHUNTER1) || chr.getJob().isA(MapleJob.WILDHUNTER2) || chr.getJob().isA(MapleJob.WILDHUNTER3) || chr.getJob().isA(MapleJob.WILDHUNTER4)) {
addCapturedInfo(mplew, (byte) 0, chr);
}
mplew.writeShort(0);
mplew.writeShort(0);
mplew.writeShort(0);
}
addItemInfoPHP Code:private static void addInventoryInfo(MaplePacketLittleEndianWriter mplew, MapleCharacter chr) {
mplew.writeInt(chr.getMeso());
mplew.writeInt(0);
for (byte i = 1; i <= 5; i++) {
mplew.write(chr.getInventory(MapleInventoryType.getByType(i)).getSlotLimit());
}
mplew.write(new byte[]{0, 64, -32, -3, 59, 55, 79, 1});
MapleInventory iv = chr.getInventory(MapleInventoryType.EQUIPPED);
Collection<IItem> equippedC = iv.list();
List<Item> equipped = new ArrayList<Item>(equippedC.size());
List<Item> equippedCash = new ArrayList<Item>(equippedC.size());
for (IItem item : equippedC) {
if (item.getPosition() <= -100) {
equippedCash.add((Item) item);
} else {
equipped.add((Item) item);
}
}
Collections.sort(equipped);
for (Item item : equipped) {
addItemInfo(mplew, item);
}
mplew.write(0);
for (Item item : equippedCash) {
addItemInfo(mplew, item);
}
mplew.write(0);
for (IItem item : chr.getInventory(MapleInventoryType.EQUIP).list()) {
addItemInfo(mplew, item);
}
mplew.write(0);
mplew.writeShort(0);
mplew.writeShort(0); // Dragon Equipements
mplew.writeShort(0); // Mechanical Equipments
mplew.writeShort(0);
for (IItem item : chr.getInventory(MapleInventoryType.USE).list()) {
addItemInfo(mplew, item);
}
mplew.write(0);
for (IItem item : chr.getInventory(MapleInventoryType.SETUP).list()) {
addItemInfo(mplew, item);
}
mplew.write(0);
for (IItem item : chr.getInventory(MapleInventoryType.ETC).list()) {
//addItemInfo(mplew, item);
}
mplew.write(0);
for (IItem item : chr.getInventory(MapleInventoryType.CASH).list()) {
addItemInfo(mplew, item);
}
mplew.write(0);
mplew.write(0);
mplew.writeInt(-1);
mplew.writeInt(0);
}
addSkillInfoPHP Code:private static void addItemInfo(MaplePacketLittleEndianWriter mplew, IItem item, boolean zeroPosition, boolean inTrade) {
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
boolean isCash = ii.isCash(item.getItemId());
boolean isPet = item.getPetId() > -1;
boolean isRing = false;
IEquip equip = null;
byte pos = item.getPosition();
if (item.getType() == 1) {
equip = (IEquip) item;
isRing = equip.getRingId() > -1;
}
if (!zeroPosition) {
if (equip != null) {
if (pos < 0) {
pos = (byte) (pos * -1);
}
mplew.writeShort(pos > 100 ? pos - 100 : pos);
} else {
mplew.write(pos);
}
}
mplew.write(item.getType());
mplew.writeInt(item.getItemId());
mplew.write(isCash ? 1 : 0);
if (isCash) {
mplew.writeLong(item.getCashId());
}
mplew.write(0); //unk
mplew.write(ITEM_MAGIC); //experation time - start
mplew.write(NON_EXPIRE2); // Note: too lazy to make a new method for expiration time :D
mplew.writeInt(-1); // expiration time - end
if (isPet) {
MaplePet pet = item.getPet();
mplew.writeAsciiString(StringUtil.getRightPaddedStr(pet.getName(), '\000', 13));
mplew.write(pet.getLevel());
mplew.writeShort(pet.getCloseness());
mplew.write(pet.getFullness());
addExpirationTime(mplew, item.getExpiration());
mplew.writeInt(0);
mplew.write(new byte[]{80, 70});
mplew.writeInt(0);
return;
}
if (equip == null) {
mplew.writeShort(item.getQuantity());
mplew.writeMapleAsciiString(item.getOwner());
mplew.writeShort(item.getFlag());
if (ItemConstants.isRechargable(item.getItemId())) {
mplew.writeInt(2);
mplew.write(new byte[]{84, 0, 0, 52});
}
return;
}
mplew.write(equip.getUpgradeSlots());
mplew.write(equip.getLevel());
mplew.writeShort(equip.getStr());
mplew.writeShort(equip.getDex());
mplew.writeShort(equip.getInt());
mplew.writeShort(equip.getLuk());
mplew.writeShort(equip.getHp());
mplew.writeShort(equip.getMp());
mplew.writeShort(equip.getWatk());
mplew.writeShort(equip.getMatk());
mplew.writeShort(equip.getWdef());
mplew.writeShort(equip.getMdef());
mplew.writeShort(equip.getAcc());
mplew.writeShort(equip.getAvoid());
mplew.writeShort(equip.getHands());
mplew.writeShort(equip.getSpeed());
mplew.writeShort(equip.getJump());
mplew.writeMapleAsciiString(equip.getOwner());
mplew.writeShort(equip.getFlag());
mplew.write(0);
mplew.write(equip.getItemLevel());
mplew.writeShort(0);
mplew.writeShort(equip.getItemExp());
mplew.writeInt(-1); //Item durability
mplew.writeInt(equip.getVicious());
mplew.writeShort(0);
mplew.write(equip.isPotentialByte());
mplew.write(equip.getStarsByte());
mplew.writeShort(equip.getPotentialStats(1)); //rare
mplew.writeShort(equip.getPotentialStats(2)); //epic
mplew.writeShort(equip.getPotentialStats(3)); //unique
mplew.writeShort(equip.getPotentialStats(4)); //TODO: legendary
mplew.writeShort(0); //HpR
mplew.writeShort(0); //MpR
if (!isCash) {
mplew.writeLong(-1);
}
mplew.writeLong(getTime(-2));
mplew.writeInt(-1);
}
addQuestInfoPHP Code:private static void addSkillInfo(MaplePacketLittleEndianWriter mplew, MapleCharacter chr) {
mplew.write(0);
mplew.write(1);
final Map<ISkill, SkillEntry> skills = chr.getSkills();
mplew.writeShort(skills.size());
for (final Entry<ISkill, SkillEntry> skill : skills.entrySet()) {
mplew.writeInt(((ISkill) skill.getKey()).getId());
if (((ISkill) skill.getKey()).getId() >= 92000000) {
mplew.writeShort(63);
mplew.write(0);
mplew.write(((MapleCharacter.SkillEntry) skill.getValue()).skillevel);
addExpirationTime(mplew, ((MapleCharacter.SkillEntry) skill.getValue()).expiration);
} else {
mplew.writeInt(((MapleCharacter.SkillEntry) skill.getValue()).skillevel);
addExpirationTime(mplew, ((MapleCharacter.SkillEntry) skill.getValue()).expiration);
if (((ISkill) skill.getKey()).isFourthJob()) {
mplew.writeInt(((MapleCharacter.SkillEntry) skill.getValue()).masterlevel);
}
}
}
mplew.writeShort(chr.getAllCooldowns().size());
for (PlayerCoolDownValueHolder cooling : chr.getAllCooldowns()) {
mplew.writeInt(cooling.skillId);
int timeLeft = (int) (cooling.length + cooling.startTime - System.currentTimeMillis());
mplew.writeInt(timeLeft / 1000);
}
}
addRingInfoPHP Code:private static void addQuestInfo(MaplePacketLittleEndianWriter mplew, MapleCharacter chr) {
mplew.write(1);
mplew.writeShort(chr.getStartedQuestsSize());
for (MapleQuestStatus q : chr.getStartedQuests()) {
mplew.writeShort(q.getQuest().getId());
mplew.writeMapleAsciiString(q.getQuestData());
if (q.getQuest().getInfoNumber() > 0) {
mplew.writeShort(q.getQuest().getInfoNumber());
mplew.writeMapleAsciiString(Integer.toString(q.getMedalProgress()));
}
}
List<MapleQuestStatus> completed = chr.getCompletedQuests();
mplew.writeShort(0);
mplew.write(1);
mplew.writeShort(completed.size());
for (MapleQuestStatus q : completed) {
mplew.writeShort(q.getQuest().getId());
int time = getQuestTimestamp(q.getCompletionTime());
mplew.writeInt(time);
mplew.writeInt(time);
}
}
addTeleportInfoPHP Code:private static void addRingInfo(MaplePacketLittleEndianWriter mplew, MapleCharacter chr) {
mplew.writeShort(chr.getCrushRings().size());
for (MapleRing ring : chr.getCrushRings()) {
mplew.writeInt(ring.getPartnerChrId());
mplew.writeAsciiString(getRightPaddedStr(ring.getPartnerName(), '\000', 13));
mplew.writeInt(ring.getRingId());
mplew.writeInt(0);
mplew.writeInt(ring.getPartnerRingId());
mplew.writeInt(0);
}
mplew.writeShort(chr.getFriendshipRings().size());
for (MapleRing ring : chr.getFriendshipRings()) {
mplew.writeInt(ring.getPartnerChrId());
mplew.writeAsciiString(getRightPaddedStr(ring.getPartnerName(), '\000', 13));
mplew.writeInt(ring.getRingId());
mplew.writeInt(0);
mplew.writeInt(ring.getPartnerRingId());
mplew.writeInt(0);
mplew.writeInt(ring.getItemId());
}
mplew.writeShort(chr.getMarriageRing() != null ? 1 : 0);
int marriageId = 30000;
if (chr.getMarriageRing() != null) {
mplew.writeInt(marriageId);
mplew.writeInt(chr.getId());
mplew.writeInt(chr.getMarriageRing().getPartnerChrId());
mplew.writeShort(3);
mplew.writeInt(chr.getMarriageRing().getRingId());
mplew.writeInt(chr.getMarriageRing().getPartnerRingId());
mplew.writeAsciiString(getRightPaddedStr(chr.getName(), '\000', 13));
mplew.writeAsciiString(getRightPaddedStr(chr.getMarriageRing().getPartnerName(), '\000', 13));
}
}
addMonsterBookInfoPHP Code:private static void addTeleportInfo(MaplePacketLittleEndianWriter mplew, MapleCharacter chr) {
int[] tele = chr.getTrockMaps();
int[] viptele = chr.getVipTrockMaps();
for (int i = 0; i < 5; i++) {
//mplew.writeInt(tele[i]);
mplew.writeInt(999999999);
}
for (int i = 0; i < 10; i++) {
//mplew.writeInt(viptele[i]);
mplew.writeInt(999999999);
}
for (int i = 0; i < 13; i++) {
mplew.writeInt(999999999);
}
for (int i = 0; i < 13; i++) {
mplew.writeInt(999999999);
}
}
addAreaInfoPHP Code:private static void addMonsterBookInfo(MaplePacketLittleEndianWriter mplew, MapleCharacter chr) {
mplew.writeInt(chr.getMonsterBookCover()); //monster book cover
mplew.write(0);
Map<Integer, Integer> cards = chr.getMonsterBook().getCards();
mplew.writeShort(cards.size());
for (Entry<Integer, Integer> all : cards.entrySet()) {
mplew.writeShort(all.getKey() % 10000); // 아이디
mplew.write(all.getValue()); // 레벨
}
mplew.writeInt(-1);
mplew.writeShort(0);
}
addCapturedInfo (didn't touch this yet, in case any change occured to it from v97 to v110)PHP Code:private static void addAreaInfo(MaplePacketLittleEndianWriter mplew, MapleCharacter chr) {
Map<Short, String> areaInfos = chr.getAreaInfos();
mplew.writeShort(areaInfos.size());
for (Short area : areaInfos.keySet()) {
mplew.writeShort(area.shortValue());
mplew.writeMapleAsciiString((String) areaInfos.get(area));
}
}
enjoyPHP Code:public static MaplePacket addCapturedInfo(MaplePacketLittleEndianWriter mplew, byte id, MapleCharacter chr) {
mplew.write(id);
for (int i = 0; i < 5; i++) {
mplew.writeInt(0);
}
return mplew.getPacket();
}
might not work with a demon slayer but you should be able to get ingame with an explorer or something

