- Joined
- Jun 7, 2020
- Messages
- 4
- Reaction score
- 0
Hi all,
I'm Porting MoopleEurope (a EMS v65 source, github.com/Hendi48/MoopleEurope) forward to EMS v70 for a nostalgia project with a friend.
Login, world/channel select, char list, char creation and char selection are all fully working now. The one remaining "blocker" is the actual login (after selecting the char). What we also tried so far is to compare it to MapleLand v92 (GMS), which should be more or less similar as both are pretty the latest preBB ones (iirc EMS hat BB at v73, while v70-73 was just events...?)
So: the header's length seems to be in the right ballpark (no overrun), but something in its content is still wrong, and it's specific enough that the client doesn't reject it outright - it just never finishes bringing the character into the world. I think the culprit might be in SetFieldReference.java
SetField Reference
I'm Porting MoopleEurope (a EMS v65 source, github.com/Hendi48/MoopleEurope) forward to EMS v70 for a nostalgia project with a friend.
Login, world/channel select, char list, char creation and char selection are all fully working now. The one remaining "blocker" is the actual login (after selecting the char). What we also tried so far is to compare it to MapleLand v92 (GMS), which should be more or less similar as both are pretty the latest preBB ones (iirc EMS hat BB at v73, while v70-73 was just events...?)
So: the header's length seems to be in the right ballpark (no overrun), but something in its content is still wrong, and it's specific enough that the client doesn't reject it outright - it just never finishes bringing the character into the world. I think the culprit might be in SetFieldReference.java
SetField Reference
public static byte[] getCharInfo(MapleCharacter chr) {
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.writeShort(SendOpcode.SET_FIELD.getValue()); // opcode confirmed correct
mplew.writeShort(2);
mplew.writeLong(1);
mplew.writeLong(2);
mplew.writeLong(chr.getClient().getChannel() - 1);
mplew.write(chr.getMap().getPortals().size());
mplew.write(1); // "connect packet" flag
mplew.writeShort(0);
for (int i = 0; i < 3; i++) {
mplew.writeInt(Randomizer.nextInt()); // CRand seeds
}
addCharacterInfo(mplew, chr);
mplew.writeInt(0); // "lucky logout gift"
mplew.writeInt(0); // SN 1
mplew.writeInt(0); // SN 2
mplew.writeInt(0); // SN 3
mplew.writeLong(getTime(System.currentTimeMillis()));
return mplew.getPacket();
}
private static void addCharacterInfo(final MaplePacketLittleEndianWriter mplew, MapleCharacter chr) {
long mask = -1L;
mplew.writeLong(mask);
mplew.write(0);
addCharStats(mplew, chr);
mplew.write(chr.getBuddylist().getCapacity());
if (chr.getLinkedName() == null) {
mplew.write(0);
} else {
mplew.write(1);
mplew.writeMapleAsciiString(chr.getLinkedName());
}
mplew.writeInt(chr.getMeso());
addInventoryInfo(mplew, chr);
addSkillInfo(mplew, chr);
addQuestInfo(mplew, chr);
addMiniGameInfo(mplew, chr);
addRingInfo(mplew, chr);
addTeleportInfo(mplew, chr);
addMonsterBookInfo(mplew, chr);
addNewYearInfo(mplew, chr);
addQuestEx(mplew, chr);
mplew.writeShort(0);
mplew.writeShort(0); // "WildHunterInfo" - also tried excluding this bit, as im not sure whether Resistance was already in the files. I remember though you could create one with /m-Exploit before they got released. but idk when it was
}
private static void addCharStats(final MaplePacketLittleEndianWriter mplew, MapleCharacter chr) {
mplew.writeInt(chr.getId());
mplew.writeAsciiString(getRightPaddedStr(chr.getName(), '\0', 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++) {
mplew.writeLong(chr.getPet(i) != null ? chr.getPet(i).getUniqueId() : 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.writeShort(chr.getHp());
mplew.writeShort(chr.getMaxHp());
mplew.writeShort(chr.getMp());
mplew.writeShort(chr.getMaxMp());
mplew.writeShort(chr.getRemainingAp());
mplew.writeShort(chr.getRemainingSp());
mplew.writeInt(chr.getExp());
mplew.writeShort(chr.getFame());
mplew.writeInt(chr.getMapId());
mplew.write(chr.getInitialSpawnpoint());
mplew.writeInt(0); // play time
mplew.writeShort(0); // "nSubJob" - confirmed correct position, this and CREATE_CHAR's
// matching field were the two confirmed real v65->v70 additions
}
- Server Information
- MoopleEurope V65, updated to v70
Last edited:

