package tools.packet; import client.*; import client.inventory.*; import constants.GameConstants; import constants.ItemConstants; import constants.ServerConstants; import handling.Buffstat; import handling.world.MapleCharacterLook; import java.util.*; import java.util.Map.Entry; import server.CashItem; import server.MapleItemInformationProvider; import server.movement.LifeMovementFragment; import server.quest.MapleQuest; import server.shops.MapleShop; import server.shops.MapleShopItem; import server.stores.AbstractPlayerStore; import server.stores.IMaplePlayerShop; import tools.BitTools; import tools.DateUtil; import tools.HexTool; import tools.KoreanDateUtil; import tools.Pair; import tools.StringUtil; import tools.Triple; import tools.data.MaplePacketLittleEndianWriter; public class PacketHelper { public static final long FT_UT_OFFSET = 116444592000000000L; public static final long MAX_TIME = 150842304000000000L; public static final long ZERO_TIME = 94354848000000000L; public static final long PERMANENT = 150841440000000000L; public static long getKoreanTimestamp(long realTimestamp) { return getTime(realTimestamp); } public static long getTime(long realTimestamp) { if (realTimestamp == -1L) { // 00 80 05 BB 46 E6 17 02, 1/1/2079 return MAX_TIME; } if (realTimestamp == -2L) { // 00 40 E0 FD 3B 37 4F 01, 1/1/1900 return ZERO_TIME; } if (realTimestamp == -3L) { return PERMANENT; } return realTimestamp * 10000L + 116444592000000000L; } public static long decodeTime(long fakeTimestamp) { if (fakeTimestamp == 150842304000000000L) { return -1L; } if (fakeTimestamp == 94354848000000000L) { return -2L; } if (fakeTimestamp == 150841440000000000L) { return -3L; } return (fakeTimestamp - 116444592000000000L) / 10000L; } public static long getFileTimestamp(long timeStampinMillis, boolean roundToMinutes) { if (TimeZone.getDefault().inDaylightTime(new Date())) { timeStampinMillis -= 3600000L; } long time; if (roundToMinutes) { time = timeStampinMillis / 1000L / 60L * 600000000L; } else { time = timeStampinMillis * 10000L; } return time + 116444592000000000L; } public static void addImageInfo(MaplePacketLittleEndianWriter mplew, byte[] image) { mplew.writeInt(image.length); mplew.write(image); } public static void addStartedQuestInfo(MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { boolean newPacket = true; mplew.write(newPacket); if (newPacket) { final List<MapleQuestStatus> started = chr.getStartedQuests(); mplew.writeShort(started.size()); for (MapleQuestStatus q : started) { mplew.writeShort(q.getQuest().getId()); if (q.hasMobKills()) { StringBuilder sb = new StringBuilder(); for (Iterator i$ = q.getMobKills().values().iterator(); i$.hasNext();) { int kills = ((Integer) i$.next()); sb.append(StringUtil.getLeftPaddedStr(String.valueOf(kills), '0', 3)); } mplew.writeMapleAsciiString(sb.toString()); } else { mplew.writeMapleAsciiString(q.getCustomData() == null ? "" : q.getCustomData()); } } } else { final List<MapleQuestStatus> started = chr.getStartedQuests(); mplew.writeShort(started.size()); for (MapleQuestStatus q : started) { mplew.writeShort(q.getQuest().getId()); } } } /*mplew.write(1); final List<MapleQuestStatus> started = chr.getStartedQuests(); mplew.writeShort(started.size()); for (MapleQuestStatus q : started) { mplew.writeShort(q.getQuest().getId()); if (q.hasMobKills()) { StringBuilder sb = new StringBuilder(); for (Iterator i$ = q.getMobKills().values().iterator(); i$.hasNext();) { int kills = ((Integer) i$.next()).intValue(); sb.append(StringUtil.getLeftPaddedStr(String.valueOf(kills), '0', 3)); } mplew.writeMapleAsciiString(sb.toString()); } else { mplew.writeMapleAsciiString(q.getCustomData() == null ? "" : q.getCustomData()); } } // addNXQuestInfo(mplew, chr); }*/ public static void addNXQuestInfo(MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { mplew.writeShort(0); /* mplew.writeShort(7); mplew.writeMapleAsciiString("1NX5211068"); mplew.writeMapleAsciiString("1"); mplew.writeMapleAsciiString("SE20130619"); mplew.writeMapleAsciiString("20130626060823"); mplew.writeMapleAsciiString("99NX5533018"); mplew.writeMapleAsciiString("1"); mplew.writeMapleAsciiString("1NX1003792"); mplew.writeMapleAsciiString("1"); mplew.writeMapleAsciiString("1NX1702337"); mplew.writeMapleAsciiString("1"); mplew.writeMapleAsciiString("1NX9102857"); mplew.writeMapleAsciiString("1"); mplew.writeMapleAsciiString("SE20130116"); mplew.writeMapleAsciiString("1"); */ } public static void addCompletedQuestInfo(MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { boolean newPacket = true; mplew.write(newPacket); if (newPacket) { final List<MapleQuestStatus> completed = chr.getCompletedQuests(); mplew.writeShort(completed.size()); for (MapleQuestStatus q : completed) { mplew.writeShort(q.getQuest().getId()); mplew.writeLong(KoreanDateUtil.getQuestTimestamp(q.getCompletionTime())); //v139 changed from long to int } } else { final List<MapleQuestStatus> completed = chr.getCompletedQuests(); mplew.writeShort(completed.size()); for (MapleQuestStatus q : completed) { mplew.writeShort(q.getQuest().getId()); } } } /*mplew.write(1); final List<MapleQuestStatus> completed = chr.getCompletedQuests(); mplew.writeShort(completed.size()); for (MapleQuestStatus q : completed) { mplew.writeShort(q.getQuest().getId()); //mplew.writeLong(KoreanDateUtil.getQuestTimestamp(q.getCompletionTime())); mplew.writeLong(getTime(q.getCompletionTime())); //v139 changed from long to int } }*/ public static void addSkillInfo(MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { final Map<Skill, SkillEntry> skills = chr.getSkills(); boolean newPacket = true; mplew.write(newPacket); if (newPacket) { mplew.writeShort(skills.size()); for (Entry<Skill, SkillEntry> skill : skills.entrySet()) { mplew.writeInt(((Skill) skill.getKey()).getId()); if (((Skill) skill.getKey()).isLinkSkills()) { mplew.writeInt(((SkillEntry) skill.getValue()).teachId); } else if (((Skill) skill.getKey()).isTeachSkills()) { mplew.writeInt(((SkillEntry) skill.getValue()).teachId > 0 ? ((SkillEntry) skill.getValue()).teachId : chr.getId()); } else { mplew.writeInt(((SkillEntry) skill.getValue()).skillLevel); } addExpirationTime(mplew, ((SkillEntry) skill.getValue()).expiration); if (((Skill) skill.getKey()).isFourthJob()) { mplew.writeInt(((SkillEntry) skill.getValue()).masterlevel); } if (((Skill) skill.getKey()).getId() == 40020002 || ((Skill) skill.getKey()).getId() == 80000004) { mplew.writeInt(0); } } int v87 = 0; mplew.writeShort(v87); for (int i = 0; i < v87; i++) { mplew.writeInt(0); mplew.writeShort(0); } } else { final Map<Integer, Integer> skillsWithoutMax = new LinkedHashMap<>(); final Map<Integer, Long> skillsWithExpiration = new LinkedHashMap<>(); final Map<Integer, Byte> skillsWithMax = new LinkedHashMap<>(); for (final Entry<Skill, SkillEntry> skill : skills.entrySet()) { skillsWithoutMax.put(((Skill) skill.getKey()).getId(), ((SkillEntry) skill.getValue()).skillLevel); if (((SkillEntry) skill.getValue()).expiration > 0L) { skillsWithExpiration.put(((Skill) skill.getKey()).getId(), ((SkillEntry) skill.getValue()).expiration); } if (((Skill) skill.getKey()).isFourthJob()) { skillsWithMax.put(((Skill) skill.getKey()).getId(), ((SkillEntry) skill.getValue()).masterlevel); } } int amount = skillsWithoutMax.size(); mplew.writeShort(amount); for (final Entry<Integer, Integer> x : skillsWithoutMax.entrySet()) { mplew.writeInt((x.getKey())); mplew.writeInt((x.getValue())); } mplew.writeShort(0); amount = skillsWithExpiration.size(); mplew.writeShort(amount); for (final Entry<Integer, Long> x : skillsWithExpiration.entrySet()) { mplew.writeInt((x.getKey())); mplew.writeLong((x.getValue())); } mplew.writeShort(0); amount = skillsWithMax.size(); mplew.writeShort(amount); for (final Entry<Integer, Byte> x : skillsWithMax.entrySet()) { mplew.writeInt((x.getKey())); mplew.writeInt((x.getValue())); } mplew.writeShort(0); } } public static void addCoolDownInfo(MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { final List<MapleCoolDownValueHolder> cd = chr.getCooldowns(); mplew.writeShort(cd.size()); for (MapleCoolDownValueHolder cooling : cd) { mplew.writeInt(cooling.skillId); mplew.writeInt((int) (cooling.length + cooling.startTime - System.currentTimeMillis()) / 1000); } } public static void addRocksInfo(MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { int[] mapz = chr.getRegRocks(); for (int i = 0; i < 5; i++) { mplew.writeInt(mapz[i]); } int[] map = chr.getRocks(); for (int i = 0; i < 10; i++) { mplew.writeInt(map[i]); } int[] maps = chr.getHyperRocks(); for (int i = 0; i < 13; i++) { mplew.writeInt(maps[i]); } // for (int i = 0; i < 13; i++) { // mplew.writeInt(maps[i]); // } } public static void addMiniGameInfo(MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { short size = 0; mplew.writeShort(size); for (int i = 0; i < size; i++) { mplew.writeInt(0); mplew.writeInt(0); mplew.writeInt(0); mplew.writeInt(0); mplew.writeInt(0); mplew.write(0); } } public static void addRingInfo(MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { Triple<List<MapleRing>, List<MapleRing>, List<MapleRing>> aRing = chr.getRings(true); List<MapleRing> cRing = aRing.getLeft(); mplew.writeShort(cRing.size()); for (MapleRing ring : cRing) { mplew.writeInt(ring.getPartnerChrId()); mplew.writeAsciiString(ring.getPartnerName(), 15); mplew.writeLong(ring.getRingId()); mplew.writeLong(ring.getPartnerRingId()); } List<MapleRing> fRing = aRing.getMid(); mplew.writeShort(fRing.size()); for (MapleRing ring : fRing) { mplew.writeInt(ring.getPartnerChrId()); mplew.writeAsciiString(ring.getPartnerName(), 15); mplew.writeLong(ring.getRingId()); mplew.writeLong(ring.getPartnerRingId()); mplew.writeInt(ring.getItemId()); } List<MapleRing> mRing = aRing.getRight(); mplew.writeShort(mRing.size()); int marriageId = 30000; for (MapleRing ring : mRing) { mplew.writeInt(marriageId); mplew.writeInt(chr.getId()); mplew.writeInt(ring.getPartnerChrId()); mplew.writeShort(3); mplew.writeInt(ring.getItemId()); mplew.writeInt(ring.getItemId()); mplew.writeAsciiString(chr.getName(), 15); mplew.writeAsciiString(ring.getPartnerName(), 15); } } public static void addMoneyInfo(MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { mplew.writeLong(chr.getMeso()); } public static void addInventoryInfo(MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { mplew.write(chr.getInventory(MapleInventoryType.EQUIP).getSlotLimit()); mplew.write(chr.getInventory(MapleInventoryType.USE).getSlotLimit()); mplew.write(chr.getInventory(MapleInventoryType.SETUP).getSlotLimit()); mplew.write(chr.getInventory(MapleInventoryType.ETC).getSlotLimit()); mplew.write(chr.getInventory(MapleInventoryType.CASH).getSlotLimit()); MapleQuestStatus stat = chr.getQuestNoAdd(MapleQuest.getInstance(122700)); if ((stat != null) && (stat.getCustomData() != null) && (Long.parseLong(stat.getCustomData()) > System.currentTimeMillis())) { mplew.writeLong(getTime(Long.parseLong(stat.getCustomData()))); } else { mplew.writeLong(getTime(-2L)); } mplew.write(0); MapleInventory iv = chr.getInventory(MapleInventoryType.EQUIPPED); final List<Item> equipped = iv.newList(); Collections.sort(equipped); for (Item item : equipped) { if ((item.getPosition() < 0) && (item.getPosition() > -100)) {//普通裝備 addItemPosition(mplew, item, false, false); addItemInfo(mplew, item, chr); } } mplew.writeShort(0);//1 for (Item item : equipped) { if ((item.getPosition() <= -100) && (item.getPosition() > -1000)) {//現金裝備 addItemPosition(mplew, item, false, false); addItemInfo(mplew, item, chr); } } mplew.writeShort(0);//2 iv = chr.getInventory(MapleInventoryType.EQUIP); for (Item item : iv.list()) {//裝備欄 addItemPosition(mplew, item, false, false); addItemInfo(mplew, item, chr); } mplew.writeShort(0);//3 for (Item item : equipped) { if ((item.getPosition() <= -1000) && (item.getPosition() > -1100)) {//龍魔龍裝備 addItemPosition(mplew, item, false, false); addItemInfo(mplew, item, chr); } } mplew.writeShort(0);//4 for (Item item : equipped) { if ((item.getPosition() <= -1100) && (item.getPosition() > -1200)) {//機甲裝備 addItemPosition(mplew, item, false, false); addItemInfo(mplew, item, chr); } } mplew.writeShort(0);//5 for (Item item : equipped) { if ((item.getPosition() <= -1200) && (item.getPosition() > -1300)) {//機器人的現金裝備 addItemPosition(mplew, item, false, false); addItemInfo(mplew, item, chr); } } mplew.writeShort(0);//6 for (Item item : equipped) { if ((item.getPosition() <= -1300) && (item.getPosition() > -1400)) {//天使破壞者裝備 addItemPosition(mplew, item, false, false); addItemInfo(mplew, item, chr); } } mplew.writeShort(0);//7 for (Item item : equipped) { if ((item.getPosition() <= -1400) && (item.getPosition() > -1500)) {//拼圖 addItemPosition(mplew, item, false, false); addItemInfo(mplew, item, chr); } } mplew.writeShort(0);//8 for (Item item : equipped) { if ((item.getPosition() <= -1500) && (item.getPosition() > -1600)) {//未知[未確認] addItemPosition(mplew, item, false, false); addItemInfo(mplew, item, chr); } } mplew.writeShort(0);//9 for (Item item : equipped) { if ((item.getPosition() <= -1600) && (item.getPosition() > -1700)) {//獸魔裝備[未確認] addItemPosition(mplew, item, false, false); addItemInfo(mplew, item, chr); } } mplew.writeShort(0);//10 for (Item item : equipped) { if ((item.getPosition() <= -1700) && (item.getPosition() > -1800)) {//未知[未確認] addItemPosition(mplew, item, false, false); addItemInfo(mplew, item, chr); } } mplew.writeShort(0);//11 for (Item item : equipped) { if ((item.getPosition() <= -5000) && (item.getPosition() > -5003)) {//圖騰 addItemPosition(mplew, item, false, false); addItemInfo(mplew, item, chr); } } mplew.writeShort(0);//12 mplew.writeShort(0);//13 //new143 idk where hai hemmi idk too mplew.writeShort(0);//14 mplew.writeShort(0);//15 mplew.writeShort(0);//16 mplew.writeShort(0);//17 iv = chr.getInventory(MapleInventoryType.USE); // 消耗 for (Item item : iv.list()) { addItemPosition(mplew, item, false, false); addItemInfo(mplew, item, chr); } mplew.write(0);//a iv = chr.getInventory(MapleInventoryType.SETUP); // 裝飾 for (Item item : iv.list()) { addItemPosition(mplew, item, false, false); addItemInfo(mplew, item, chr); } mplew.write(0);//b iv = chr.getInventory(MapleInventoryType.ETC); // 其他 for (Item item : iv.list()) { if (item.getPosition() < 100) { addItemPosition(mplew, item, false, false); addItemInfo(mplew, item, chr); } } mplew.write(0);//c iv = chr.getInventory(MapleInventoryType.CASH); // 特殊(現金欄位) for (Item item : iv.list()) { addItemPosition(mplew, item, false, false); addItemInfo(mplew, item, chr); } mplew.write(0);//d mplew.writeInt(0); mplew.writeInt(chr.getExtendedSlots().size()); for (int i = 0; i < chr.getExtendedSlots().size(); i++) { mplew.writeInt(i); mplew.writeInt(chr.getExtendedSlot(i)); for (Item item : chr.getInventory(MapleInventoryType.ETC).list()) { if ((item.getPosition() > i * 100 + 100) && (item.getPosition() < i * 100 + 200)) { addItemPosition(mplew, item, false, true); addItemInfo(mplew, item, chr); } } mplew.writeInt(-1); } mplew.writeZeroBytes(9);//was9 } public static void addPotionPotInfo(MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { if (chr.getPotionPots() == null) { mplew.writeInt(0); return; } mplew.writeInt(chr.getPotionPots().size()); for (MaplePotionPot p : chr.getPotionPots()) { mplew.writeInt(p.getId()); mplew.writeInt(p.getMaxValue()); mplew.writeInt(p.getHp()); mplew.writeInt(0); mplew.writeInt(p.getMp()); mplew.writeLong(PacketHelper.getTime(p.getStartDate())); mplew.writeLong(PacketHelper.getTime(p.getEndDate())); } } public static void addCharCreateStats(MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { mplew.writeInt(chr.getId()); mplew.writeAsciiString(chr.getName(), 15); mplew.write(chr.getGender()); mplew.write(0); // addCharCreateStats unk mplew.write(chr.getSkinColor()); mplew.writeInt(chr.getFace()); mplew.writeInt(chr.getHair()); mplew.write(-1);//176+ mplew.write(0);//176+ mplew.write(0);//176+ mplew.write(chr.getLevel()); mplew.writeShort(chr.getJob()); chr.getStat().connectData(mplew, chr); mplew.writeShort(chr.getRemainingAp()); if (GameConstants.isSeparatedSp(chr.getJob())) { int size = chr.getRemainingSpSize(); mplew.write(size); for (int i = 0; i < chr.getRemainingSps().length; i++) { if (chr.getRemainingSp(i) > 0) { mplew.write(i + 1); mplew.writeInt(chr.getRemainingSp(i)); } } } else { mplew.writeShort(chr.getRemainingSp()); } mplew.writeLong(chr.getExp()); mplew.writeInt(chr.getFame()); mplew.writeInt(0); // 未知 mplew.writeLong(chr.getGachExp()); mplew.writeLong(DateUtil.getFileTimestamp(System.currentTimeMillis())); mplew.writeInt(chr.getMapId()); mplew.write(chr.getInitialSpawnpoint()); mplew.writeShort(chr.getSubcategory()); if (MapleJob.is惡魔(chr.getJob()) || MapleJob.is傑諾(chr.getJob()) || MapleJob.is幻獸師(chr.getJob())) { mplew.writeInt(chr.getFaceMarking()); } mplew.write(chr.getFatigue()); mplew.writeInt(GameConstants.getCurrentDate()); for (MapleTrait.MapleTraitType t : MapleTrait.MapleTraitType.values()) {//性向,循環6次 mplew.writeInt(chr.getTrait(t).getTotalExp()); } //idb - 21 for (MapleTrait.MapleTraitType t : MapleTrait.MapleTraitType.values()) {//性向,循環6次 mplew.writeShort(0); // today's trait points } mplew.write(0); mplew.writeLong(getTime(-2L)); mplew.writeInt(chr.getStat().pvpExp); mplew.write(chr.getStat().pvpRank); mplew.writeInt(chr.getBattlePoints()); mplew.write(6); // idk mplew.write(7); // TODO JUMP mplew.writeInt(0); mplew.writeInt(0); addPartTimeJob(mplew, MapleCharacter.getPartTime(chr.getId())); chr.getCharacterCard().connectData(mplew); mplew.writeReversedLong(getTime(-2)); mplew.write(0); // 178+ mplew.writeZeroBytes(25); mplew.write(0); mplew.write(0); mplew.write(0); mplew.write(0); mplew.write(0); } public static void addCharStats(MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { mplew.writeInt(chr.getId()); mplew.writeAsciiString(chr.getName(), 15); mplew.write(chr.getGender()); mplew.write(1); // addCharCreateStats unk mplew.write(chr.getSkinColor()); mplew.writeInt(chr.getFace()); mplew.writeInt(chr.getHair()); mplew.write(-1);//176+ mplew.writeShort(0);//176+ mplew.write(chr.getLevel()); mplew.writeShort(chr.getJob()); chr.getStat().connectData(mplew, chr); mplew.writeShort(chr.getRemainingAp()); if (GameConstants.isSeparatedSp(chr.getJob())) { int size = chr.getRemainingSpSize(); mplew.write(size); for (int i = 0; i < chr.getRemainingSps().length; i++) { if (chr.getRemainingSp(i) > 0) { mplew.write(i + 1); mplew.writeInt(chr.getRemainingSp(i)); } } } else { mplew.writeShort(chr.getRemainingSp()); } mplew.writeLong(chr.getExp()); mplew.writeInt(chr.getFame()); mplew.writeInt(0); // 未知 mplew.writeLong(chr.getGachExp()); mplew.writeLong(getTime(-2)); mplew.writeInt(chr.getMapId()); mplew.write(chr.getInitialSpawnpoint()); mplew.writeShort(chr.getSubcategory()); if (MapleJob.is惡魔(chr.getJob()) || MapleJob.is傑諾(chr.getJob()) || MapleJob.is幻獸師(chr.getJob())) { mplew.writeInt(chr.getFaceMarking()); } mplew.write(chr.getFatigue()); mplew.writeInt(GameConstants.getCurrentDate()); for (MapleTrait.MapleTraitType t : MapleTrait.MapleTraitType.values()) { mplew.writeInt(chr.getTrait(t).getTotalExp()); } for (MapleTrait.MapleTraitType t : MapleTrait.MapleTraitType.values()) { mplew.writeShort(0); // today's trait points } mplew.write(0); mplew.writeLong(getTime(-2L)); mplew.writeInt(chr.getStat().pvpExp); mplew.write(chr.getStat().pvpRank); mplew.writeInt(chr.getBattlePoints()); mplew.write(6);//idk mplew.write(7);//TODO JUMP mplew.writeInt(0); mplew.writeInt(0); addPartTimeJob(mplew, MapleCharacter.getPartTime(chr.getId())); chr.getCharacterCard().connectData(mplew); mplew.writeReversedLong(getTime(-2)); mplew.write(0); // 178+ mplew.writeZeroBytes(25); mplew.write(0); mplew.write(0); mplew.write(0); mplew.write(0); mplew.write(0); } public static void addCharLook(MaplePacketLittleEndianWriter mplew, MapleCharacterLook chr, boolean mega, boolean second) { mplew.write(second ? chr.getSecondGender() : chr.getGender()); mplew.write(second ? chr.getSecondSkinColor() : chr.getSkinColor()); mplew.writeInt(second ? chr.getSecondFace() : chr.getFace()); mplew.writeInt(chr.getJob()); mplew.write(mega ? 0 : 1); mplew.writeInt(second ? chr.getSecondHair() : chr.getHair()); final Map<Byte, Integer> myEquip = new LinkedHashMap<>(); final Map<Byte, Integer> maskedEquip = new LinkedHashMap<>(); final Map<Byte, Integer> equip = second ? chr.getSecondEquips(true) : chr.getEquips(true); for (final Entry<Byte, Integer> item : equip.entrySet()) { if ((item.getKey()) < -127) { continue; } byte pos = (byte) ((item.getKey()) * -1); if ((pos < 100) && (myEquip.get(pos) == null)) { myEquip.put(pos, item.getValue()); } else if ((pos > 100) && (pos != 111)) { pos = (byte) (pos - 100); if (myEquip.get(pos) != null) { maskedEquip.put(pos, myEquip.get(pos)); } myEquip.put(pos, item.getValue()); } else if (myEquip.get(pos) != null) { maskedEquip.put(pos, item.getValue()); } } final Map<Byte, Integer> totemEquip = chr.getTotems(); for (Map.Entry entry : myEquip.entrySet()) { int weapon = ((Integer) entry.getValue()); if (ItemConstants.武器類型(weapon) == (second ? MapleWeaponType.琉 : MapleWeaponType.璃)) { continue; } mplew.write(((Byte) entry.getKey())); mplew.writeInt(((Integer) entry.getValue())); } mplew.write(0xFF); for (Map.Entry entry : maskedEquip.entrySet()) { mplew.write(((Byte) entry.getKey())); mplew.writeInt(((Integer) entry.getValue())); } mplew.write(0xFF); for (Map.Entry entry : totemEquip.entrySet()) { mplew.write(((Byte) entry.getKey())); mplew.writeInt(((Integer) entry.getValue())); } mplew.write(0xFF); boolean zero = MapleJob.is神之子(chr.getJob()); Integer cWeapon = equip.get(Byte.valueOf((byte) -111)); Integer Weapon = equip.get(Byte.valueOf((byte) -11)); Integer Shield = equip.get(Byte.valueOf((byte) -10)); mplew.writeInt(cWeapon != null ? cWeapon : 0); mplew.writeInt(Weapon != null ? Weapon : 0); mplew.writeInt(!zero && Shield != null ? Shield : 0); mplew.write(!MapleJob.is精靈遊俠(chr.getJob()) ? chr.getElf() : chr.getElf() == 0 ? 1 : 0);// 精靈耳朵 mplew.writeInt(0); // 寵物[1] mplew.writeInt(0); // 寵物[2] mplew.writeInt(0); // 寵物[3] if (MapleJob.is惡魔(chr.getJob())) { mplew.writeInt(chr.getFaceMarking()); } else if (MapleJob.is傑諾(chr.getJob())) { mplew.writeInt(chr.getFaceMarking()); } else if (MapleJob.is神之子(chr.getJob())) { mplew.write(1); } else if (MapleJob.is幻獸師(chr.getJob())) { mplew.writeInt(chr.getFaceMarking()); mplew.write(1); mplew.writeInt(chr.getEars()); mplew.write(1); mplew.writeInt(chr.getTail()); } mplew.write(0);//176+ mplew.write(0);//176+ } public static void addExpirationTime(MaplePacketLittleEndianWriter mplew, long time) { mplew.writeLong(getTime(time)); } public static void addItemPosition(MaplePacketLittleEndianWriter mplew, Item item, boolean trade, boolean bagSlot) { if (item == null) { mplew.write(0); return; } short pos = item.getPosition(); if (pos <= -1) { pos = (short) (pos * -1); if ((pos > 100) && (pos < 1000)) { pos = (short) (pos - 100); } } if (bagSlot) { mplew.writeInt(pos % 100 - 1); } else if ((!trade) && (item.getType() == 1)) { mplew.writeShort(pos); } else { mplew.write(pos); } } public static void addItemInfo(MaplePacketLittleEndianWriter mplew, Item item) { addItemInfo(mplew, item, null); } public static void addItemInfo(final MaplePacketLittleEndianWriter mplew, final Item item, final MapleCharacter chr) { mplew.write(item.getPet() != null ? 3 : item.getType()); mplew.writeInt(item.getItemId()); boolean hasUniqueId = item.getUniqueId() > 0 && !ItemConstants.類型.結婚戒指(item.getItemId()) && item.getItemId() / 10000 != 166; //marriage rings arent cash items so dont have uniqueids, but we assign them anyway for the sake of rings mplew.write(hasUniqueId ? 1 : 0); if (hasUniqueId) { mplew.writeLong(item.getUniqueId()); } if (item.getPet() != null) { // Pet addPetItemInfo(mplew, item, item.getPet(), true); } else { addExpirationTime(mplew, item.getExpiration()); mplew.writeInt(chr == null ? -1 : chr.getExtendedSlots().indexOf(item.getItemId())); if (item.getType() == 1) { final Equip equip = Equip.calculateEquipStats((Equip) item); addEquipStats(mplew, equip); addEquipBonusStats(mplew, equip, hasUniqueId); } else { mplew.writeShort(item.getQuantity()); mplew.writeMapleAsciiString(item.getOwner()); mplew.writeShort(item.getFlag()); //mplew.writeShort(0); if (ItemConstants.類型.可充值道具(item.getItemId()) || item.getItemId() / 10000 == 287) { mplew.writeLong(/*(int)*/(item.getInventoryId() <= 0 ? -1 : item.getInventoryId())); //mplew.writeShort(0); } } } } public static void addEquipStats(MaplePacketLittleEndianWriter mplew, Equip equip) { int head = 0; if (equip.getStats().size() > 0) { for (EquipStat stat : equip.getStats()) { head |= stat.getValue(); } } mplew.writeInt(head); if (head != 0) { if (equip.getStats().contains(EquipStat.SLOTS)) { mplew.write(equip.getUpgradeSlots()); } if (equip.getStats().contains(EquipStat.LEVEL)) { mplew.write(equip.getLevel()); } if (equip.getStats().contains(EquipStat.STR)) { mplew.writeShort(equip.getStr()); } if (equip.getStats().contains(EquipStat.DEX)) { mplew.writeShort(equip.getDex()); } if (equip.getStats().contains(EquipStat.INT)) { mplew.writeShort(equip.getInt()); } if (equip.getStats().contains(EquipStat.LUK)) { mplew.writeShort(equip.getLuk()); } if (equip.getStats().contains(EquipStat.MHP)) { mplew.writeShort(equip.getHp()); } if (equip.getStats().contains(EquipStat.MMP)) { mplew.writeShort(equip.getMp()); } if (equip.getStats().contains(EquipStat.WATK)) { mplew.writeShort(equip.getWatk()); } if (equip.getStats().contains(EquipStat.MATK)) { mplew.writeShort(equip.getMatk()); } if (equip.getStats().contains(EquipStat.WDEF)) { mplew.writeShort(equip.getWdef()); } if (equip.getStats().contains(EquipStat.MDEF)) { mplew.writeShort(equip.getMdef()); } if (equip.getStats().contains(EquipStat.ACC)) { mplew.writeShort(equip.getAcc()); } if (equip.getStats().contains(EquipStat.AVOID)) { mplew.writeShort(equip.getAvoid()); } if (equip.getStats().contains(EquipStat.HANDS)) { mplew.writeShort(equip.getHands()); } if (equip.getStats().contains(EquipStat.SPEED)) { mplew.writeShort(equip.getSpeed()); } if (equip.getStats().contains(EquipStat.JUMP)) { mplew.writeShort(equip.getJump()); } if (equip.getStats().contains(EquipStat.FLAG)) { mplew.writeInt(equip.getFlag()); } if (equip.getStats().contains(EquipStat.INC_SKILL)) { mplew.write(equip.getIncSkill() > 0 ? 1 : 0); } if (equip.getStats().contains(EquipStat.ITEM_LEVEL)) { mplew.write(Math.max(equip.getBaseLevel(), equip.getEquipLevel())); // Item level } if (equip.getStats().contains(EquipStat.ITEM_EXP)) { mplew.writeLong(equip.getExpPercentage() * 100000); // Item Exp... 10000000 = 100% } if (equip.getStats().contains(EquipStat.DURABILITY)) { mplew.writeInt(equip.getDurability()); } if (equip.getStats().contains(EquipStat.VICIOUS_HAMMER)) { mplew.writeInt(equip.getViciousHammer()); } if (equip.getStats().contains(EquipStat.PVP_DAMAGE)) { mplew.writeShort(equip.getPVPDamage()); } if (equip.getStats().contains(EquipStat.DOWNLEVEL)) { mplew.write(0); } if (equip.getStats().contains(EquipStat.ENHANCT_BUFF)) { mplew.writeShort(equip.getEnhanctBuff()); } if (equip.getStats().contains(EquipStat.DURABILITY_SPECIAL)) { mplew.writeInt(equip.getDurability()); } if (equip.getStats().contains(EquipStat.REQUIRED_LEVEL)) { mplew.write(equip.getReqLevel()); } if (equip.getStats().contains(EquipStat.YGGDRASIL_WISDOM)) { mplew.write(equip.getYggdrasilWisdom()); } if (equip.getStats().contains(EquipStat.FINAL_STRIKE)) { mplew.write(equip.getFinalStrike()); } if (equip.getStats().contains(EquipStat.BOSS_DAMAGE)) { mplew.write(equip.getBossDamage()); } if (equip.getStats().contains(EquipStat.IGNORE_PDR)) { mplew.write(equip.getIgnorePDR()); } } else { /* * if ( v3 >= 0 ) * v36 = 0; * else * v36 = (unsigned __int8)CInPacket::Decode1(a2); */ // mplew.write(0); //unknown } addEquipSpecialStats(mplew, equip); } public static void addEquipSpecialStats(MaplePacketLittleEndianWriter mplew, Equip equip) { //int head = equip.getEquipSpecialFlag(); int head = 0; if (equip.getSpecialStats().size() > 0) { for (EquipSpecialStat stat : equip.getSpecialStats()) { head |= stat.getValue(); } } mplew.writeInt(head); // System.out.println("mask " + head); if (head != 0) { if (equip.getSpecialStats().contains(EquipSpecialStat.TOTAL_DAMAGE)) { mplew.write(equip.getTotalDamage()); } if (equip.getSpecialStats().contains(EquipSpecialStat.ALL_STAT)) { mplew.write(equip.getAllStat()); } if (equip.getSpecialStats().contains(EquipSpecialStat.KARMA_COUNT)) { mplew.write(equip.getKarmaCount()); } if (equip.getSpecialStats().contains(EquipSpecialStat.FIRE)) { mplew.writeLong(System.currentTimeMillis()); } if (equip.getSpecialStats().contains(EquipSpecialStat.STAR_FORCE)) { mplew.write(0); mplew.write(equip.getStarForce()); mplew.write(0); mplew.write(0); } if (equip.isTrace()) { mplew.write(1); } } } public static void addEquipBonusStats(MaplePacketLittleEndianWriter mplew, Equip equip, boolean hasUniqueId) { mplew.writeMapleAsciiString(equip.getOwner());//擁有者名字 mplew.write(equip.getState(true) > 0 && equip.getState(true) < 17 ? equip.getState(false) | 0x20 : equip.getState(false)); //潛能等級 17 = 特殊rare, 18 = 稀有epic, 19 = 罕見unique, 20 = 傳說legendary, potential flags. special grade is 14 but it crashes mplew.write(equip.getEnhance());//裝備星級 for (int i = 1; i <= 3; i++) {//潛能 mplew.writeShort(equip.getState(false) > 0 && equip.getState(false) < 17 ? 0 : equip.getPotential(i, false)); } for (int i = 1; i <= 3; i++) {//附加潛能 mplew.writeShort(equip.getState(true) > 0 && equip.getState(true) < 17 ? i == 1 ? equip.getState(true) : 0 : equip.getPotential(i, true)); } mplew.writeShort(equip.getFusionAnvil() % 10000); mplew.writeShort(equip.getSocketState()); mplew.writeShort(equip.getSocket1() % 10000); // > 0 = mounted, 0 = empty, -1 = none. mplew.writeShort(equip.getSocket2() % 10000); mplew.writeShort(equip.getSocket3() % 10000); if (!hasUniqueId) { mplew.writeLong(equip.getInventoryId()); //some tracking ID } mplew.writeLong(getTime(-2)); mplew.writeInt(-1); mplew.writeLong(0); mplew.writeLong(getTime(-2)); mplew.writeLong(0); mplew.writeShort(0); mplew.writeShort(0);//魂武器 : 0 mplew.writeShort(0);//魂武器 / 100 : 0 mplew.writeShort(0);//魂武器 / 100 : 0 mplew.writeShort(equip.getSoulName());//魂武器類型 : 0 mplew.writeShort(equip.getSoulEnchanter());//魂武器 : 0 mplew.writeShort(equip.getSoulPotential());//item.getItemId()) ? equip.getPotential7() : equip.getPotential7() <= 0 ? 0 : 0 mplew.writeInt(0);//equip.getMaxDamage() : 0//突破傷害上限 mplew.writeLong(getTime(-2)); } public static void serializeMovementList(MaplePacketLittleEndianWriter lew, List<LifeMovementFragment> moves) { lew.write(moves.size()); for (LifeMovementFragment move : moves) { move.serialize(lew); } } public static void addAnnounceBox(MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { if ((chr.getPlayerShop() != null) && (chr.getPlayerShop().isOwner(chr)) && (chr.getPlayerShop().getShopType() != 1) && (chr.getPlayerShop().isAvailable())) { addInteraction(mplew, chr.getPlayerShop()); } else { mplew.write(0); } } public static void addInteraction(MaplePacketLittleEndianWriter mplew, IMaplePlayerShop shop) { mplew.write(shop.getGameType()); mplew.writeInt(((AbstractPlayerStore) shop).getObjectId()); mplew.writeMapleAsciiString(shop.getDescription()); // if (shop.getShopType() != 1) { mplew.write(shop.getPassword().length() > 0 ? 1 : 0); // } mplew.write(shop.getItemId() % 10); mplew.write(shop.getSize()); mplew.write(shop.getMaxSize()); // if (shop.getShopType() != 1) { mplew.write(shop.isOpen() ? 0 : 1); // } } public static void addCharacterInfo(MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { long mask = 0xFF_FF_FF_FF_FF_FF_FF_FFL; //FF FF FF FF FF FF DF FF v148+ mplew.writeLong(mask); mplew.write(0); for (int i = 0; i < 3; i++) { mplew.writeInt(-1); } int v7 = 0; mplew.write(v7); for (int i = 1; i < v7; i++) { mplew.writeInt(0); } int v10 = 0; mplew.writeInt(v10); for (int i = 0; i < v10; i++) { mplew.writeInt(0); mplew.writeLong(0); // Time } boolean v215 = false; mplew.writeBoolean(v215); if (v215) { mplew.write(0); int v11 = 0; mplew.writeInt(v11); for (int i = 0; i < v11; i++) { mplew.writeLong(0); } int v14 = 0; mplew.writeInt(v14); for (int i = 0; i < v14; i++) { mplew.writeLong(0); } } if ((mask & 1) != 0) { addCharStats(mplew, chr); // 角色狀態訊息 mplew.write(chr.getBuddylist().getCapacity()); // 好友上限 mplew.write(chr.getBlessOfFairyOrigin() != null); // 精靈的祝福 if (chr.getBlessOfFairyOrigin() != null) { mplew.writeMapleAsciiString(chr.getBlessOfFairyOrigin()); } mplew.write(chr.getBlessOfEmpressOrigin() != null); // 女皇的祝福 if (chr.getBlessOfEmpressOrigin() != null) { mplew.writeMapleAsciiString(chr.getBlessOfEmpressOrigin()); } // 終極冒險家訊息 MapleQuestStatus ultExplorer = chr.getQuestNoAdd(MapleQuest.getInstance(GameConstants.ULT_EXPLORER)); mplew.write((ultExplorer != null) && (ultExplorer.getCustomData() != null)); if ((ultExplorer != null) && (ultExplorer.getCustomData() != null)) { mplew.writeMapleAsciiString(ultExplorer.getCustomData()); } mplew.writeLong(getTime(System.currentTimeMillis())); mplew.writeLong(getTime(-2L)); PacketHelper.UnkFunctin6(mplew); } if ((mask & 2) != 0) { addMoneyInfo(mplew, chr);// 楓幣 mplew.writeInt(chr.getId()); mplew.writeInt(0); // 小鋼珠 mplew.writeInt(chr.getCSPoints(2)); // 楓葉點數 } if ((mask & 8 | mask & 0x2000000) != 0) { int v20 = 0; mplew.writeInt(v20); for (int i = 0; i > v20; i++) { mplew.writeInt(0); mplew.writeInt(0); mplew.writeInt(0); mplew.writeLong(0); } } if ((mask & 0x80) != 0) { int j = 0; mplew.writeInt(j); for (int i = 0; i < j; i++) { UnkFunction(mplew); } UnkFunction2(mplew, chr); int v22 = 0; mplew.writeInt(v22); for (int i = 1; i < v22; i++) { mplew.writeInt(0); } boolean v24 = false; mplew.writeBoolean(v24); if (v24) { UnkFunction3(mplew); } int v25 = 0; mplew.write(v25); if (v25 > 0) { for (int i = 0; i < v25; i++) { UnkFunction4(mplew); } } int v26 = 0; mplew.write(v26); if (v26 > 0) { for (int i = 0; i < v26; i++) { UnkFunction4(mplew); } } } if ((mask & 4) != 0) { addInventoryInfo(mplew, chr);//道具訊息 } if ((mask & 0x100) != 0) { addSkillInfo(mplew, chr);//技能訊息 } if ((mask & 0x8000) != 0) { addCoolDownInfo(mplew, chr);//冷卻技能訊息 } if ((mask & 0x200) != 0) { addStartedQuestInfo(mplew, chr);//已開始任務訊息 } if ((mask & 0x4000) != 0) { addCompletedQuestInfo(mplew, chr);//已完成任務訊息 } if ((mask & 0x400) != 0) { addMiniGameInfo(mplew, chr);//小遊戲訊息 } if ((mask & 0x800) != 0) { addRingInfo(mplew, chr);//戒指訊息 } if ((mask & 0x1000) != 0) { addRocksInfo(mplew, chr); } if ((mask & 0x40000) != 0) { chr.QuestInfoPacket(mplew);//任務數據 } if ((mask & 0x20) != 0) { int i1 = 0; mplew.writeShort(i1); for (int i = 0; i < i1; i++) { mplew.writeInt(0); addCharLook(mplew, chr, false, false); } } if ((mask & 0x1000) != 0) { int i2 = 0; mplew.writeInt(i2); for (int i = 0; i < i2; i++) { mplew.writeInt(0); mplew.writeInt(0); } } if ((mask & 0x200000) != 0) { if ((chr.getJob() >= 3300) && (chr.getJob() <= 3312)) { addJaguarInfo(mplew, chr);//狂豹訊息 } } if ((mask & 0x800) != 0) { if (MapleJob.is神之子(chr.getJob())) { addZeroInfo(mplew, chr);//神之子訊息 } } if ((mask & 0x400000) != 0) { int v142 = 0; mplew.writeShort(v142);//未知 for (int i = 0; i < v142; i++) { mplew.writeShort(0); mplew.writeLong(0); } } if ((mask & 0x4000000) != 0) { int v143 = 0; mplew.writeShort(v143);//未知 for (int i = 0; i < v143; i++) { mplew.writeShort(0); mplew.writeInt(0); } } if ((mask & 0x10000000) != 0 || (mask & 0x20000000) != 0) { addStealSkills(mplew, chr);//幻影複製技能訊息 } if ((mask & 0x80000000) != 0) { addAbilityInfo(mplew, chr);//角色內在能力訊息 } if ((mask & 0x400000) != 0) { int v183 = 0; mplew.writeShort(v183); for (int i = 0; i < v183; i++) { mplew.writeInt(0); mplew.writeInt(0); } } if ((mask & 1) != 0) { addHonorInfo(mplew, chr);//內在能力聲望訊息 } if ((mask & 0x2000) != 0) { addCoreAura(mplew, chr); mplew.write(1); } if ((mask & 0x4000) != 0) { int OX_System = 0; mplew.writeShort(OX_System); //for <short> length write 2 shorts for (int i = 0; i < OX_System; i++) { mplew.writeInt(0); mplew.writeInt(0); mplew.writeMapleAsciiString(""); mplew.write(0); mplew.writeLong(0); mplew.writeInt(0); mplew.writeMapleAsciiString(""); mplew.write(0); mplew.write(0); mplew.writeLong(0); mplew.writeMapleAsciiString(""); } } if ((mask & 0x8000) != 0) { int i8 = 0; mplew.writeShort(i8); for (int i = 0; i < i8; i++) { mplew.writeZeroBytes(20); } } if ((mask & 0x10000) != 0) { addRedLeafInfo(mplew, chr); } if ((mask & 0x20000) != 0) { int i4 = 0; mplew.writeShort(i4); for (int i = 0; i < i4; i++) { mplew.writeInt(0); mplew.writeInt(0); mplew.writeInt(0); mplew.writeLong(0); mplew.writeLong(0); mplew.writeInt(0); int result = 0; mplew.writeInt(result); for (int j = 0; j < result; j++) { mplew.writeInt(0); } } } if ((mask & 2) != 0) {//3 boolean b5 = true; mplew.writeBoolean(b5);//1 if (b5) { int v1 = 0; mplew.writeShort(v1);//2 for (int i = 0; i < v1; i++) { mplew.writeShort(0); int i5 = 0; mplew.writeShort(0); for (int j = 0; j < i5; j++) { mplew.writeInt(0); mplew.writeInt(0); } } } else { int i6 = 0; mplew.writeShort(i6); for (int i = 0; i < i6; i++) { mplew.writeShort(0); mplew.writeInt(0); mplew.writeInt(0); } } } if ((mask & 4) != 0) {//1 int v3 = 0; mplew.write(v3); if (v3 > 0) { mplew.write(0); mplew.writeInt(0); } } if ((mask & 8) != 0) { mplew.writeInt(MapleJob.is天使破壞者(chr.getJob()) ? 21173 : 0); mplew.writeInt(MapleJob.is天使破壞者(chr.getJob()) ? 37141 : 0); mplew.writeInt(MapleJob.is天使破壞者(chr.getJob()) ? 1051291 : 0); mplew.write(0); mplew.writeInt(-1); mplew.writeInt(0); mplew.writeInt(0); } if ((mask & 0x200000) != 0) { mplew.writeInt(0); mplew.writeInt(0); mplew.writeLong(getTime(-2)); } if ((mask & 0x10) != 0) { int v181 = 0; mplew.writeShort(v181); for (int i = 0; i < v181; i++) { mplew.writeShort(0); mplew.writeInt(0); mplew.writeInt(0); } int v186 = 0; mplew.writeShort(v186); for (int i = 0; i < v186; i++) { mplew.writeShort(0); mplew.writeInt(0); mplew.writeInt(0); } } if ((mask & 0x200) != 0) { boolean v4 = false; mplew.write(v4); if (v4) { mplew.write(0); mplew.writeInt(0); mplew.writeInt(0); } } if ((mask & 0x400) != 0) { mplew.writeInt(0); mplew.writeLong(getTime(-2)); mplew.writeInt(0); } UnkFunction5(mplew); if ((mask & 0x40000) != 0) { boolean v190 = true; mplew.writeBoolean(v190); if (v190) { mplew.write(0); mplew.writeInt(1); mplew.writeInt(0); mplew.writeInt(0);//100 mplew.writeLong(getTime(-2)); } int v192 = 0; mplew.writeShort(v192); for (int i = 0; i < v192; i++) { mplew.write(0); mplew.writeInt(0); mplew.writeInt(0); } int v194 = 0; mplew.writeShort(v194); for (int i = 0; i < v194; i++) { mplew.writeInt(0); mplew.writeInt(0); mplew.writeLong(0); } } if ((mask & 0x80000) != 0) { mplew.write(0); } if ((mask & 0x100000) != 0) { int v5 = 0; mplew.writeInt(v5); for (int i = 0; i < v5; i++) { mplew.writeShort(0); mplew.writeShort(0); } int v8 = 0; mplew.writeInt(v8); for (int i = 0; i < v8; i++) { mplew.writeShort(0); mplew.writeInt(0); } } if ((1 & mask) != 0) { mplew.writeInt(chr.getId()); mplew.writeInt(0); mplew.writeInt(0); mplew.writeLong(getTime(-2)); mplew.writeInt(30); } } public static void UnkFunction(final MaplePacketLittleEndianWriter mplew) { mplew.writeInt(0); mplew.writeInt(0); mplew.writeInt(0); mplew.writeInt(0); mplew.writeInt(0); mplew.writeInt(0); mplew.write(0); mplew.writeInt(0); mplew.writeInt(0); } public static void UnkFunction2(final MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { mplew.writeInt(chr.getId()); for (int i = 0; i < 3; i++) { mplew.writeInt(0); mplew.writeInt(0); } } public static void UnkFunction3(final MaplePacketLittleEndianWriter mplew) { mplew.writeInt(0); mplew.writeInt(0); mplew.writeInt(0); mplew.writeInt(0); mplew.writeInt(0); mplew.writeInt(0); mplew.writeInt(0); mplew.writeInt(0); mplew.writeInt(0); mplew.writeLong(0); mplew.writeLong(0); mplew.writeLong(0); } public static void UnkFunction4(final MaplePacketLittleEndianWriter mplew) { mplew.write(0); mplew.writeInt(0); mplew.write(0); mplew.writeInt(0); mplew.writeInt(0); mplew.writeInt(0); mplew.writeInt(0); mplew.writeInt(0); mplew.writeInt(0); mplew.writeMapleAsciiString(""); // char name?? } public static void UnkFunction5(final MaplePacketLittleEndianWriter mplew) { int result = 0; mplew.writeInt(result); for (int i = 0; i < result; i++) { mplew.writeInt(0); mplew.writeMapleAsciiString(""); } } public static void UnkFunctin6(final MaplePacketLittleEndianWriter mplew) { int v7 = 2; do { mplew.writeInt(0); while (true) { int res = 255; mplew.write(res); if (res == 255) break; mplew.writeInt(0); } v7 += 36; } while (v7 < 74); } public static int getSkillBook(final int i) { switch (i) { case 1: case 2: return 4; case 3: return 3; case 4: return 2; } return 0; } public static void addAbilityInfo(final MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { final List<InnerSkillValueHolder> skills = chr.getInnerSkills(); mplew.writeShort(skills.size()); for (int i = 0; i < skills.size(); ++i) { mplew.write(i + 1); // key mplew.writeInt(skills.get(i).getSkillId()); //d 7000000 id ++, 71 = char cards mplew.write(skills.get(i).getSkillLevel()); // level mplew.write(skills.get(i).getRank()); //rank, C, B, A, and S } } public static void addHonorInfo(final MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { mplew.writeInt(chr.getHonorLevel()); //之前是聲望等級honor lvl mplew.writeInt(chr.getHonourExp()); //之前是聲望經驗值,現在是聲望honor exp } public static void addEvolutionInfo(final MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { mplew.writeShort(0); mplew.writeShort(0); } public static void addCoreAura(MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { MapleCoreAura aura = chr.getCoreAura(); // mplew.writeInt(aura.getId()); //nvr change//176- //mplew.writeInt(chr.getId()); mplew.writeInt(0); int level = chr.getSkillLevel(80001151) > 0 ? chr.getSkillLevel(80001151) : chr.getSkillLevel(1214); mplew.writeInt(level); mplew.writeInt(aura.getExpire());//timer mplew.writeInt(0); mplew.writeInt(0); mplew.writeInt(aura.getAtt());//wep att mplew.writeInt(aura.getDex());//dex mplew.writeInt(aura.getLuk());//luk mplew.writeInt(aura.getMagic());//magic att mplew.writeInt(aura.getInt());//int mplew.writeInt(aura.getStr());//str mplew.writeInt(0); mplew.writeInt(aura.getTotal());//max mplew.writeInt(0); mplew.writeInt(0); mplew.writeLong(getTime(System.currentTimeMillis() + 86400000L)); mplew.write(MapleJob.is蒼龍俠客(chr.getJob()) && MapleJob.is幻獸師(chr.getJob()) ? 1 : 0); } public static void addStolenSkills(MaplePacketLittleEndianWriter mplew, MapleCharacter chr, int jobNum, boolean writeJob) { if (writeJob) { mplew.writeInt(jobNum); } int count = 0; if (chr.getStolenSkills() != null) { for (Pair<Integer, Boolean> sk : chr.getStolenSkills()) { if (MapleJob.getNumber(sk.left / 10000) == jobNum) { mplew.writeInt(sk.left); count++; if (count >= GameConstants.getNumSteal(jobNum)) { break; } } } } while (count < GameConstants.getNumSteal(jobNum)) { //for now? mplew.writeInt(0); count++; } } public static void addChosenSkills(MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { for (int i = 1; i <= 4; i++) { boolean found = false; if (chr.getStolenSkills() != null) { for (Pair<Integer, Boolean> sk : chr.getStolenSkills()) { if (MapleJob.getNumber(sk.left / 10000) == i && sk.right) { mplew.writeInt(sk.left); found = true; break; } } } if (!found) { mplew.writeInt(0); } } } public static void addStealSkills(final MaplePacketLittleEndianWriter mplew, final MapleCharacter chr) { for (int i = 1; i <= 4; i++) { addStolenSkills(mplew, chr, i, false); // 52 } addChosenSkills(mplew, chr); // 16 } public static void addMonsterBookInfo(MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { if (chr.getMonsterBook().getSetScore() > 0) { chr.getMonsterBook().writeFinished(mplew); } else { chr.getMonsterBook().writeUnfinished(mplew); } mplew.writeInt(chr.getMonsterBook().getSet()); } public static void addPetItemInfo(MaplePacketLittleEndianWriter mplew, Item item, MaplePet pet, boolean active) { if (item == null) { mplew.writeLong(PacketHelper.getKoreanTimestamp((long) (System.currentTimeMillis() * 1.5))); } else { addExpirationTime(mplew, item.getExpiration() <= System.currentTimeMillis() ? -1L : item.getExpiration()); } mplew.writeInt(-1); mplew.writeAsciiString(pet.getName(), 13); mplew.write(pet.getLevel()); mplew.writeShort(pet.getCloseness()); mplew.write(pet.getFullness()); if (item == null) { mplew.writeLong(PacketHelper.getKoreanTimestamp((long) (System.currentTimeMillis() * 1.5))); } else { addExpirationTime(mplew, item.getExpiration() <= System.currentTimeMillis() ? -1L : item.getExpiration()); } mplew.writeShort(0); mplew.writeShort(pet.getFlags()); mplew.writeInt((pet.getPetItemId() == 5000054) && (pet.getSecondsLeft() > 0) ? pet.getSecondsLeft() : 0); mplew.writeShort(pet.isCanPickup() ? 0 : 2); mplew.write(active ? 0 : pet.getSummoned() ? pet.getSummonedValue() : 0); mplew.writeInt(0); mplew.writeInt(0); mplew.writeInt(0); mplew.writeInt(0); mplew.writeInt(-1); mplew.writeShort(100); } public static void addShopInfo(MaplePacketLittleEndianWriter mplew, MapleShop shop, MapleClient c) { MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance(); mplew.write(0); mplew.writeInt(GameConstants.getCurrentDate()); mplew.write(shop.getRanks().size() > 0 ? 1 : 0); if (shop.getRanks().size() > 0) { mplew.write(shop.getRanks().size()); for (Pair s : shop.getRanks()) { mplew.writeInt(((Integer) s.left)); mplew.writeMapleAsciiString((String) s.right); } } mplew.writeShort(shop.getItems().size() + c.getPlayer().getRebuy().size()); for (MapleShopItem item : shop.getItems()) { addShopItemInfo(mplew, item, shop, ii, null, c.getPlayer()); } for (Item i : c.getPlayer().getRebuy()) { addShopItemInfo(mplew, new MapleShopItem(i.getItemId(), (int) ii.getPrice(i.getItemId()), i.getQuantity(), i.getPosition()), shop, ii, i, c.getPlayer()); } } /* * Categories: * 0 - 標題 * 1 - 裝備 * 2 - 消耗 * 3 - 裝飾 * 4 - 其他 * 5 - 配方 * 6 - 卷軸 * 7 - 特殊 * 8 - 七週年 * 9 - 紐扣 * 10 - 入場券 * 11 - 材料 * 12 - 新楓之谷 * 13 - 運動會 * 14 - 楓核心 * 80 - 喬 * 81 - 海麗蜜 * 82 - 小龍 * 83 - 李卡司 */ public static void addShopItemInfo(MaplePacketLittleEndianWriter mplew, MapleShopItem item, MapleShop shop, MapleItemInformationProvider ii, Item i, MapleCharacter chr) { mplew.writeInt(item.getItemId()); mplew.writeInt(item.getPrice()); mplew.write(ServerConstants.SHOP_DISCOUNT);//打折 mplew.writeInt(item.getReqItem());//貨幣道具 mplew.writeInt(item.getReqItemQ());//消耗貨幣數量 mplew.writeInt(0);//點數道具 mplew.writeInt(0);//消耗點數數量 mplew.writeInt(0); mplew.writeMapleAsciiString(""); mplew.writeInt(0); mplew.writeInt(0); mplew.writeInt(0); mplew.writeInt(item.getExpiration());//使用時限(單位分鐘) mplew.writeInt(item.getMinLevel());//購買等級限制 mplew.writeShort(0); mplew.writeShort(0); mplew.writeInt(0);//未知 mplew.writeLong(getTime(-2L)); mplew.writeLong(getTime(-1L)); mplew.writeInt(item.getCategory()); mplew.writeMapleAsciiString("1900010100"); mplew.writeMapleAsciiString("2079010100"); if (ItemConstants.類型.裝備(item.getItemId())) { mplew.writeInt(item.hasPotential() ? 1 : 0); } else { mplew.writeInt(0); } mplew.writeInt(0);//允許購買次數 mplew.write(0); if (!ItemConstants.類型.可充值道具(item.getItemId())) { int slotMax = MapleItemInformationProvider.getInstance().getSlotMax(item.getItemId()); int quantity = item.getQuantity() == 0 ? slotMax : item.getQuantity(); mplew.writeShort(quantity); //購買數量 mplew.writeShort(quantity > 1 ? 1 : item.getBuyable() == 0 ? slotMax : item.getBuyable()); //可購買數量 } else { mplew.writeAsciiString("333333"); mplew.writeShort(BitTools.doubleToShortBits(ii.getPrice(item.getItemId()))); mplew.writeShort(ii.getSlotMax(item.getItemId())); } mplew.write(i == null ? 0 : 1); if (i != null) { addItemInfo(mplew, i); } if (shop.getRanks().size() > 0) { mplew.write(item.getRank() >= 0 ? 1 : 0); if (item.getRank() >= 0) { mplew.write(item.getRank()); } } for (int j = 0; j < 4; j++) { mplew.writeInt(0); //red leaf high price probably } int idarr[] = new int[]{9410165, 9410166, 9410167, 9410168, 9410198}; for (int k = 0; k < 5; k++) { mplew.writeInt(idarr[k]); mplew.writeInt(chr.getFriendShipPoints()[k]); } } public static void addJaguarInfo(MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { mplew.write(chr.getIntNoRecord(GameConstants.JAGUAR)); for (int i = 0; i < 5; i++) { mplew.writeInt(0); } } public static void addAdventurerInfo(MaplePacketLittleEndianWriter mplew) { mplew.write(HexTool.getByteArrayFromHexString("2A 00 98 46 07 00 63 6F 75 6E 74 3D 30 10 47 06 00 76 61 6C 32 3D 30 16 69 00 00 99 46 07 00 63 6F 75 6E 74 3D 30 09 47 03 00 44 3D 32 6A 36 1D 00 6C 61 73 74 47 61 6D 65 3D 31 34 2F 30 32 2F 31 39 3B 53 6E 57 41 74 74 65 6E 64 3D 30 CD 33 0B 00 62 6F 72 6E 3D 31 34 30 32 30 34 8B 45 00 00 17 69 00 00 9A 46 1A 00 63 6F 75 6E 74 30 3D 31 3B 63 6F 75 6E 74 31 3D 31 3B 63 6F 75 6E 74 32 3D 31 0A 47 03 00 45 3D 31 22 47 17 00 63 6F 6D 70 3D 31 3B 69 3D 32 33 30 30 30 30 30 30 30 30 30 30 30 30 FA 46 20 00 63 6F 75 6E 74 3D 35 3B 74 69 6D 65 3D 32 30 31 33 2F 31 32 2F 31 34 20 30 38 3A 33 32 3A 31 32 12 47 40 00 4D 4C 3D 30 3B 4D 4D 3D 30 3B 4D 41 3D 30 3B 4D 42 3D 30 3B 4D 43 3D 30 3B 4D 44 3D 30 3B 4D 45 3D 30 3B 4D 46 3D 30 3B 4D 47 3D 30 3B 4D 48 3D 30 3B 4D 49 3D 30 3B 4D 4A 3D 30 3B 4D 4B 3D 30 CB 36 1B 00 6D 41 74 74 65 6E 64 3D 30 3B 6C 61 73 74 47 61 6D 65 3D 31 34 2F 30 32 2F 31 39 1C 1E 13 00 64 72 61 77 3D 30 3B 6C 6F 73 65 3D 30 3B 77 69 6E 3D 30 18 69 00 00 23 47 09 00 62 41 74 74 65 6E 64 3D 30 63 47 20 00 64 74 3D 31 33 2F 31 32 2F 32 34 3B 64 3D 32 30 31 33 31 32 32 34 3B 69 3D 33 30 30 30 30 30 30 D7 33 05 00 73 6E 32 3D 30 F7 33 04 00 30 33 3D 31 19 69 00 00 B4 46 07 00 63 6F 75 6E 74 3D 30 23 7F 1F 00 6C 61 73 74 44 65 63 54 69 6D 65 3D 32 30 31 34 2F 30 32 2F 31 39 20 30 35 3A 34 31 3A 31 32 2C 47 07 00 4C 6F 67 69 6E 3D 31 64 47 04 00 41 51 3D 31 85 46 17 00 31 3D 30 3B 32 3D 30 3B 33 3D 30 3B 34 3D 30 3B 35 3D 30 3B 36 3D 30 B5 46 07 00 63 6F 75 6E 74 3D 30 0D 47 14 00 65 54 69 6D 65 3D 31 32 2F 31 32 2F 33 31 2F 30 30 2F 30 30 1D 47 06 00 73 74 65 70 3D 30 B6 46 07 00 63 6F 75 6E 74 3D 30 55 67 05 00 76 61 6C 3D 30 16 47 31 00 52 48 3D 30 3B 47 54 3D 30 3B 57 4D 3D 30 3B 46 41 3D 30 3B 45 43 3D 30 3B 43 48 3D 30 3B 4B 44 3D 30 3B 49 4B 3D 30 3B 50 44 3D 30 3B 50 46 3D 30 31 15 04 00 64 63 3D 30 87 46 1E 00 52 47 3D 30 3B 53 4D 3D 30 3B 41 4C 50 3D 30 3B 44 42 3D 30 3B 43 44 3D 30 3B 4D 48 3D 30 14 69 13 00 73 66 3D 30 3B 6D 74 3D 30 3B 61 6C 3D 31 3B 69 64 3D 30 42 34 0C 00 52 6F 6C 6C 50 65 72 44 61 79 3D 30 9F 46 1C 00 69 6E 64 65 78 3D 31 3B 6C 61 73 74 52 3D 31 33 2F 30 39 2F 32 35 3B 73 6E 31 3D 30 24 C8 0A 00 53 74 61 67 65 4B 65 79 3D 30 C3 33 07 00 63 6F 75 6E 74 3D 30 53 0C 07 00 72 65 73 65 74 3D 31 A0 46 05 00 6E 75 6D 3D 30 00 00")); } public static void addZeroInfo(MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { short mask = 0; mplew.writeShort(mask); if ((mask & 1) != 0) { mplew.write(0); //bool } if ((mask & 2) != 0) { mplew.writeInt(0); } if ((mask & 4) != 0) { mplew.writeInt(0); } if ((mask & 8) != 0) { mplew.write(0); } if ((mask & 10) != 0) { mplew.writeInt(0); } if ((mask & 20) != 0) { mplew.writeInt(0); } if ((mask & 40) != 0) { mplew.writeInt(0); } if (mask < 0) { mplew.writeInt(0); } if ((mask & 100) != 0) { mplew.writeInt(0); } } public static void addAdventurerInfo(MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { mplew.write(HexTool.getByteArrayFromHexString("14 00 0D 47 14 00 65 54 69 6D 65 3D 31 32 2F 31 32 2F 33 31 2F 30 30 2F 30 30 B6 46 07 00 63 6F 75 6E 74 3D 30 87 46 1E 00 52 47 3D 30 3B 53 4D 3D 30 3B 41 4C 50 3D 30 3B 44 42 3D 30 3B 43 44 3D 30 3B 4D 48 3D 30 16 47 31 00 52 48 3D 30 3B 47 54 3D 30 3B 57 4D 3D 30 3B 46 41 3D 30 3B 45 43 3D 30 3B 43 48 3D 30 3B 4B 44 3D 30 3B 49 4B 3D 30 3B 50 44 3D 30 3B 50 46 3D 30 9F 46 1C 00 69 6E 64 65 78 3D 31 3B 6C 61 73 74 52 3D 31 34 2F 30 33 2F 32 36 3B 73 6E 31 3D 30 A0 46 05 00 6E 75 6D 3D 30 40 47 3A 00 63 6F 75 6E 74 3D 30 3B 61 67 6F 3D 35 3B 64 6F 31 3D 30 3B 64 6F 32 3D 30 3B 64 61 69 6C 79 46 50 3D 30 3B 6C 61 73 74 44 61 74 65 3D 32 30 31 34 30 33 32 38 3B 46 50 3D 30 10 47 06 00 76 61 6C 32 3D 30 9A 46 1A 00 63 6F 75 6E 74 30 3D 31 3B 63 6F 75 6E 74 31 3D 31 3B 63 6F 75 6E 74 32 3D 31 22 47 17 00 63 6F 6D 70 3D 31 3B 69 3D 32 33 30 30 30 30 30 30 30 30 30 30 30 30 0A 47 03 00 45 3D 31 5B 46 0C 00 52 65 74 75 72 6E 55 73 65 72 3D 31 12 47 40 00 4D 4C 3D 30 3B 4D 4D 3D 30 3B 4D 41 3D 30 3B 4D 42 3D 30 3B 4D 43 3D 30 3B 4D 44 3D 30 3B 4D 45 3D 30 3B 4D 46 3D 30 3B 4D 47 3D 30 3B 4D 48 3D 30 3B 4D 49 3D 30 3B 4D 4A 3D 30 3B 4D 4B 3D 30 FA 46 20 00 63 6F 75 6E 74 3D 35 3B 74 69 6D 65 3D 32 30 31 34 2F 30 33 2F 32 36 20 30 37 3A 30 38 3A 33 37 23 47 09 00 62 41 74 74 65 6E 64 3D 30 B4 46 07 00 63 6F 75 6E 74 3D 30 85 46 17 00 31 3D 30 3B 32 3D 30 3B 33 3D 30 3B 34 3D 30 3B 35 3D 30 3B 36 3D 30 2C 47 07 00 4C 6F 67 69 6E 3D 31 64 47 04 00 41 51 3D 30 B5 46 07 00 63 6F 75 6E 74 3D 30")); } public static void addBeastTamerInfo(MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { int beast = MapleJob.is幻獸師(chr.getJob()) ? 1 : 0; String ears = Integer.toString(chr.getEars()); String tail = Integer.toString(chr.getTail()); mplew.write(HexTool.getByteArrayFromHexString("28 00 10 47 06 00 76 61 6C 32 3D 30 16 69 00 00 6A 36 1D 00 6C 61 73 74 47 61 6D 65 3D 31 34 2F 30 33 2F 30 36 3B 53 6E 57 41 74 74 65 6E 64 3D 30 8B 45 00 00 CD 33 0B 00 62 6F 72 6E 3D 31 34 30 33 30 36 9A 46 1A 00 63 6F 75 6E 74 30 3D 31 3B 63 6F 75 6E 74 31 3D 31 3B 63 6F 75 6E 74 32 3D 31 17 69 00 00 0A 47 03 00 45 3D 31 22 47 17 00 63 6F 6D 70 3D 31 3B 69 3D 32 33 30 30 30 30 30 30 30 30 30 30 30 30 FA 46 20 00 63 6F 75 6E 74 3D 35 3B 74 69 6D 65 3D 32 30 31 34 2F 30 33 2F 30 36 20 30 31 3A 30 39 3A 32 35 12 47 40 00 4D 4C 3D 30 3B 4D 4D 3D 30 3B 4D 41 3D 30 3B 4D 42 3D 30 3B 4D 43 3D 30 3B 4D 44 3D 30 3B 4D 45 3D 30 3B 4D 46 3D 30 3B 4D 47 3D 30 3B 4D 48 3D 30 3B 4D 49 3D 30 3B 4D 4A 3D 30 3B 4D 4B 3D 30 CB 36 1B 00 6D 41 74 74 65 6E 64 3D 30 3B 6C 61 73 74 47 61 6D 65 3D 31 34 2F 30 33 2F 30 36 1C 1E 13 00 64 72 61 77 3D 30 3B 6C 6F 73 65 3D 30 3B 77 69 6E 3D 30 18 69 00 00 23 47 09 00 62 41 74 74 65 6E 64 3D 30 D7 33 05 00 73 6E 32 3D 30 F7 33 04 00 30 33 3D 31 19 69 00 00 B4 46 07 00 63 6F 75 6E 74 3D 30 23 7F 1F 00 6C 61 73 74 44 65 63 54 69 6D 65 3D 32 30 31 34 2F 30 33 2F 30 36 20 30 36 3A 35 39 3A 32 32 2C 47 07 00 4C 6F 67 69 6E 3D 31 64 47 04 00 41 51 3D 30 85 46 17 00 31 3D 30 3B 32 3D 30 3B 33 3D 30 3B 34 3D 30 3B 35 3D 30 3B 36 3D 30 B5 46 07 00 63 6F 75 6E 74 3D 30 0D 47 14 00 65 54 69 6D 65 3D 31 32 2F 31 32 2F 33 31 2F 30 30 2F 30 30 1D 47 06 00 73 74 65 70 3D 30 B6 46 07 00 63 6F 75 6E 74 3D 30 55 67 05 00 76 61 6C 3D 30 16 47 31 00 52 48 3D 30 3B 47 54 3D 30 3B 57 4D 3D 30 3B 46 41 3D 30 3B 45 43 3D 30 3B 43 48 3D 30 3B 4B 44 3D 30 3B 49 4B 3D 30 3B 50 44 3D 30 3B 50 46 3D 30 31 15 04 00 64 63 3D 30 87 46 1E 00 52 47 3D 30 3B 53 4D 3D 30 3B 41 4C 50 3D 30 3B 44 42 3D 30 3B 43 44 3D 30 3B 4D 48 3D 30 14 69 13 00 73 66 3D 30 3B 6D 74 3D 30 3B 61 6C 3D 31 3B 69 64 3D 30 42 34 0C 00 52 6F 6C 6C 50 65 72 44 61 79 3D 30 9F 46 1C 00 69 6E 64 65 78 3D 31 3B 6C 61 73 74 52 3D 31 34 2F 30 33 2F 30 36 3B 73 6E 31 3D 30 8D E6 0E 00 6D 6F 76 69 65 3D 31 3B 74 75 74 6F 3D 31 A4 E7 2B 00")); mplew.writeAsciiString("bTail=" + beast + ";"); mplew.writeAsciiString("bEar=" + beast + ";"); mplew.writeAsciiString("TailID=" + tail + ";"); mplew.writeAsciiString("EarID=" + ears); mplew.write(HexTool.getByteArrayFromHexString("24 C8 0A 00 53 74 61 67 65 4B 65 79 3D 30 C3 33 07 00 63 6F 75 6E 74 3D 30 53 0C 07 00 72 65 73 65 74 3D 31 A0 46 05 00 6E 75 6D 3D 30 00 00")); } public static void addFarmInfo(MaplePacketLittleEndianWriter mplew, MapleClient c, int idk) { mplew.writeMapleAsciiString(c.getFarm().getName()); mplew.writeInt(c.getFarm().getWaru()); mplew.writeInt(c.getFarm().getLevel()); mplew.writeInt(c.getFarm().getExp()); mplew.writeInt(c.getFarm().getAestheticPoints()); mplew.writeInt(0); //gems mplew.write((byte) idk); mplew.writeInt(0); mplew.writeInt(0); mplew.writeInt(1); } public static void addRedLeafInfo(MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { int idarr[] = new int[]{9410165, 9410166, 9410167, 9410168, 9410198}; mplew.writeInt(chr.getClient().getAccID()); mplew.writeInt(chr.getId()); int size = 5; mplew.writeInt(size); mplew.writeInt(0); for (int i = 0; i < 5; i++) { mplew.writeInt(idarr[i]); mplew.writeInt(chr.getFriendShipPoints()[i]); } } public static void addLuckyLogoutInfo(MaplePacketLittleEndianWriter mplew, boolean enable, CashItem item0, CashItem item1, CashItem item2) { mplew.writeInt(enable ? 1 : 0); if (enable) { CSPacket.addCSItemInfo(mplew, item0); CSPacket.addCSItemInfo(mplew, item1); CSPacket.addCSItemInfo(mplew, item2); } } public static void addPartTimeJob(MaplePacketLittleEndianWriter mplew, PartTimeJob parttime) { mplew.write(parttime.getJob()); if (parttime.getJob() > 0 && parttime.getJob() <= 5) { mplew.writeReversedLong(parttime.getTime()); } else { mplew.writeReversedLong(getTime(-2)); } mplew.writeInt(parttime.getReward()); mplew.write(parttime.getReward() > 0); } public static <E extends Buffstat> void writeSingleMask(MaplePacketLittleEndianWriter mplew, E statup) { writeSingleMask(mplew, statup, GameConstants.MAX_BUFFSTAT); } public static <E extends Buffstat> void writeSingleMobMask(MaplePacketLittleEndianWriter mplew, E statup) { writeSingleMask(mplew, statup, GameConstants.MAX_MOBSTAT); } public static <E extends Buffstat> void writeSingleMask(MaplePacketLittleEndianWriter mplew, E statup, int maxMask) { for (int i = 0; i < maxMask; i++) { mplew.writeInt(i == statup.getPosition() ? statup.getValue() : 0); } } public static <E extends Buffstat> void writeMask(MaplePacketLittleEndianWriter mplew, Collection<E> statups) { writeMask(mplew, statups, GameConstants.MAX_BUFFSTAT); } public static <E extends Buffstat> void writeMobMask(MaplePacketLittleEndianWriter mplew, Collection<E> statups) { writeMask(mplew, statups, GameConstants.MAX_MOBSTAT); } public static <E extends Buffstat> void writeMask(MaplePacketLittleEndianWriter mplew, Collection<E> statups, int maxMask) { int[] mask = new int[maxMask]; for (Buffstat statup : statups) { mask[(statup.getPosition())] |= statup.getValue(); } for (int i = 0; i < mask.length; i++) { mplew.writeInt(mask[i]); } } public static <E extends Buffstat> void writeBuffMask(MaplePacketLittleEndianWriter mplew, Collection<Pair<E, Integer>> statups) { int[] mask = new int[GameConstants.MAX_BUFFSTAT]; for (Pair statup : statups) { mask[(((Buffstat) statup.left).getPosition())] |= ((Buffstat) statup.left).getValue(); } for (int i = 0; i < mask.length; i++) { mplew.writeInt(mask[i]); } } public static <E extends Buffstat> void writeBuffMask(MaplePacketLittleEndianWriter mplew, Map<E, Integer> statups) { int[] mask = new int[GameConstants.MAX_BUFFSTAT]; for (Buffstat statup : statups.keySet()) { mask[(statup.getPosition())] |= statup.getValue(); } for (int i = 0; i < mask.length; i++) { mplew.writeInt(mask[i]); } } }