From c8f905e1a58f1da5a81f634ed5aa7f587a26adde Mon Sep 17 00:00:00 2001 From: ronancpl Date: Fri, 7 Apr 2017 21:42:42 -0300 Subject: [PATCH] Fixed quest rewarding + Lethal attacks in Dojo Fixed quests not giving items in some cases, lethal damages rendering dojo uncompletable and added new scripts. --- mychanges_ptbr.txt | 8 +- nbproject/private/private.xml | 12 +- scripts/event/0_EXAMPLE.js | 76 + scripts/event/s4aWorld.js | 84 + scripts/npc/world0/1061012.js | 62 + sql/db_database.sql | 4 +- sql/db_drops.sql | 6 +- src/client/MapleJob.java | 13 + src/constants/GameConstants.java | 18 + src/constants/ServerConstants.java | 3 + .../handlers/AbstractDealDamageHandler.java | 15 +- .../channel/handlers/TakeDamageHandler.java | 11 +- src/scripting/event/EventInstanceManager.java | 57 +- src/server/life/ChangeableStats.java | 50 + src/server/life/MapleMonster.java | 34 +- src/server/life/MapleMonsterStats.java | 9 + src/server/life/OverrideMonsterStats.java | 64 + src/server/maps/MapleMap.java | 23 +- src/server/quest/MapleQuest.java | 6 +- .../quest/MapleQuestRequirementType.java | 12 +- src/server/quest/actions/ItemAction.java | 31 +- .../quest/actions/MapleQuestAction.java | 87 +- src/tools/MaplePacketCreator.java | 13740 ++++++++-------- 23 files changed, 7503 insertions(+), 6922 deletions(-) create mode 100644 scripts/event/0_EXAMPLE.js create mode 100644 scripts/event/s4aWorld.js create mode 100644 scripts/npc/world0/1061012.js create mode 100644 src/server/life/ChangeableStats.java create mode 100644 src/server/life/OverrideMonsterStats.java diff --git a/mychanges_ptbr.txt b/mychanges_ptbr.txt index 950824373a..d96f2ca174 100644 --- a/mychanges_ptbr.txt +++ b/mychanges_ptbr.txt @@ -131,4 +131,10 @@ Corre 06 Abril 2017, Tentativa de correção em casos de falta de respawn em certas areas do jogo. -Otimização de funções que lidam com popular ou despopular areas. \ No newline at end of file +Otimização de funções que lidam com popular ou despopular areas. + +07 Abril 2017, +Correção nos métodos que completam quests, que não atribuíam corretamente itens que dependem de jobs. +Agora é possível variar atributos de mobs a serem spawnados (classes ChangeableStats, OverrideStats). +Removido ataques letais (1HP/1MP) de bosses em Dojo, que tornava impossível a completude do mesmo. +Adição de novos scripts de evento no jogo. \ No newline at end of file diff --git a/nbproject/private/private.xml b/nbproject/private/private.xml index f3d2fb934b..6807a2ba19 100644 --- a/nbproject/private/private.xml +++ b/nbproject/private/private.xml @@ -2,16 +2,6 @@ - - file:/C:/Nexon/MapleSolaxia/src/scripting/event/EventManager.java - file:/C:/Nexon/MapleSolaxia/scripts/npc/world0/2012001.js - file:/C:/Nexon/MapleSolaxia/src/net/SendOpcode.java - file:/C:/Nexon/MapleSolaxia/src/server/life/SpawnPoint.java - file:/C:/Nexon/MapleSolaxia/scripts/npc/world0/2012002.js - file:/C:/Nexon/MapleSolaxia/src/server/maps/MapleMapFactory.java - file:/C:/Nexon/MapleSolaxia/src/tools/MaplePacketCreator.java - file:/C:/Nexon/MapleSolaxia/scripts/event/Boats.js - file:/C:/Nexon/MapleSolaxia/src/server/maps/MapleMap.java - + diff --git a/scripts/event/0_EXAMPLE.js b/scripts/event/0_EXAMPLE.js new file mode 100644 index 0000000000..1687a153fc --- /dev/null +++ b/scripts/event/0_EXAMPLE.js @@ -0,0 +1,76 @@ +function init() { + // After loading, ChannelServer +} + +function setup(eim, leaderid) { + // Setup the instance when invoked, EG : start PQ +} + +function playerEntry(eim, player) { + // Warp player in etc.. +} + +function changedMap(eim, player, mapid) { + // What to do when player've changed map, based on the mapid +} + +function scheduledTimeout(eim) { + // When event timeout.. + + // restartEventTimer(long time) + // stopEventTimer() + // startEventTimer(long time) + // isTimerStarted() +} + +function allMonstersDead(eim) { + // When invoking unregisterMonster(MapleMonster mob) OR killed + // Happens only when size = 0 +} + +function playerDead(eim, player) { + // Happens when player dies +} + +function playerRevive(eim, player) { + // Happens when player's revived. + // @Param : returns true/false +} + +function playerDisconnected(eim, player) { + // return 0 - Deregister player normally + Dispose instance if there are zero player left + // return x that is > 0 - Deregister player normally + Dispose instance if there x player or below + // return x that is < 0 - Deregister player normally + Dispose instance if there x player or below, if it's leader = boot all +} + +function monsterValue(eim, mobid) { + // Invoked when a monster that's registered has been killed + // return x amount for this player - "Saved Points" +} + +function leftParty(eim, player) { + // Happens when a player left the party +} + +function disbandParty(eim, player) { + // Happens when the party is disbanded by the leader. +} + +function clearPQ(eim) { + // Happens when the function EventInstanceManager.finishPQ() is invoked by NPC/Reactor script +} + +function removePlayer(eim, player) { + // Happens when the funtion NPCConversationalManager.removePlayerFromInstance() is invoked +} + +function registerCarnivalParty(eim, carnivalparty) { + // Happens when carnival PQ is started. - Unused for now. +} + +function onMapLoad(eim, player) { + // Happens when player change map - Unused for now. +} + +function cancelSchedule() { +} \ No newline at end of file diff --git a/scripts/event/s4aWorld.js b/scripts/event/s4aWorld.js new file mode 100644 index 0000000000..2cc476082e --- /dev/null +++ b/scripts/event/s4aWorld.js @@ -0,0 +1,84 @@ +/* + * 4th Job Snipe / Concentration + */ + +function init() { + em.setProperty("started", "false"); +} + +function monsterValue(eim, mobId) { + return 1; +} + +function setup() { + var eim = em.newInstance("s4aWorld"); + + eim.setInstanceMap(910500000).resetFully(); + eim.startEventTimer(1200000); + + em.setProperty("started", "true"); + + return eim; +} + +function playerEntry(eim, player) { + var map = eim.getMapFactory().getMap(910500000); + player.changeMap(map, map.getPortal(0)); +} + +function playerDead(eim, player) { +} + +function playerRevive(eim, player) { +} + +function scheduledTimeout(eim) { + eim.disposeIfPlayerBelow(100, 105090200); + + em.setProperty("started", "false"); +} + +function changedMap(eim, player, mapid) { + if (mapid != 910500000) { + eim.unregisterPlayer(player); + + if (eim.disposeIfPlayerBelow(0, 0)) { + em.setProperty("started", "false"); + } + } +} + +function playerDisconnected(eim, player) { + return 0; +} + +function leftParty(eim, player) { + // If only 2 players are left, uncompletable: + playerExit(eim, player); +} + +function disbandParty(eim) { + //boot whole party and end + eim.disposeIfPlayerBelow(100, 105090200); + + em.setProperty("started", "false"); +} + +function playerExit(eim, player) { + eim.unregisterPlayer(player); + var map = eim.getMapFactory().getMap(105090200); + player.changeMap(map, map.getPortal(0)); +} + +function clearPQ(eim) { + eim.disposeIfPlayerBelow(100, 105090200); + + em.setProperty("started", "false"); +} + +function allMonstersDead(eim) { +//has nothing to do with monster killing +} + +function cancelSchedule() { +} \ No newline at end of file diff --git a/scripts/npc/world0/1061012.js b/scripts/npc/world0/1061012.js new file mode 100644 index 0000000000..7161167a13 --- /dev/null +++ b/scripts/npc/world0/1061012.js @@ -0,0 +1,62 @@ +/* + NPC Name: Insiginificant Being + Map(s): Dungeon : Another Entrance + Description: Takes you to another Dimension +*/ + +function start() { + if (cm.getQuestStatus(6108) == 1) { + var ret = checkJob(); + if (ret == -1) { + cm.sendOk("Please form a party and talk to me again."); + } else if (ret == 0) { + cm.sendOk("Please make sure that your party is a size of 2."); + } else if (ret == 1) { + cm.sendOk("One of your party member's job is not eligible for entering the other world."); + } else if (ret == 2) { + cm.sendOk("One of your party member's level is not eligible for entering the other world."); + } else { + var em = cm.getEventManager("s4aWorld"); + if (em == null) { + cm.sendOk("You're not allowed to enter with unknown reason. Try again." ); + } else if (em.getProperty("started").equals("true")) { + cm.sendOk("Someone else is already attempting to defeat the Jr.Balrog in another world." ); + } else { + em.startInstance(cm.getParty(), cm.getMap()); + } + } + } + else { + cm.sendOk("You're not allowed to enter the other world with unknown reason."); + } + + cm.dispose(); +} + +function action(mode, type, selection) { +} + +function checkJob() { + var party = cm.getParty(); + + if (party == null) { + return -1; + } + // if (party.getMembers().size() != 2) { + // return 0; + // } + var it = party.getMembers().iterator(); + + while (it.hasNext()) { + var cPlayer = it.next(); + + if (cPlayer.getJobId() == 312 || cPlayer.getJobId() == 322 || cPlayer.getJobId() == 900) { + if (cPlayer.getLevel() < 120) { + return 2; + } + } else { + return 1; + } + } + return 3; +} \ No newline at end of file diff --git a/sql/db_database.sql b/sql/db_database.sql index fece777b54..dd396c33e9 100644 --- a/sql/db_database.sql +++ b/sql/db_database.sql @@ -12786,8 +12786,8 @@ CREATE TABLE IF NOT EXISTS `drop_data_global` ( ) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC AUTO_INCREMENT=5 ; INSERT INTO `drop_data_global` (`id`, `continent`, `dropType`, `itemid`, `minimum_quantity`, `maximum_quantity`, `questid`, `chance`, `comments`) VALUES -(1, 0, 0, 4031865, 1, 1, 0, 150000, 'NX Card 100 PTS'), -(2, 0, 0, 4031866, 1, 1, 0, 90000, 'NX Card 250 PTS'), +(1, 0, 0, 4031865, 1, 1, 0, 125000, 'NX Card 100 PTS'), +(2, 0, 0, 4031866, 1, 1, 0, 78000, 'NX Card 250 PTS'), (3, 0, 0, 4001126, 1, 2, 0, 10000, 'Maple Leaves'), (4, 0, 0, 2049100, 1, 1, 0, 1500, 'Chaos Scroll 60%'), (5, 0, 0, 4001006, 1, 1, 0, 12000, 'Flaming Feather'); diff --git a/sql/db_drops.sql b/sql/db_drops.sql index f2fef6d3ff..af01c54935 100644 --- a/sql/db_drops.sql +++ b/sql/db_drops.sql @@ -18839,9 +18839,9 @@ UPDATE drop_data SET questid=6191 WHERE itemid=4001107; UPDATE drop_data SET questid=28344 WHERE itemid=4032475; - UPDATE drop_data SET questid=77777 WHERE itemid=4001358; #id 77777 for ALL "quest items" with no v83 quest. - UPDATE drop_data SET questid=77777 WHERE itemid=4001359; - UPDATE drop_data SET questid=77777 WHERE itemid=4001342; + UPDATE drop_data SET questid=7777 WHERE itemid=4001358; #id 7777 for ALL "quest items" with no v83 quest. + UPDATE drop_data SET questid=7777 WHERE itemid=4001359; + UPDATE drop_data SET questid=7777 WHERE itemid=4001342; UPDATE drop_data SET chance=0 WHERE itemid=2050099; UPDATE drop_data SET chance=40000 WHERE itemid=4031991; UPDATE drop_data SET questid=6191 WHERE itemid=4031477; diff --git a/src/client/MapleJob.java b/src/client/MapleJob.java index 511471c61b..9c1287f3e4 100644 --- a/src/client/MapleJob.java +++ b/src/client/MapleJob.java @@ -123,4 +123,17 @@ public enum MapleJob { public boolean isA(MapleJob basejob) { return getId() >= basejob.getId() && getId() / 100 == basejob.getId() / 100; } + + public int getJobNiche() { + return (jobid / 100) % 10; + + /* + case 0: BEGINNER; + case 1: WARRIOR; + case 2: MAGICIAN; + case 3: BOWMAN; + case 4: THIEF; + case 5: PIRATE; + */ + } } diff --git a/src/constants/GameConstants.java b/src/constants/GameConstants.java index ae4ae339cc..f399d8ebb0 100644 --- a/src/constants/GameConstants.java +++ b/src/constants/GameConstants.java @@ -7,6 +7,17 @@ import constants.skills.Aran; * @author kevintjuh93 */ public class GameConstants { + private static final int[] mobHpVal = {0, 15, 20, 25, 35, 50, 65, 80, 95, 110, 125, 150, 175, 200, 225, 250, 275, 300, 325, 350, + 375, 405, 435, 465, 495, 525, 580, 650, 720, 790, 900, 990, 1100, 1200, 1300, 1400, 1500, 1600, 1700, 1800, + 1900, 2000, 2100, 2200, 2300, 2400, 2520, 2640, 2760, 2880, 3000, 3200, 3400, 3600, 3800, 4000, 4300, 4600, 4900, 5200, + 5500, 5900, 6300, 6700, 7100, 7500, 8000, 8500, 9000, 9500, 10000, 11000, 12000, 13000, 14000, 15000, 17000, 19000, 21000, 23000, + 25000, 27000, 29000, 31000, 33000, 35000, 37000, 39000, 41000, 43000, 45000, 47000, 49000, 51000, 53000, 55000, 57000, 59000, 61000, 63000, + 65000, 67000, 69000, 71000, 73000, 75000, 77000, 79000, 81000, 83000, 85000, 89000, 91000, 93000, 95000, 97000, 99000, 101000, 103000, + 105000, 107000, 109000, 111000, 113000, 115000, 118000, 120000, 125000, 130000, 135000, 140000, 145000, 150000, 155000, 160000, 165000, 170000, 175000, 180000, + 185000, 190000, 195000, 200000, 205000, 210000, 215000, 220000, 225000, 230000, 235000, 240000, 250000, 260000, 270000, 280000, 290000, 300000, 310000, 320000, + 330000, 340000, 350000, 360000, 370000, 380000, 390000, 400000, 410000, 420000, 430000, 440000, 450000, 460000, 470000, 480000, 490000, 500000, 510000, 520000, + 530000, 550000, 570000, 590000, 610000, 630000, 650000, 670000, 690000, 710000, 730000, 750000, 770000, 790000, 810000, 830000, 850000, 870000, 890000, 910000}; + public static int getHiddenSkill(final int skill) { switch (skill) { @@ -96,4 +107,11 @@ public class GameConstants { return false; } } + + public static int getMonsterHP(final int level) { + if (level < 0 || level >= mobHpVal.length) { + return Integer.MAX_VALUE; + } + return mobHpVal[level]; + } } diff --git a/src/constants/ServerConstants.java b/src/constants/ServerConstants.java index cfeeb8747c..5b46843fbe 100644 --- a/src/constants/ServerConstants.java +++ b/src/constants/ServerConstants.java @@ -55,6 +55,9 @@ public class ServerConstants { public static final double PET_AUTOHP_RATIO = 0.99; //will automatically consume potions until given ratio of the MaxHP/MaxMP is reached. public static final double PET_AUTOMP_RATIO = 0.99; + //Should bosses use 1HP,1MP attacks in dojo? + public static final boolean USE_DEADLY_DOJO = false; + //Rates public static final int EXP_RATE = 10; public static final int MESO_RATE = 10; diff --git a/src/net/server/channel/handlers/AbstractDealDamageHandler.java b/src/net/server/channel/handlers/AbstractDealDamageHandler.java index 9590afc855..0e864510e7 100644 --- a/src/net/server/channel/handlers/AbstractDealDamageHandler.java +++ b/src/net/server/channel/handlers/AbstractDealDamageHandler.java @@ -273,15 +273,14 @@ public abstract class AbstractDealDamageHandler extends AbstractMaplePacketHandl Skill pickpocket = SkillFactory.getSkill(ChiefBandit.PICKPOCKET); int delay = 0; final int maxmeso = player.getBuffedValue(MapleBuffStat.PICKPOCKET).intValue(); - for (Integer eachd : onedList) { - - eachd += Integer.MAX_VALUE; + for (Integer eachd : onedList) { + eachd += Integer.MAX_VALUE; if (pickpocket.getEffect(player.getSkillLevel(pickpocket)).makeChanceResult()) { - final Integer eachdf; - if(eachd < 0) - eachdf = eachd + Integer.MAX_VALUE; - else - eachdf = eachd; + final Integer eachdf; + if(eachd < 0) + eachdf = eachd + Integer.MAX_VALUE; + else + eachdf = eachd; TimerManager.getInstance().schedule(new Runnable() { @Override diff --git a/src/net/server/channel/handlers/TakeDamageHandler.java b/src/net/server/channel/handlers/TakeDamageHandler.java index 0d5f7755b3..4c95b0b7fd 100644 --- a/src/net/server/channel/handlers/TakeDamageHandler.java +++ b/src/net/server/channel/handlers/TakeDamageHandler.java @@ -30,6 +30,7 @@ import client.inventory.Item; import client.inventory.MapleInventoryType; import client.status.MonsterStatus; import client.status.MonsterStatusEffect; +import constants.ServerConstants; import constants.skills.Aran; import constants.skills.Corsair; @@ -63,7 +64,7 @@ public final class TakeDamageHandler extends AbstractMaplePacketHandler { int damage = slea.readInt(); int oid = 0, monsteridfrom = 0, pgmr = 0, direction = 0; int pos_x = 0, pos_y = 0, fake = 0; - boolean is_pgmr = false, is_pg = true; + boolean is_pgmr = false, is_pg = true, is_deadly = false; int mpattack = 0; MapleMonster attacker = null; final MapleMap map = player.getMap(); @@ -111,6 +112,7 @@ public final class TakeDamageHandler extends AbstractMaplePacketHandler { if (attackInfo != null) { if (attackInfo.isDeadlyAttack()) { mpattack = player.getMp() - 1; + is_deadly = true; } mpattack += attackInfo.getMpBurn(); MobSkill skill = MobSkillFactory.getMobSkill(attackInfo.getDiseaseSkill(), attackInfo.getDiseaseLevel()); @@ -142,6 +144,13 @@ public final class TakeDamageHandler extends AbstractMaplePacketHandler { if (damage == -1) { fake = 4020002 + (player.getJob().getId() / 10 - 40) * 100000; } + + //in dojo player cannot use pot, so deadly attacks should be turned off as well + if(is_deadly && player.getMap().isDojoMap() && !ServerConstants.USE_DEADLY_DOJO) { + damage = 0; + mpattack = 0; + } + if (damage == 0) { player.getAutobanManager().addMiss(); } else { diff --git a/src/scripting/event/EventInstanceManager.java b/src/scripting/event/EventInstanceManager.java index 51fe219b5d..450bd9c5c7 100644 --- a/src/scripting/event/EventInstanceManager.java +++ b/src/scripting/event/EventInstanceManager.java @@ -30,6 +30,8 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Properties; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantReadWriteLock; import javax.script.ScriptException; @@ -61,6 +63,8 @@ public class EventInstanceManager { private MapleExpedition expedition = null; private List mapIds = new LinkedList(); private List isInstanced = new LinkedList(); + private final ReentrantReadWriteLock mutex = new ReentrantReadWriteLock(); + private final Lock rL = mutex.readLock(), wL = mutex.writeLock(); private boolean disposed = false; public EventInstanceManager(EventManager em, String name) { @@ -78,8 +82,16 @@ public class EventInstanceManager { if (chr == null || !chr.isLoggedin()){ return; } - try { - chars.add(chr); + + try { + wL.lock(); + try { + chars.add(chr); + } + finally { + wL.unlock(); + } + chr.setEventInstance(this); em.getIv().invokeFunction("playerEntry", this, chr); } catch (ScriptException | NoSuchMethodException ex) { @@ -125,7 +137,13 @@ public class EventInstanceManager { } public void unregisterPlayer(MapleCharacter chr) { - chars.remove(chr); + wL.lock(); + try { + chars.remove(chr); + } finally { + wL.unlock(); + } + chr.setEventInstance(null); } @@ -346,4 +364,37 @@ public class EventInstanceManager { isInstanced.add(false); return this.getMapFactory().getMap(mapid); } + + public final boolean disposeIfPlayerBelow(final byte size, final int towarp) { + if (disposed) { + return true; + } + MapleMap map = null; + if (towarp > 0) { + map = this.getMapFactory().getMap(towarp); + } + + wL.lock(); + try { + if (chars != null && chars.size() <= size) { + final List chrs = new LinkedList(chars); + for (MapleCharacter chr : chrs) { + if (chr == null) { + continue; + } + unregisterPlayer(chr); + if (towarp > 0) { + chr.changeMap(map, map.getPortal(0)); + } + } + dispose(); + return true; + } + } catch (Exception ex) { + ex.printStackTrace(); + } finally { + wL.unlock(); + } + return false; + } } diff --git a/src/server/life/ChangeableStats.java b/src/server/life/ChangeableStats.java new file mode 100644 index 0000000000..a4ffa7cd85 --- /dev/null +++ b/src/server/life/ChangeableStats.java @@ -0,0 +1,50 @@ +/* +This file is part of the OdinMS Maple Story Server +Copyright (C) 2008 ~ 2010 Patrick Huy +Matthias Butz +Jan Christian Meyer +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License version 3 +as published by the Free Software Foundation. You may not use, modify +or distribute this program under any other version of the +GNU Affero General Public License. +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + */ +package server.life; + +import constants.GameConstants; + +public class ChangeableStats extends OverrideMonsterStats { + + public int watk, matk, wdef, mdef, level; + + public ChangeableStats(MapleMonsterStats stats, OverrideMonsterStats ostats) { + hp = ostats.getHp(); + exp = ostats.getExp(); + mp = ostats.getMp(); + watk = stats.getPADamage(); + matk = stats.getMADamage(); + wdef = stats.getPDDamage(); + mdef = stats.getMDDamage(); + level = stats.getLevel(); + } + + public ChangeableStats(MapleMonsterStats stats, int newLevel, boolean pqMob) { // here we go i think + final double mod = (double) newLevel / (double) stats.getLevel(); + final double hpRatio = (double) stats.getHp() / (double) stats.getExp(); + final double pqMod = (pqMob ? 1.5 : 1.0); // god damn + hp = (int) Math.round((!stats.isBoss() ? GameConstants.getMonsterHP(newLevel) : (stats.getHp() * mod)) * pqMod); // right here lol + exp = (int) Math.round((!stats.isBoss() ? (GameConstants.getMonsterHP(newLevel) / hpRatio) : (stats.getExp())) * pqMod); + mp = (int) Math.round(stats.getMp() * mod * pqMod); + watk = (int) Math.round(stats.getPADamage() * mod); + matk = (int) Math.round(stats.getMADamage() * mod); + wdef = Math.min(stats.isBoss() ? 30 : 20, (int) Math.round(stats.getPDDamage() * mod)); + mdef = Math.min(stats.isBoss() ? 30 : 20, (int) Math.round(stats.getMDDamage() * mod)); + level = newLevel; + } +} \ No newline at end of file diff --git a/src/server/life/MapleMonster.java b/src/server/life/MapleMonster.java index 41290adcfa..dceccf9600 100644 --- a/src/server/life/MapleMonster.java +++ b/src/server/life/MapleMonster.java @@ -63,7 +63,7 @@ import tools.Pair; import tools.Randomizer; public class MapleMonster extends AbstractLoadedMapleLife { - + private ChangeableStats ostats = null; //unused, v83 WZs offers no support for changeable stats. private MapleMonsterStats stats; private int hp, mp; private WeakReference controller = new WeakReference<>(null); @@ -957,4 +957,36 @@ public class MapleMonster extends AbstractLoadedMapleLife { public Map getStati() { return stati; } + + // ---- one can always have fun trying these pieces of codes below in-game rofl ---- + + public final ChangeableStats getChangedStats() { + return ostats; + } + + public final int getMobMaxHp() { + if (ostats != null) { + return ostats.hp; + } + return stats.getHp(); + } + + public final void setOverrideStats(final OverrideMonsterStats ostats) { + this.ostats = new ChangeableStats(stats, ostats); + this.hp = ostats.getHp(); + this.mp = ostats.getMp(); + } + + public final void changeLevel(final int newLevel) { + changeLevel(newLevel, true); + } + + public final void changeLevel(final int newLevel, boolean pqMob) { + if (!stats.isChangeable()) { + return; + } + this.ostats = new ChangeableStats(stats, newLevel, pqMob); + this.hp = ostats.getHp(); + this.mp = ostats.getMp(); + } } diff --git a/src/server/life/MapleMonsterStats.java b/src/server/life/MapleMonsterStats.java index 65a20703b6..2d7c5738c6 100644 --- a/src/server/life/MapleMonsterStats.java +++ b/src/server/life/MapleMonsterStats.java @@ -36,6 +36,7 @@ import tools.Pair; * @author Frz */ public class MapleMonsterStats { + private boolean changeable; private int exp, hp, mp, level, PADamage, PDDamage, MADamage, MDDamage, dropPeriod, cp, buffToGive, removeAfter; private boolean boss, undead, ffaLoot, isExplosiveReward, firstAttack, removeOnMiss; private String name; @@ -50,6 +51,14 @@ public class MapleMonsterStats { private selfDestruction selfDestruction = null; private boolean friendly; + public void setChange(boolean change) { + this.changeable = change; + } + + public boolean isChangeable() { + return changeable; + } + public int getExp() { return exp; } diff --git a/src/server/life/OverrideMonsterStats.java b/src/server/life/OverrideMonsterStats.java new file mode 100644 index 0000000000..45be7fd624 --- /dev/null +++ b/src/server/life/OverrideMonsterStats.java @@ -0,0 +1,64 @@ +/* +This file is part of the OdinMS Maple Story Server +Copyright (C) 2008 ~ 2010 Patrick Huy +Matthias Butz +Jan Christian Meyer +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License version 3 +as published by the Free Software Foundation. You may not use, modify +or distribute this program under any other version of the +GNU Affero General Public License. +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + */ +package server.life; + +public class OverrideMonsterStats { + + public int hp; + public int exp, mp; + + public OverrideMonsterStats() { + hp = 1; + exp = 0; + mp = 0; + } + + public OverrideMonsterStats(int hp, int mp, int exp, boolean change) { + this.hp = /*change ? (hp * 3L / 2L) : */ hp; + this.mp = mp; + this.exp = exp; + } + + public OverrideMonsterStats(int hp, int mp, int exp) { + this(hp, mp, exp, true); + } + + public int getExp() { + return exp; + } + + public void setOExp(int exp) { + this.exp = exp; + } + + public int getHp() { + return hp; + } + + public void setOHp(int hp) { + this.hp = hp; + } + + public int getMp() { + return mp; + } + + public void setOMp(int mp) { + this.mp = mp; + } +} \ No newline at end of file diff --git a/src/server/maps/MapleMap.java b/src/server/maps/MapleMap.java index 8c932edcf7..591e841247 100644 --- a/src/server/maps/MapleMap.java +++ b/src/server/maps/MapleMap.java @@ -368,14 +368,14 @@ public class MapleMap { final MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance(); final byte droptype = (byte) (mob.getStats().isExplosiveReward() ? 3 : mob.getStats().isFfaLoot() ? 2 : chr.getParty() != null ? 1 : 0); final int mobpos = mob.getPosition().x; - int chServerrate = chr.getDropRate(); + int chRate = chr.getDropRate(); Item idrop; byte d = 1; Point pos = new Point(0, mob.getPosition().y); Map stati = mob.getStati(); if (stati.containsKey(MonsterStatus.SHOWDOWN)) { - chServerrate *= (stati.get(MonsterStatus.SHOWDOWN).getStati().get(MonsterStatus.SHOWDOWN).doubleValue() / 100.0 + 1.0); + chRate *= (stati.get(MonsterStatus.SHOWDOWN).getStati().get(MonsterStatus.SHOWDOWN).doubleValue() / 100.0 + 1.0); } final MapleMonsterInformationProvider mi = MapleMonsterInformationProvider.getInstance(); @@ -383,7 +383,7 @@ public class MapleMap { Collections.shuffle(dropEntry); for (final MonsterDropEntry de : dropEntry) { - if (Randomizer.nextInt(999999) < de.chance * chServerrate) { + if (Randomizer.nextInt(999999) < de.chance * chRate) { if (droptype == 3) { pos.x = (int) (mobpos + (d % 2 == 0 ? (40 * (d + 1) / 2) : -(40 * (d / 2)))); } else { @@ -418,9 +418,7 @@ public class MapleMap { } else { pos.x = (int) (mobpos + ((d % 2 == 0) ? (25 * (d + 1) / 2) : -(25 * (d / 2)))); } - if (de.itemId == 0) { - //chr.getCashShop().gainCash(1, 80); - } else { + if (de.itemId != 0) { if (ItemConstants.getInventoryType(de.itemId) == MapleInventoryType.EQUIP) { idrop = ii.randomizeStats((Equip) ii.getEquipById(de.itemId)); } else { @@ -538,7 +536,6 @@ public class MapleMap { if (damage > 0) { monster.damage(chr, damage); if (!monster.isAlive()) { // monster just died - //killMonster(monster, chr, true); killed = true; } } else if (monster.getId() >= 8810002 && monster.getId() <= 8810009) { @@ -2437,4 +2434,16 @@ public class MapleMap { public void broadcastShip(final boolean state) { broadcastMessage(MaplePacketCreator.boatPacket(state)); } + + public boolean isDojoMap() { + return mapid >= 925020000 && mapid < 925040000; + } + + public final void resetFully() { + resetFully(true); + } + + public final void resetFully(final boolean respawn) { + resetMapObjects(); + } } diff --git a/src/server/quest/MapleQuest.java b/src/server/quest/MapleQuest.java index 14bc6bc0c6..8bb0ddb71a 100644 --- a/src/server/quest/MapleQuest.java +++ b/src/server/quest/MapleQuest.java @@ -104,7 +104,7 @@ public class MapleQuest { MapleData completeReqData = reqData.getChildByPath("1"); if (completeReqData != null) { for (MapleData completeReq : completeReqData.getChildren()) { - MapleQuestRequirementType type = MapleQuestRequirementType.getByWZName(completeReq.getName()); + MapleQuestRequirementType type = MapleQuestRequirementType.getByWZName(completeReq.getName()); MapleQuestRequirement req = this.getRequirement(type, completeReq); if(req == null) continue; @@ -222,6 +222,10 @@ public class MapleQuest { for (MapleQuestAction a : completeActs.values()) { a.run(c, selection); } + + //dont seems to work... + //c.getClient().getSession().write(MaplePacketCreator.showForeignEffect(12)); // Quest completion + //c.getMap().broadcastMessage(c, MaplePacketCreator.showForeignEffect(c.getId(), 12), false); } } diff --git a/src/server/quest/MapleQuestRequirementType.java b/src/server/quest/MapleQuestRequirementType.java index a89d1fce6d..50e69da3d5 100644 --- a/src/server/quest/MapleQuestRequirementType.java +++ b/src/server/quest/MapleQuestRequirementType.java @@ -76,12 +76,12 @@ public enum MapleQuestRequirementType { return INFO_EX; } else if (name.equals("questComplete")) { return COMPLETED_QUEST; - } else if(name.equals("start")) { - return START; - } else if(name.equals("end")) { - return END; - } else if(name.equals("daybyday")) { - return DAY_BY_DAY; + } else if(name.equals("start")) { + return START; + } else if(name.equals("end")) { + return END; + } else if(name.equals("daybyday")) { + return DAY_BY_DAY; } else { return UNDEFINED; } diff --git a/src/server/quest/actions/ItemAction.java b/src/server/quest/actions/ItemAction.java index 5b6b44aa2d..fdd516a2d7 100644 --- a/src/server/quest/actions/ItemAction.java +++ b/src/server/quest/actions/ItemAction.java @@ -178,14 +178,29 @@ public class ItemAction extends MapleQuestAction { if (item.getGender() != 2 && item.getGender() != chr.getGender()) { return false; } - - if(item.getJob() != -1) { - if (item.getJob() != chr.getJob().getId()) { - return false; - } else if (MapleJob.getBy5ByteEncoding(item.getJob()).getId() / 100 != chr.getJob().getId() / 100) { - return false; - } - } + + if (item.job > 0) { + final List code = getJobBy5ByteEncoding(item.getJob()); + boolean jobFound = false; + for (int codec : code) { + if (codec / 100 == chr.getJob().getId() / 100) { + jobFound = true; + break; + } + } + /* + if (!jobFound && item.jobEx > 0) { + final List codeEx = getJobBySimpleEncoding(item.jobEx); + for (int codec : codeEx) { + if ((codec / 100 % 10) == (chr.getJob().getId() / 100 % 10)) { + jobFound = true; + break; + } + } + } + */ + return jobFound; + } return true; } diff --git a/src/server/quest/actions/MapleQuestAction.java b/src/server/quest/actions/MapleQuestAction.java index b82a139920..9bdd70d683 100644 --- a/src/server/quest/actions/MapleQuestAction.java +++ b/src/server/quest/actions/MapleQuestAction.java @@ -11,6 +11,9 @@ import provider.MapleData; import server.quest.MapleQuest; import server.quest.MapleQuestActionType; +import java.util.List; +import java.util.ArrayList; + /** * * @author Tyler (Twdtwd) @@ -34,6 +37,86 @@ public abstract class MapleQuestAction { } public MapleQuestActionType getType() { - return type; - } + return type; + } + + public static List getJobBy5ByteEncoding(int encoded) { + List ret = new ArrayList(); + if ((encoded & 0x1) != 0) { + ret.add(0); + } + if ((encoded & 0x2) != 0) { + ret.add(100); + } + if ((encoded & 0x4) != 0) { + ret.add(200); + } + if ((encoded & 0x8) != 0) { + ret.add(300); + } + if ((encoded & 0x10) != 0) { + ret.add(400); + } + if ((encoded & 0x20) != 0) { + ret.add(500); + } + if ((encoded & 0x400) != 0) { + ret.add(1000); + } + if ((encoded & 0x800) != 0) { + ret.add(1100); + } + if ((encoded & 0x1000) != 0) { + ret.add(1200); + } + if ((encoded & 0x2000) != 0) { + ret.add(1300); + } + if ((encoded & 0x4000) != 0) { + ret.add(1400); + } + if ((encoded & 0x8000) != 0) { + ret.add(1500); + } + if ((encoded & 0x20000) != 0) { + ret.add(2001); //im not sure of this one + ret.add(2200); + } + if ((encoded & 0x100000) != 0) { + ret.add(2000); + ret.add(2001); //? + } + if ((encoded & 0x200000) != 0) { + ret.add(2100); + } + if ((encoded & 0x400000) != 0) { + ret.add(2001); //? + ret.add(2200); + } + + if ((encoded & 0x40000000) != 0) { //i haven't seen any higher than this o.o + ret.add(3000); + ret.add(3200); + ret.add(3300); + ret.add(3500); + } + return ret; + } + + public static List getJobBySimpleEncoding(int encoded) { + List ret = new ArrayList(); + if ((encoded & 0x1) != 0) { + ret.add(200); + } + if ((encoded & 0x2) != 0) { + ret.add(300); + } + if ((encoded & 0x4) != 0) { + ret.add(400); + } + if ((encoded & 0x8) != 0) { + ret.add(500); + } + return ret; + } } diff --git a/src/tools/MaplePacketCreator.java b/src/tools/MaplePacketCreator.java index 7e7fa9bddb..9325e2e1aa 100644 --- a/src/tools/MaplePacketCreator.java +++ b/src/tools/MaplePacketCreator.java @@ -112,6876 +112,6880 @@ import constants.skills.ThunderBreaker; */ public class MaplePacketCreator { - public static final List> EMPTY_STATUPDATE = Collections.emptyList(); - private final static long FT_UT_OFFSET = 116444592000000000L; // EDT - private final static long DEFAULT_TIME = 150842304000000000L;//00 80 05 BB 46 E6 17 02 - public final static long ZERO_TIME = 94354848000000000L;//00 40 E0 FD 3B 37 4F 01 - private final static long PERMANENT = 150841440000000000L; // 00 C0 9B 90 7D E5 17 02 + public static final List> EMPTY_STATUPDATE = Collections.emptyList(); + private final static long FT_UT_OFFSET = 116444592000000000L; // EDT + private final static long DEFAULT_TIME = 150842304000000000L;//00 80 05 BB 46 E6 17 02 + public final static long ZERO_TIME = 94354848000000000L;//00 40 E0 FD 3B 37 4F 01 + private final static long PERMANENT = 150841440000000000L; // 00 C0 9B 90 7D E5 17 02 + + private static long getTime(long realTimestamp) { + if (realTimestamp == -1) { + return DEFAULT_TIME;//high number ll + } else if (realTimestamp == -2) { + return ZERO_TIME; + } else if (realTimestamp == -3) { + return PERMANENT; + } + return realTimestamp * 10000 + FT_UT_OFFSET; + } - private static long getTime(long realTimestamp) { - if (realTimestamp == -1) { - return DEFAULT_TIME;//high number ll - } else if (realTimestamp == -2) { - return ZERO_TIME; - } else if (realTimestamp == -3) { - return PERMANENT; - } - return realTimestamp * 10000 + FT_UT_OFFSET; - } - public static byte[] showHpHealed(int cid, int amount) { - MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SHOW_FOREIGN_EFFECT.getValue()); - mplew.writeInt(cid); - mplew.write(0x0A); //Type - mplew.write(amount); - return mplew.getPacket(); + MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SHOW_FOREIGN_EFFECT.getValue()); + mplew.writeInt(cid); + mplew.write(0x0A); //Type + mplew.write(amount); + return mplew.getPacket(); } - private static void addCharStats(final MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { - mplew.writeInt(chr.getId()); // character id - mplew.writeAsciiString(StringUtil.getRightPaddedStr(chr.getName(), '\0', 13)); - mplew.write(chr.getGender()); // gender (0 = male, 1 = female) - mplew.write(chr.getSkinColor().getId()); // skin color - mplew.writeInt(chr.getFace()); // face - mplew.writeInt(chr.getHair()); // hair - - for (int i = 0; i < 3; i++) { - if (chr.getPet(i) != null) //Checked GMS.. and your pets stay when going into the cash shop. - { - mplew.writeLong(chr.getPet(i).getUniqueId()); - } else { - mplew.writeLong(0); - } - } - - mplew.write(chr.getLevel()); // level - mplew.writeShort(chr.getJob().getId()); // job - mplew.writeShort(chr.getStr()); // str - mplew.writeShort(chr.getDex()); // dex - mplew.writeShort(chr.getInt()); // int - mplew.writeShort(chr.getLuk()); // luk - mplew.writeShort(chr.getHp()); // hp (?) - mplew.writeShort(chr.getMaxHp()); // maxhp - mplew.writeShort(chr.getMp()); // mp (?) - mplew.writeShort(chr.getMaxMp()); // maxmp - mplew.writeShort(chr.getRemainingAp()); // remaining ap - if (GameConstants.hasSPTable(chr.getJob())) { - mplew.write(chr.getRemainingSpSize()); - for (int i = 0; i < chr.getRemainingSps().length; i++) { - if (chr.getRemainingSpBySkill(i) > 0) { - mplew.write(i + 1); - mplew.write(chr.getRemainingSpBySkill(i)); - } - } - } else { - mplew.writeShort(chr.getRemainingSp()); // remaining sp - } - mplew.writeInt(chr.getExp()); // current exp - mplew.writeShort(chr.getFame()); // fame - mplew.writeInt(chr.getGachaExp()); //Gacha Exp - mplew.writeInt(chr.getMapId()); // current map id - mplew.write(chr.getInitialSpawnpoint()); // spawnpoint - mplew.writeInt(0); - } - - private static void addCharLook(final MaplePacketLittleEndianWriter mplew, MapleCharacter chr, boolean mega) { - mplew.write(chr.getGender()); - mplew.write(chr.getSkinColor().getId()); // skin color - mplew.writeInt(chr.getFace()); // face - mplew.write(mega ? 0 : 1); - mplew.writeInt(chr.getHair()); // hair - addCharEquips(mplew, chr); - } - - private static void addCharacterInfo(final MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { - mplew.writeLong(-1); - 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);//have fun! - addAreaInfo(mplew, chr);//assuming it stayed here xd - mplew.writeShort(0); - } - - private static void addNewYearInfo(final MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { - mplew.writeShort(0); - /* - *(_DWORD *)this = CInPacket::Decode4(a2); - *((_DWORD *)v2 + 1) = CInPacket::Decode4(a2); - CInPacket::DecodeStr(&v7); - v9 = 0; - (*(void (__stdcall **)(char *, int))((char *)&loc_B1410B + 1))((char *)v2 + 8, v7); - *(_DWORD *)((char *)v2 + 21) = (unsigned __int8)CInPacket::Decode1(a2); - CInPacket::DecodeBuffer((char *)v2 + 25, 8); - *(_DWORD *)((char *)v2 + 33) = CInPacket::Decode4(a2); - CInPacket::DecodeStr(&v6); - LOBYTE(v8) = 1; - (*(void (__stdcall **)(char *, int))((char *)&loc_B1410B + 1))((char *)v2 + 37, v6); - *(_DWORD *)((char *)v2 + 50) = (unsigned __int8)CInPacket::Decode1(a2); - *(_DWORD *)((char *)v2 + 54) = (unsigned __int8)CInPacket::Decode1(a2); - CInPacket::DecodeBuffer((char *)v2 + 58, 8); - CInPacket::DecodeStr(&v9); - */ - } - - private static void addTeleportInfo(final MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { - final List tele = chr.getTrockMaps(); - final List viptele = chr.getVipTrockMaps(); - for (int i = 0; i < 5; i++) { - mplew.writeInt(tele.get(i)); - } - for (int i = 0; i < 10; i++) { - mplew.writeInt(viptele.get(i)); - } - } - - private static void addMiniGameInfo(final MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { - mplew.writeShort(0); - /*for (int m = size; m > 0; m--) {//nexon does this :P - mplew.writeInt(0); - mplew.writeInt(0); - mplew.writeInt(0); - mplew.writeInt(0); - mplew.writeInt(0); - }*/ - } - - private static void addAreaInfo(final MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { - Map areaInfos = chr.getAreaInfos(); - mplew.writeShort(areaInfos.size()); - for (Short area : areaInfos.keySet()) { - mplew.writeShort(area); - mplew.writeMapleAsciiString(areaInfos.get(area)); - } - } - - private static void addCharEquips(final MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { - MapleInventory equip = chr.getInventory(MapleInventoryType.EQUIPPED); - Collection ii = MapleItemInformationProvider.getInstance().canWearEquipment(chr, equip.list()); - Map myEquip = new LinkedHashMap<>(); - Map maskedEquip = new LinkedHashMap<>(); - for (Item item : ii) { - short pos = (byte) (item.getPosition() * -1); - if (pos < 100 && myEquip.get(pos) == null) { - myEquip.put(pos, item.getItemId()); - } else if (pos > 100 && pos != 111) { // don't ask. o.o - 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 (Entry entry : myEquip.entrySet()) { - mplew.write(entry.getKey()); - mplew.writeInt(entry.getValue()); - } - mplew.write(0xFF); - for (Entry entry : maskedEquip.entrySet()) { - mplew.write(entry.getKey()); - mplew.writeInt(entry.getValue()); - } - mplew.write(0xFF); - Item cWeapon = equip.getItem((short) -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).getItemId()); - } else { - mplew.writeInt(0); - } - } - } - - private static void addCharEntry(final MaplePacketLittleEndianWriter mplew, MapleCharacter chr, boolean viewall) { - addCharStats(mplew, chr); - addCharLook(mplew, chr, false); - if (!viewall) { - mplew.write(0); - } - if (chr.isGM()) { - mplew.write(0); - return; - } - mplew.write(1); // world rank enabled (next 4 ints are not sent if disabled) Short?? - mplew.writeInt(chr.getRank()); // world rank - mplew.writeInt(chr.getRankMove()); // move (negative is downwards) - mplew.writeInt(chr.getJobRank()); // job rank - mplew.writeInt(chr.getJobRankMove()); // move (negative is downwards) - } - - private static void addQuestInfo(final MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { - 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(q.getQuestData()); - } - } - List completed = chr.getCompletedQuests(); - mplew.writeShort(completed.size()); - for (MapleQuestStatus q : completed) { - mplew.writeShort(q.getQuest().getId()); - mplew.writeLong(getTime(q.getCompletionTime())); - } - } - - private static void addItemInfo(final MaplePacketLittleEndianWriter mplew, Item item) { - addItemInfo(mplew, item, false); - } - - private static void addExpirationTime(final MaplePacketLittleEndianWriter mplew, long time) { - mplew.writeLong(getTime(time)); - } - - private static void addItemInfo(final MaplePacketLittleEndianWriter mplew, Item item, boolean zeroPosition) { - MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance(); - boolean isCash = ii.isCash(item.getItemId()); - boolean isPet = item.getPetId() > -1; - boolean isRing = false; - Equip equip = null; - short pos = item.getPosition(); - if (item.getType() == 1) { - equip = (Equip) item; - isRing = equip.getRingId() > -1; - } - if (!zeroPosition) { - if (equip != null) { - if (pos < 0) { - pos *= -1; - } - mplew.writeShort(pos > 100 ? pos - 100 : pos); - } else { - mplew.write(pos); - } - } - mplew.write(item.getType()); - mplew.writeInt(item.getItemId()); - mplew.writeBool(isCash); - if (isCash) { - mplew.writeLong(isPet ? item.getPetId() : isRing ? equip.getRingId() : item.getCashId()); - } - addExpirationTime(mplew, item.getExpiration()); - if (isPet) { - MaplePet pet = item.getPet(); - mplew.writeAsciiString(StringUtil.getRightPaddedStr(pet.getName(), '\0', 13)); - mplew.write(pet.getLevel()); - mplew.writeShort(pet.getCloseness()); - mplew.write(pet.getFullness()); - addExpirationTime(mplew, item.getExpiration()); - mplew.writeInt(0); - mplew.write(new byte[]{(byte) 0x50, (byte) 0x46}); //wonder what this is - mplew.writeInt(0); - return; - } - if (equip == null) { - mplew.writeShort(item.getQuantity()); - mplew.writeMapleAsciiString(item.getOwner()); - mplew.writeShort(item.getFlag()); // flag - - if (ItemConstants.isRechargable(item.getItemId())) { - mplew.writeInt(2); - mplew.write(new byte[]{(byte) 0x54, 0, 0, (byte) 0x34}); - } - return; - } - mplew.write(equip.getUpgradeSlots()); // upgrade slots - mplew.write(equip.getLevel()); // level - mplew.writeShort(equip.getStr()); // str - mplew.writeShort(equip.getDex()); // dex - mplew.writeShort(equip.getInt()); // int - mplew.writeShort(equip.getLuk()); // luk - mplew.writeShort(equip.getHp()); // hp - mplew.writeShort(equip.getMp()); // mp - mplew.writeShort(equip.getWatk()); // watk - mplew.writeShort(equip.getMatk()); // matk - mplew.writeShort(equip.getWdef()); // wdef - mplew.writeShort(equip.getMdef()); // mdef - mplew.writeShort(equip.getAcc()); // accuracy - mplew.writeShort(equip.getAvoid()); // avoid - mplew.writeShort(equip.getHands()); // hands - mplew.writeShort(equip.getSpeed()); // speed - mplew.writeShort(equip.getJump()); // jump - mplew.writeMapleAsciiString(equip.getOwner()); // owner name - mplew.writeShort(equip.getFlag()); //Item Flags - - if (isCash) { - for (int i = 0; i < 10; i++) { - mplew.write(0x40); - } - } else { - mplew.write(0); - mplew.write(equip.getItemLevel()); //Item Level - mplew.writeShort(0); - mplew.writeShort(equip.getItemExp()); //Works pretty weird :s - mplew.writeInt(equip.getVicious()); //WTF NEXON ARE YOU SERIOUS? - mplew.writeLong(0); - } - mplew.writeLong(getTime(-2)); - mplew.writeInt(-1); - - } - - private static void addInventoryInfo(final MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { - for (byte i = 1; i <= 5; i++) { - mplew.write(chr.getInventory(MapleInventoryType.getByType(i)).getSlotLimit()); - } - mplew.writeLong(getTime(-2)); - MapleInventory iv = chr.getInventory(MapleInventoryType.EQUIPPED); - Collection equippedC = iv.list(); - List equipped = new ArrayList<>(equippedC.size()); - List equippedCash = new ArrayList<>(equippedC.size()); - for (Item 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.writeShort(0); // start of equip cash - for (Item item : equippedCash) { - addItemInfo(mplew, item); - } - mplew.writeShort(0); // start of equip inventory - for (Item item : chr.getInventory(MapleInventoryType.EQUIP).list()) { - addItemInfo(mplew, item); - } - mplew.writeInt(0); - for (Item item : chr.getInventory(MapleInventoryType.USE).list()) { - addItemInfo(mplew, item); - } - mplew.write(0); - for (Item item : chr.getInventory(MapleInventoryType.SETUP).list()) { - addItemInfo(mplew, item); - } - mplew.write(0); - for (Item item : chr.getInventory(MapleInventoryType.ETC).list()) { - addItemInfo(mplew, item); - } - mplew.write(0); - for (Item item : chr.getInventory(MapleInventoryType.CASH).list()) { - addItemInfo(mplew, item); - } - } - - private static void addSkillInfo(final MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { - mplew.write(0); // start of skills - Map skills = chr.getSkills(); - int skillsSize = skills.size(); - // We don't want to include any hidden skill in this, so subtract them from the size list and ignore them. - for (Iterator> it = skills.entrySet().iterator(); it.hasNext();) { - Entry skill = it.next(); - if (GameConstants.isHiddenSkills(skill.getKey().getId())) { - skillsSize--; - } - } - mplew.writeShort(skillsSize); - for (Iterator> it = skills.entrySet().iterator(); it.hasNext();) { - Entry skill = it.next(); - if (GameConstants.isHiddenSkills(skill.getKey().getId())) { - continue; - } - mplew.writeInt(skill.getKey().getId()); - mplew.writeInt(skill.getValue().skillevel); - addExpirationTime(mplew, skill.getValue().expiration); - if (skill.getKey().isFourthJob()) { - mplew.writeInt(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.writeShort(timeLeft / 1000); - } - } - - private static void addMonsterBookInfo(final MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { - mplew.writeInt(chr.getMonsterBookCover()); // cover - mplew.write(0); - Map cards = chr.getMonsterBook().getCards(); - mplew.writeShort(cards.size()); - for (Entry all : cards.entrySet()) { - mplew.writeShort(all.getKey() % 10000); // Id - mplew.write(all.getValue()); // Level - } - } - - public static byte[] sendGuestTOS() { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.GUEST_ID_LOGIN.getValue()); - mplew.writeShort(0x100); - mplew.writeInt(Randomizer.nextInt(999999)); - mplew.writeLong(0); - mplew.writeLong(getTime(-2)); - mplew.writeLong(getTime(System.currentTimeMillis())); - mplew.writeInt(0); - mplew.writeMapleAsciiString("http://maplesolaxia.com"); - return mplew.getPacket(); - } - - /** - * Sends a hello packet. - * - * @param mapleVersion The maple client version. - * @param sendIv the IV used by the server for sending - * @param recvIv the IV used by the server for receiving - * @return - */ - public static byte[] getHello(short mapleVersion, byte[] sendIv, byte[] recvIv) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(8); - mplew.writeShort(0x0E); - mplew.writeShort(mapleVersion); - mplew.writeShort(1); - mplew.write(49); - mplew.write(recvIv); - mplew.write(sendIv); - mplew.write(8); - return mplew.getPacket(); - } - - /** - * Sends a ping packet. - * - * @return The packet. - */ - public static byte[] getPing() { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(2); - mplew.writeShort(SendOpcode.PING.getValue()); - return mplew.getPacket(); - } - - /** - * Gets a login failed packet. - * - * Possible values for reason:
3: ID deleted or blocked
- * 4: Incorrect password
5: Not a registered id
6: System error
- * 7: Already logged in
8: System error
9: System error
10: - * Cannot process so many connections
11: Only users older than 20 can - * use this channel
13: Unable to log on as master at this ip
14: - * Wrong gateway or personal info and weird korean button
15: Processing - * request with that korean button!
16: Please verify your account - * through email...
17: Wrong gateway or personal info
21: Please - * verify your account through email...
23: License agreement
25: - * Maple Europe notice =[ FUCK YOU NEXON
27: Some weird full client - * notice, probably for trial versions
- * - * @param reason The reason logging in failed. - * @return The login failed packet. - */ - public static byte[] getLoginFailed(int reason) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(8); - mplew.writeShort(SendOpcode.LOGIN_STATUS.getValue()); - mplew.write(reason); - mplew.write(0); - mplew.writeInt(0); - return mplew.getPacket(); - } - - /** - * Gets a login failed packet. - * - * Possible values for reason:
2: ID deleted or blocked
- * 3: ID deleted or blocked
4: Incorrect password
5: Not a - * registered id
6: Trouble logging into the game?
7: Already logged - * in
8: Trouble logging into the game?
9: Trouble logging into the - * game?
10: Cannot process so many connections
11: Only users older - * than 20 can use this channel
12: Trouble logging into the game?
- * 13: Unable to log on as master at this ip
14: Wrong gateway or - * personal info and weird korean button
15: Processing request with - * that korean button!
16: Please verify your account through - * email...
17: Wrong gateway or personal info
21: Please verify - * your account through email...
23: Crashes
25: Maple Europe notice - * =[ FUCK YOU NEXON
27: Some weird full client notice, probably for - * trial versions
- * - * @param reason The reason logging in failed. - * @return The login failed packet. - */ - public static byte[] getAfterLoginError(int reason) {//same as above o.o - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(8); - mplew.writeShort(SendOpcode.SELECT_CHARACTER_BY_VAC.getValue()); - mplew.writeShort(reason);//using other types then stated above = CRASH - return mplew.getPacket(); - } - - public static byte[] sendPolice() { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.FAKE_GM_NOTICE.getValue()); - mplew.write(0);//doesn't even matter what value - return mplew.getPacket(); - } - - public static byte[] sendPolice(String text) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.DATA_CRC_CHECK_FAILED.getValue()); - mplew.writeMapleAsciiString(text); - return mplew.getPacket(); - } - - public static byte[] getPermBan(byte reason) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.LOGIN_STATUS.getValue()); - mplew.write(2); // Account is banned - mplew.write(0); - mplew.writeInt(0); - mplew.write(0); - mplew.writeLong(getTime(-1)); - - return mplew.getPacket(); - } - - public static byte[] getTempBan(long timestampTill, byte reason) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(17); - mplew.writeShort(SendOpcode.LOGIN_STATUS.getValue()); - mplew.write(2); - mplew.write(0); - mplew.writeInt(0); - mplew.write(reason); - mplew.writeLong(getTime(timestampTill)); // Tempban date is handled as a 64-bit long, number of 100NS intervals since 1/1/1601. Lulz. - - return mplew.getPacket(); - } - - /** - * Gets a successful authentication and PIN Request packet. - * - * @param c - * @param account The account name. - * @return The PIN request packet. - */ - public static byte[] getAuthSuccess(MapleClient c) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.LOGIN_STATUS.getValue()); - mplew.writeInt(0); - mplew.writeShort(0); - mplew.writeInt(c.getAccID()); //user id - mplew.write(c.getGender()); - mplew.writeBool(c.getGMLevel() > 0); //admin byte - short toWrite = (short) (c.getGMLevel() * 64); - //toWrite = toWrite |= 0x100; only in higher versions - mplew.write(toWrite >= 0x80 ? 0x80 : 0);//0x80 is admin, 0x20 and 0x40 = subgm - mplew.writeBool(c.getGMLevel() > 0); - //mplew.writeShort(toWrite > 0x80 ? 0x80 : toWrite); only in higher versions... - mplew.writeMapleAsciiString(c.getAccountName()); - mplew.write(0); - mplew.write(0); //isquietbanned - mplew.writeLong(0);//isquietban time - mplew.writeLong(c.getSessionId()); //creation time - mplew.writeInt(0); - mplew.writeShort(2);//PIN - - return mplew.getPacket(); - } - - /** - * Gets a packet detailing a PIN operation. - * - * Possible values for mode:
0 - PIN was accepted
1 - - * Register a new PIN
2 - Invalid pin / Reenter
3 - Connection - * failed due to system error
4 - Enter the pin - * - * @param mode The mode. - * @return - */ - private static byte[] pinOperation(byte mode) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(3); - mplew.writeShort(SendOpcode.CHECK_PINCODE.getValue()); - mplew.write(mode); - return mplew.getPacket(); - } - - public static byte[] pinRegistered() { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(3); - mplew.writeShort(SendOpcode.UPDATE_PINCODE.getValue()); - mplew.write(0); - return mplew.getPacket(); - } - - public static byte[] requestPin() { - return pinOperation((byte) 4); - } - - public static byte[] requestPinAfterFailure() { - return pinOperation((byte) 2); - } - - public static byte[] registerPin() { - return pinOperation((byte) 1); - } - - public static byte[] pinAccepted() { - return pinOperation((byte) 0); - } - - public static byte[] wrongPic() { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(3); - mplew.writeShort(SendOpcode.CHECK_SPW_RESULT.getValue()); - mplew.write(0); - return mplew.getPacket(); - } - - /** - * Gets a packet detailing a server and its channels. - * - * @param serverId - * @param serverName The name of the server. - * @param channelLoad Load of the channel - 1200 seems to be max. - * @return The server info packet. - */ - public static byte[] getServerList(int serverId, String serverName, int flag, String eventmsg, List channelLoad) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SERVERLIST.getValue()); - mplew.write(serverId); - mplew.writeMapleAsciiString(serverName); - mplew.write(flag); - mplew.writeMapleAsciiString(eventmsg); - mplew.write(100); // rate modifier, don't ask O.O! - mplew.write(0); // event xp * 2.6 O.O! - mplew.write(100); // rate modifier, don't ask O.O! - mplew.write(0); // drop rate * 2.6 - mplew.write(0); - mplew.write(channelLoad.size()); - for (Channel ch : channelLoad) { - mplew.writeMapleAsciiString(serverName + "-" + ch.getId()); - mplew.writeInt((ch.getConnectedClients() * 1200) / ServerConstants.CHANNEL_LOAD); - mplew.write(1); - mplew.writeShort(ch.getId() - 1); - } - mplew.writeShort(0); - return mplew.getPacket(); - } - - /** - * Gets a packet saying that the server list is over. - * - * @return The end of server list packet. - */ - public static byte[] getEndOfServerList() { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(3); - mplew.writeShort(SendOpcode.SERVERLIST.getValue()); - mplew.write(0xFF); - return mplew.getPacket(); - } - - /** - * Gets a packet detailing a server status message. - * - * Possible values for status:
0 - Normal
1 - Highly - * populated
2 - Full - * - * @param status The server status. - * @return The server status packet. - */ - public static byte[] getServerStatus(int status) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(4); - mplew.writeShort(SendOpcode.SERVERSTATUS.getValue()); - mplew.writeShort(status); - return mplew.getPacket(); - } - - /** - * Gets a packet telling the client the IP of the channel server. - * - * @param inetAddr The InetAddress of the requested channel server. - * @param port The port the channel is on. - * @param clientId The ID of the client. - * @return The server IP packet. - */ - public static byte[] getServerIP(InetAddress inetAddr, int port, int clientId) { - final 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.write(new byte[]{0, 0, 0, 0, 0}); - return mplew.getPacket(); - } - - /** - * Gets a packet telling the client the IP of the new channel. - * - * @param inetAddr The InetAddress of the requested channel server. - * @param port The port the channel is on. - * @return The server IP packet. - */ - public static byte[] getChannelChange(InetAddress inetAddr, int port) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.CHANGE_CHANNEL.getValue()); - mplew.write(1); - byte[] addr = inetAddr.getAddress(); - mplew.write(addr); - mplew.writeShort(port); - return mplew.getPacket(); - } - - /** - * Gets a packet with a list of characters. - * - * @param c The MapleClient to load characters of. - * @param serverId The ID of the server requested. - * @return The character list packet. - */ - public static byte[] getCharList(MapleClient c, int serverId) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.CHARLIST.getValue()); - mplew.write(0); - List chars = c.loadCharacters(serverId); - mplew.write((byte) chars.size()); - for (MapleCharacter chr : chars) { - addCharEntry(mplew, chr, false); - } - if (ServerConstants.ENABLE_PIC) { - mplew.write(c.getPic() == null || c.getPic().length() == 0 ? 0 : 1); - } else { - mplew.write(2); - } - - mplew.writeInt(c.getCharacterSlots()); - return mplew.getPacket(); - } - - public static byte[] enableTV() { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(7); - mplew.writeShort(SendOpcode.ENABLE_TV.getValue()); - mplew.writeInt(0); - mplew.write(0); - return mplew.getPacket(); - } - - /** - * Removes TV - * - * @return The Remove TV Packet - */ - public static byte[] removeTV() { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(2); - mplew.writeShort(SendOpcode.REMOVE_TV.getValue()); - return mplew.getPacket(); - } - - /** - * Sends MapleTV - * - * @param chr The character shown in TV - * @param messages The message sent with the TV - * @param type The type of TV - * @param partner The partner shown with chr - * @return the SEND_TV packet - */ - public static byte[] sendTV(MapleCharacter chr, List messages, int type, MapleCharacter partner) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SEND_TV.getValue()); - mplew.write(partner != null ? 3 : 1); - mplew.write(type); //Heart = 2 Star = 1 Normal = 0 - addCharLook(mplew, chr, false); - mplew.writeMapleAsciiString(chr.getName()); - if (partner != null) { - mplew.writeMapleAsciiString(partner.getName()); - } else { - mplew.writeShort(0); - } - for (int i = 0; i < messages.size(); i++) { - if (i == 4 && messages.get(4).length() > 15) { - mplew.writeMapleAsciiString(messages.get(4).substring(0, 15)); - } else { - mplew.writeMapleAsciiString(messages.get(i)); - } - } - mplew.writeInt(1337); // time limit shit lol 'Your thing still start in blah blah seconds' - if (partner != null) { - addCharLook(mplew, partner, false); - } - return mplew.getPacket(); - } - - /** - * Gets character info for a character. - * - * @param chr The character to get info about. - * @return The character info packet. - */ - public static byte[] getCharInfo(MapleCharacter chr) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SET_FIELD.getValue()); - mplew.writeInt(chr.getClient().getChannel() - 1); - mplew.write(1); - mplew.write(1); - mplew.writeShort(0); - for (int i = 0; i < 3; i++) { - mplew.writeInt(Randomizer.nextInt()); - } - addCharacterInfo(mplew, chr); - mplew.writeLong(getTime(System.currentTimeMillis())); - return mplew.getPacket(); - } - - /** - * Gets an empty stat update. - * - * @return The empy stat update packet. - */ - public static byte[] enableActions() { - return updatePlayerStats(EMPTY_STATUPDATE, true, null); - } - - /** - * Gets an update for specified stats. - * - * @param stats The stats to update. - * @return The stat update packet. - */ - public static byte[] updatePlayerStats(List> stats, MapleCharacter chr) { - return updatePlayerStats(stats, false, chr); - } - - /** - * Gets an update for specified stats. - * - * @param stats The list of stats to update. - * @param itemReaction Result of an item reaction(?) - * @return The stat update packet. - */ - public static byte[] updatePlayerStats(List> stats, boolean itemReaction, MapleCharacter chr) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.STAT_CHANGED.getValue()); - mplew.write(itemReaction ? 1 : 0); - int updateMask = 0; - for (Pair statupdate : stats) { - updateMask |= statupdate.getLeft().getValue(); - } - List> mystats = stats; - if (mystats.size() > 1) { - Collections.sort(mystats, new Comparator>() { - @Override - public int compare(Pair o1, Pair o2) { - int val1 = o1.getLeft().getValue(); - int val2 = o2.getLeft().getValue(); - return (val1 < val2 ? -1 : (val1 == val2 ? 0 : 1)); - } - }); - } - mplew.writeInt(updateMask); - for (Pair statupdate : mystats) { - if (statupdate.getLeft().getValue() >= 1) { - if (statupdate.getLeft().getValue() == 0x1) { - mplew.writeShort(statupdate.getRight().shortValue()); - } else if (statupdate.getLeft().getValue() <= 0x4) { - mplew.writeInt(statupdate.getRight()); - } else if (statupdate.getLeft().getValue() < 0x20) { - mplew.write(statupdate.getRight().shortValue()); - } else if (statupdate.getLeft().getValue() == 0x8000) { - if (GameConstants.hasSPTable(chr.getJob())) { - mplew.write(chr.getRemainingSpSize()); - for (int i = 0; i < chr.getRemainingSps().length; i++) { - if (chr.getRemainingSpBySkill(i) > 0) { - mplew.write(i + 1); - mplew.write(chr.getRemainingSpBySkill(i)); - } - } - } else { - mplew.writeShort(statupdate.getRight().shortValue()); - } - } else if (statupdate.getLeft().getValue() < 0xFFFF) { - mplew.writeShort(statupdate.getRight().shortValue()); - } else { - mplew.writeInt(statupdate.getRight().intValue()); - } - } - } - return mplew.getPacket(); - } - - /** - * Gets a packet telling the client to change maps. - * - * @param to The MapleMap to warp to. - * @param spawnPoint The spawn portal number to spawn at. - * @param chr The character warping to to - * @return The map change packet. - */ - public static byte[] getWarpToMap(MapleMap to, int spawnPoint, MapleCharacter chr) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SET_FIELD.getValue()); - mplew.writeInt(chr.getClient().getChannel() - 1); - mplew.writeInt(0);//updated - mplew.write(0);//updated - mplew.writeInt(to.getId()); - mplew.write(spawnPoint); - mplew.writeShort(chr.getHp()); - mplew.write(0); - mplew.writeLong(getTime(System.currentTimeMillis())); - return mplew.getPacket(); - } - - /** - * Gets a packet to spawn a portal. - * - * @param townId The ID of the town the portal goes to. - * @param targetId The ID of the target. - * @param pos Where to put the portal. - * @return The portal spawn packet. - */ - public static byte[] spawnPortal(int townId, int targetId, Point pos) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(14); - mplew.writeShort(SendOpcode.SPAWN_PORTAL.getValue()); - mplew.writeInt(townId); - mplew.writeInt(targetId); - if (pos != null) { - mplew.writePos(pos); - } - return mplew.getPacket(); - } - - /** - * Gets a packet to spawn a door. - * - * @param oid The door's object ID. - * @param pos The position of the door. - * @param town - * @return The remove door packet. - */ - public static byte[] spawnDoor(int oid, Point pos, boolean town) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(11); - mplew.writeShort(SendOpcode.SPAWN_DOOR.getValue()); - mplew.writeBool(town); - mplew.writeInt(oid); - mplew.writePos(pos); - return mplew.getPacket(); - } - - /** - * Gets a packet to remove a door. - * - * @param oid The door's ID. - * @param town - * @return The remove door packet. - */ - public static byte[] removeDoor(int oid, boolean town) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(10); - if (town) { - mplew.writeShort(SendOpcode.SPAWN_PORTAL.getValue()); - mplew.writeInt(999999999); - mplew.writeInt(999999999); - } else { - mplew.writeShort(SendOpcode.REMOVE_DOOR.getValue()); - mplew.write(0); - mplew.writeInt(oid); - } - return mplew.getPacket(); - } - - /** - * Gets a packet to spawn a special map object. - * - * @param summon - * @param skillLevel The level of the skill used. - * @param animated Animated spawn? - * @return The spawn packet for the map object. - */ - public static byte[] spawnSummon(MapleSummon summon, boolean animated) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(25); - mplew.writeShort(SendOpcode.SPAWN_SPECIAL_MAPOBJECT.getValue()); - mplew.writeInt(summon.getOwner().getId()); - mplew.writeInt(summon.getObjectId()); - mplew.writeInt(summon.getSkill()); - mplew.write(0x0A); //v83 - mplew.write(summon.getSkillLevel()); - mplew.writePos(summon.getPosition()); - mplew.skip(3); - mplew.write(summon.getMovementType().getValue()); // 0 = don't move, 1 = follow (4th mage summons?), 2/4 = only tele follow, 3 = bird follow - mplew.write(summon.isPuppet() ? 0 : 1); // 0 and the summon can't attack - but puppets don't attack with 1 either ^.- - mplew.write(animated ? 0 : 1); - return mplew.getPacket(); - } - - /** - * Gets a packet to remove a special map object. - * - * @param summon - * @param animated Animated removal? - * @return The packet removing the object. - */ - public static byte[] removeSummon(MapleSummon summon, boolean animated) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(11); - mplew.writeShort(SendOpcode.REMOVE_SPECIAL_MAPOBJECT.getValue()); - mplew.writeInt(summon.getOwner().getId()); - mplew.writeInt(summon.getObjectId()); - mplew.write(animated ? 4 : 1); // ? - return mplew.getPacket(); - } - - /** - * Gets the response to a relog request. - * - * @return The relog response packet. - */ - public static byte[] getRelogResponse() { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(3); - mplew.writeShort(SendOpcode.RELOG_RESPONSE.getValue()); - mplew.write(1);//1 O.O Must be more types ): - return mplew.getPacket(); - } - - /** - * Gets a server message packet. - * - * @param message The message to convey. - * @return The server message packet. - */ - public static byte[] serverMessage(String message) { - return serverMessage(4, (byte) 0, message, true, false, 0); - } - - /** - * Gets a server notice packet. - * - * Possible values for type:
0: [Notice]
1: Popup
- * 2: Megaphone
3: Super Megaphone
4: Scrolling message at top
- * 5: Pink Text
6: Lightblue Text - * - * @param type The type of the notice. - * @param message The message to convey. - * @return The server notice packet. - */ - public static byte[] serverNotice(int type, String message) { - return serverMessage(type, (byte) 0, message, false, false, 0); - } - - /** - * Gets a server notice packet. - * - * Possible values for type:
0: [Notice]
1: Popup
- * 2: Megaphone
3: Super Megaphone
4: Scrolling message at top
- * 5: Pink Text
6: Lightblue Text - * - * @param type The type of the notice. - * @param channel The channel this notice was sent on. - * @param message The message to convey. - * @return The server notice packet. - */ - public static byte[] serverNotice(int type, String message, int npc) { - return serverMessage(type, 0, message, false, false, npc); - } - - public static byte[] serverNotice(int type, int channel, String message) { - return serverMessage(type, channel, message, false, false, 0); - } - - public static byte[] serverNotice(int type, int channel, String message, boolean smegaEar) { - return serverMessage(type, channel, message, false, smegaEar, 0); - } - - /** - * Gets a server message packet. - * - * Possible values for type:
0: [Notice]
1: Popup
- * 2: Megaphone
3: Super Megaphone
4: Scrolling message at top
- * 5: Pink Text
6: Lightblue Text
7: BroadCasting NPC - * - * @param type The type of the notice. - * @param channel The channel this notice was sent on. - * @param message The message to convey. - * @param servermessage Is this a scrolling ticker? - * @return The server notice packet. - */ - private static byte[] serverMessage(int type, int channel, String message, boolean servermessage, boolean megaEar, int npc) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SERVERMESSAGE.getValue()); - mplew.write(type); - if (servermessage) { - mplew.write(1); - } - mplew.writeMapleAsciiString(message); - if (type == 3) { - mplew.write(channel - 1); // channel - mplew.writeBool(megaEar); - } else if (type == 6) { - mplew.writeInt(0); - } else if (type == 7) { // npc - mplew.writeInt(npc); - } - return mplew.getPacket(); - } - - /** - * Sends a Avatar Super Megaphone packet. - * - * @param chr The character name. - * @param medal The medal text. - * @param channel Which channel. - * @param itemId Which item used. - * @param message The message sent. - * @param ear Whether or not the ear is shown for whisper. - * @return - */ - public static byte[] getAvatarMega(MapleCharacter chr, String medal, int channel, int itemId, List message, boolean ear) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SET_AVATAR_MEGAPHONE.getValue()); - mplew.writeInt(itemId); - mplew.writeMapleAsciiString(medal + chr.getName()); - for (String s : message) { - mplew.writeMapleAsciiString(s); - } - mplew.writeInt(channel - 1); // channel - mplew.writeBool(ear); - addCharLook(mplew, chr, true); - return mplew.getPacket(); - } - - /* - * Sends a packet to remove the tiger megaphone - * @return - */ - public static byte[] byeAvatarMega() { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.CLEAR_AVATAR_MEGAPHONE.getValue()); - mplew.write(1); - return mplew.getPacket(); - } - - /** - * Sends the Gachapon green message when a user uses a gachapon ticket. - * - * @param item - * @param town - * @param player - * @return - */ - public static byte[] gachaponMessage(Item item, String town, MapleCharacter player) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SERVERMESSAGE.getValue()); - mplew.write(0x0B); - mplew.writeMapleAsciiString(player.getName() + " : got a(n)"); - mplew.writeInt(0); //random? - mplew.writeMapleAsciiString(town); - addItemInfo(mplew, item, true); - return mplew.getPacket(); - } - - public static byte[] spawnNPC(MapleNPC life) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(24); - mplew.writeShort(SendOpcode.SPAWN_NPC.getValue()); - mplew.writeInt(life.getObjectId()); - mplew.writeInt(life.getId()); - mplew.writeShort(life.getPosition().x); - mplew.writeShort(life.getCy()); - if (life.getF() == 1) { - mplew.write(0); - } else { - mplew.write(1); - } - mplew.writeShort(life.getFh()); - mplew.writeShort(life.getRx0()); - mplew.writeShort(life.getRx1()); - mplew.write(1); - return mplew.getPacket(); - } - - public static byte[] spawnNPCRequestController(MapleNPC life, boolean MiniMap) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(23); - mplew.writeShort(SendOpcode.SPAWN_NPC_REQUEST_CONTROLLER.getValue()); - mplew.write(1); - mplew.writeInt(life.getObjectId()); - mplew.writeInt(life.getId()); - mplew.writeShort(life.getPosition().x); - mplew.writeShort(life.getCy()); - if (life.getF() == 1) { - mplew.write(0); - } else { - mplew.write(1); - } - mplew.writeShort(life.getFh()); - mplew.writeShort(life.getRx0()); - mplew.writeShort(life.getRx1()); - mplew.writeBool(MiniMap); - return mplew.getPacket(); - } - - /** - * Gets a spawn monster packet. - * - * @param life The monster to spawn. - * @param newSpawn Is it a new spawn? - * @return The spawn monster packet. - */ - public static byte[] spawnMonster(MapleMonster life, boolean newSpawn) { - return spawnMonsterInternal(life, false, newSpawn, false, 0, false); - } - - /** - * Gets a spawn monster packet. - * - * @param life The monster to spawn. - * @param newSpawn Is it a new spawn? - * @return The spawn monster packet. - */ - public static byte[] spawnHPQMonster(MapleMonster life, boolean newSpawn) { - return spawnMonsterInternal(life, false, newSpawn, false, 0, false); - } - - /** - * Gets a spawn monster packet. - * - * @param life The monster to spawn. - * @param newSpawn Is it a new spawn? - * @param effect The spawn effect. - * @return The spawn monster packet. - */ - public static byte[] spawnMonster(MapleMonster life, boolean newSpawn, int effect) { - return spawnMonsterInternal(life, false, newSpawn, false, effect, false); - } - - /** - * Gets a control monster packet. - * - * @param life The monster to give control to. - * @param newSpawn Is it a new spawn? - * @param aggro Aggressive monster? - * @return The monster control packet. - */ - public static byte[] controlMonster(MapleMonster life, boolean newSpawn, boolean aggro) { - return spawnMonsterInternal(life, true, newSpawn, aggro, 0, false); - } - - /** - * Removes a monster invisibility. - * - * @param life - * @return - */ - public static byte[] removeMonsterInvisibility(MapleMonster life) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SPAWN_MONSTER_CONTROL.getValue()); - mplew.write(1); - mplew.writeInt(life.getObjectId()); - return mplew.getPacket(); - //return spawnMonsterInternal(life, true, false, false, 0, false); - } - - /** - * Makes a monster invisible for Ariant PQ. - * - * @param life - * @return - */ - public static byte[] makeMonsterInvisible(MapleMonster life) { - return spawnMonsterInternal(life, true, false, false, 0, true); - } - - /** - * Internal function to handler monster spawning and controlling. - * - * @param life The mob to perform operations with. - * @param requestController Requesting control of mob? - * @param newSpawn New spawn (fade in?) - * @param aggro Aggressive mob? - * @param effect The spawn effect to use. - * @return The spawn/control packet. - */ - private static byte[] spawnMonsterInternal(MapleMonster life, boolean requestController, boolean newSpawn, boolean aggro, int effect, boolean makeInvis) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - if (makeInvis) { - mplew.writeShort(SendOpcode.SPAWN_MONSTER_CONTROL.getValue()); - mplew.write(0); - mplew.writeInt(life.getObjectId()); - return mplew.getPacket(); - } - if (requestController) { - mplew.writeShort(SendOpcode.SPAWN_MONSTER_CONTROL.getValue()); - mplew.write(aggro ? 2 : 1); - } else { - mplew.writeShort(SendOpcode.SPAWN_MONSTER.getValue()); - } - mplew.writeInt(life.getObjectId()); - mplew.write(life.getController() == null ? 5 : 1); - mplew.writeInt(life.getId()); - mplew.skip(15); - mplew.write(0x88); - mplew.skip(6); - mplew.writePos(life.getPosition()); - mplew.write(life.getStance()); - mplew.writeShort(0); //Origin FH //life.getStartFh() - mplew.writeShort(life.getFh()); - - if (effect > 0) { - mplew.write(effect); - mplew.write(0); - mplew.writeShort(0); - if (effect == 15) { - mplew.write(0); - } - } - mplew.write(newSpawn ? -2 : -1); - mplew.write(life.getTeam()); - mplew.writeInt(0); - return mplew.getPacket(); - } - - /** - * Handles monsters not being targettable, such as Zakum's first body. - * - * @param life The mob to spawn as non-targettable. - * @param effect The effect to show when spawning. - * @return The packet to spawn the mob as non-targettable. - */ - public static byte[] spawnFakeMonster(MapleMonster life, int effect) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SPAWN_MONSTER_CONTROL.getValue()); - mplew.write(1); - mplew.writeInt(life.getObjectId()); - mplew.write(5); - mplew.writeInt(life.getId()); - mplew.skip(15); - mplew.write(0x88); - mplew.skip(6); - mplew.writePos(life.getPosition()); - mplew.write(life.getStance()); - mplew.writeShort(0);//life.getStartFh() - mplew.writeShort(life.getFh()); - if (effect > 0) { - mplew.write(effect); - mplew.write(0); - mplew.writeShort(0); - } - mplew.writeShort(-2); - mplew.write(life.getTeam()); - mplew.writeInt(0); - return mplew.getPacket(); - } - - /** - * Makes a monster previously spawned as non-targettable, targettable. - * - * @param life The mob to make targettable. - * @return The packet to make the mob targettable. - */ - public static byte[] makeMonsterReal(MapleMonster life) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SPAWN_MONSTER.getValue()); - mplew.writeInt(life.getObjectId()); - mplew.write(5); - mplew.writeInt(life.getId()); - mplew.skip(15); - mplew.write(0x88); - mplew.skip(6); - mplew.writePos(life.getPosition()); - mplew.write(life.getStance()); - mplew.writeShort(0);//life.getStartFh() - mplew.writeShort(life.getFh()); - mplew.writeShort(-1); - mplew.writeInt(0); - return mplew.getPacket(); - } - - /** - * Gets a stop control monster packet. - * - * @param oid The ObjectID of the monster to stop controlling. - * @return The stop control monster packet. - */ - public static byte[] stopControllingMonster(int oid) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(7); - mplew.writeShort(SendOpcode.SPAWN_MONSTER_CONTROL.getValue()); - mplew.write(0); - mplew.writeInt(oid); - return mplew.getPacket(); - } - - /** - * Gets a response to a move monster packet. - * - * @param objectid The ObjectID of the monster being moved. - * @param moveid The movement ID. - * @param currentMp The current MP of the monster. - * @param useSkills Can the monster use skills? - * @return The move response packet. - */ - public static byte[] moveMonsterResponse(int objectid, short moveid, int currentMp, boolean useSkills) { - return moveMonsterResponse(objectid, moveid, currentMp, useSkills, 0, 0); - } - - /** - * Gets a response to a move monster packet. - * - * @param objectid The ObjectID of the monster being moved. - * @param moveid The movement ID. - * @param currentMp The current MP of the monster. - * @param useSkills Can the monster use skills? - * @param skillId The skill ID for the monster to use. - * @param skillLevel The level of the skill to use. - * @return The move response packet. - */ - public static byte[] moveMonsterResponse(int objectid, short moveid, int currentMp, boolean useSkills, int skillId, int skillLevel) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(13); - mplew.writeShort(SendOpcode.MOVE_MONSTER_RESPONSE.getValue()); - mplew.writeInt(objectid); - mplew.writeShort(moveid); - mplew.writeBool(useSkills); - mplew.writeShort(currentMp); - mplew.write(skillId); - mplew.write(skillLevel); - return mplew.getPacket(); - } - - /** - * Gets a general chat packet. - * - * @param cidfrom The character ID who sent the chat. - * @param text The text of the chat. - * @param whiteBG - * @param show - * @return The general chat packet. - */ - public static byte[] getChatText(int cidfrom, String text, boolean gm, int show) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.CHATTEXT.getValue()); - mplew.writeInt(cidfrom); - mplew.writeBool(gm); - mplew.writeMapleAsciiString(text); - mplew.write(show); - return mplew.getPacket(); - } - - /** - * Gets a packet telling the client to show an EXP increase. - * - * @param gain The amount of EXP gained. - * @param inChat In the chat box? - * @param white White text or yellow? - * @return The exp gained packet. - */ - public static byte[] getShowExpGain(int gain, int equip, int party, boolean inChat, boolean white) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SHOW_STATUS_INFO.getValue()); - mplew.write(3); // 3 = exp, 4 = fame, 5 = mesos, 6 = guildpoints - mplew.writeBool(white); - mplew.writeInt(gain); - mplew.writeBool(inChat); - mplew.writeInt(0); // monster book bonus (Bonus Event Exp) - mplew.write(0); // third monster kill event - mplew.write(0); // RIP byte, this is always a 0 - mplew.writeInt(0); //wedding bonus - if (inChat) { // quest bonus rate stuff - mplew.write(0); - } - - int mod = ServerConstants.PARTY_EXPERIENCE_MOD != 1 ? ServerConstants.PARTY_EXPERIENCE_MOD * 100 : 0; - - mplew.write(mod); //0 = party bonus, 100 = 1x Bonus EXP, 200 = 2x Bonus EXP - mplew.writeInt(party); // party bonus - mplew.writeInt(equip); //equip bonus - mplew.writeInt(0); //Internet Cafe Bonus - mplew.writeInt(0); //Rainbow Week Bonus - return mplew.getPacket(); - } - - /** - * Gets a packet telling the client to show a fame gain. - * - * @param gain How many fame gained. - * @return The meso gain packet. - */ - public static byte[] getShowFameGain(int gain) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SHOW_STATUS_INFO.getValue()); - mplew.write(4); - mplew.writeInt(gain); - return mplew.getPacket(); - } - - /** - * Gets a packet telling the client to show a meso gain. - * - * @param gain How many mesos gained. - * @return The meso gain packet. - */ - public static byte[] getShowMesoGain(int gain) { - return getShowMesoGain(gain, false); - } - - /** - * Gets a packet telling the client to show a meso gain. - * - * @param gain How many mesos gained. - * @param inChat Show in the chat window? - * @return The meso gain packet. - */ - public static byte[] getShowMesoGain(int gain, boolean inChat) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SHOW_STATUS_INFO.getValue()); - if (!inChat) { - mplew.write(0); - mplew.writeShort(1); //v83 - } else { - mplew.write(5); - } - mplew.writeInt(gain); - mplew.writeShort(0); - return mplew.getPacket(); - } - - /** - * Gets a packet telling the client to show a item gain. - * - * @param itemId The ID of the item gained. - * @param quantity How many items gained. - * @return The item gain packet. - */ - public static byte[] getShowItemGain(int itemId, short quantity) { - return getShowItemGain(itemId, quantity, false); - } - - /** - * Gets a packet telling the client to show an item gain. - * - * @param itemId The ID of the item gained. - * @param quantity The number of items gained. - * @param inChat Show in the chat window? - * @return The item gain packet. - */ - public static byte[] getShowItemGain(int itemId, short quantity, boolean inChat) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - if (inChat) { - mplew.writeShort(SendOpcode.SHOW_ITEM_GAIN_INCHAT.getValue()); - mplew.write(3); - mplew.write(1); - mplew.writeInt(itemId); - mplew.writeInt(quantity); - } else { - mplew.writeShort(SendOpcode.SHOW_STATUS_INFO.getValue()); - mplew.writeShort(0); - mplew.writeInt(itemId); - mplew.writeInt(quantity); - mplew.writeInt(0); - mplew.writeInt(0); - } - return mplew.getPacket(); - } - - public static byte[] killMonster(int oid, boolean animation) { - return killMonster(oid, animation ? 1 : 0); - } - - /** - * Gets a packet telling the client that a monster was killed. - * - * @param oid The objectID of the killed monster. - * @param animation 0 = dissapear, 1 = fade out, 2+ = special - * @return The kill monster packet. - */ - public static byte[] killMonster(int oid, int animation) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.KILL_MONSTER.getValue()); - mplew.writeInt(oid); - mplew.write(animation); - mplew.write(animation); - return mplew.getPacket(); - } - - public static byte[] dropItemFromMapObject(MapleMapItem drop, Point dropfrom, Point dropto, byte mod) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.DROP_ITEM_FROM_MAPOBJECT.getValue()); - mplew.write(mod); - mplew.writeInt(drop.getObjectId()); - mplew.writeBool(drop.getMeso() > 0); // 1 mesos, 0 item, 2 and above all item meso bag, - mplew.writeInt(drop.getItemId()); // drop object ID - mplew.writeInt(drop.getOwner()); // owner charid/paryid :) - mplew.write(drop.getDropType()); // 0 = timeout for non-owner, 1 = timeout for non-owner's party, 2 = FFA, 3 = explosive/FFA - mplew.writePos(dropto); - mplew.writeInt(drop.getDropType() == 0 ? drop.getOwner() : 0); //test - - if (mod != 2) { - mplew.writePos(dropfrom); - mplew.writeShort(0);//Fh? - } - if (drop.getMeso() == 0) { - addExpirationTime(mplew, drop.getItem().getExpiration()); - } - mplew.write(drop.isPlayerDrop() ? 0 : 1); //pet EQP pickup - return mplew.getPacket(); - } - - /** - * Gets a packet spawning a player as a mapobject to other clients. - * - * @param chr The character to spawn to other clients. - * @return The spawn player packet. - */ - public static byte[] spawnPlayerMapobject(MapleCharacter chr) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SPAWN_PLAYER.getValue()); - mplew.writeInt(chr.getId()); - mplew.write(chr.getLevel()); //v83 - mplew.writeMapleAsciiString(chr.getName()); - if (chr.getGuildId() < 1) { - mplew.writeMapleAsciiString(""); - mplew.write(new byte[6]); - } else { - MapleGuildSummary gs = chr.getClient().getWorldServer().getGuildSummary(chr.getGuildId(), chr.getWorld()); - if (gs != null) { - mplew.writeMapleAsciiString(gs.getName()); - mplew.writeShort(gs.getLogoBG()); - mplew.write(gs.getLogoBGColor()); - mplew.writeShort(gs.getLogo()); - mplew.write(gs.getLogoColor()); - } else { - mplew.writeMapleAsciiString(""); - mplew.write(new byte[6]); - } - } - mplew.writeInt(0); - mplew.writeShort(0); //v83 - mplew.write(0xFC); - mplew.write(1); - if (chr.getBuffedValue(MapleBuffStat.MORPH) != null) { - mplew.writeInt(2); - } else { - mplew.writeInt(0); - } - long buffmask = 0; - Integer buffvalue = null; - if (chr.getBuffedValue(MapleBuffStat.DARKSIGHT) != null && !chr.isHidden()) { - buffmask |= MapleBuffStat.DARKSIGHT.getValue(); - } - if (chr.getBuffedValue(MapleBuffStat.COMBO) != null) { - buffmask |= MapleBuffStat.COMBO.getValue(); - buffvalue = Integer.valueOf(chr.getBuffedValue(MapleBuffStat.COMBO).intValue()); - } - if (chr.getBuffedValue(MapleBuffStat.SHADOWPARTNER) != null) { - buffmask |= MapleBuffStat.SHADOWPARTNER.getValue(); - } - if (chr.getBuffedValue(MapleBuffStat.SOULARROW) != null) { - buffmask |= MapleBuffStat.SOULARROW.getValue(); - } - if (chr.getBuffedValue(MapleBuffStat.MORPH) != null) { - buffvalue = Integer.valueOf(chr.getBuffedValue(MapleBuffStat.MORPH).intValue()); - } - if (chr.getBuffedValue(MapleBuffStat.ENERGY_CHARGE) != null) { - buffmask |= MapleBuffStat.ENERGY_CHARGE.getValue(); - buffvalue = Integer.valueOf(chr.getBuffedValue(MapleBuffStat.ENERGY_CHARGE).intValue()); - }//AREN'T THESE - mplew.writeInt((int) ((buffmask >> 32) & 0xffffffffL)); - if (buffvalue != null) { - if (chr.getBuffedValue(MapleBuffStat.MORPH) != null) { //TEST - mplew.writeShort(buffvalue); - } else { - mplew.write(buffvalue.byteValue()); - } - } - mplew.writeInt((int) (buffmask & 0xffffffffL)); - int CHAR_MAGIC_SPAWN = Randomizer.nextInt(); - mplew.skip(6); - mplew.writeInt(CHAR_MAGIC_SPAWN); - mplew.skip(11); - mplew.writeInt(CHAR_MAGIC_SPAWN);//v74 - mplew.skip(11); - mplew.writeInt(CHAR_MAGIC_SPAWN); - mplew.writeShort(0); - mplew.write(0); - final Item mount = chr.getInventory(MapleInventoryType.EQUIPPED).getItem((short) -18); - if (chr.getBuffedValue(MapleBuffStat.MONSTER_RIDING) != null && mount != null) { - mplew.writeInt(mount.getItemId()); - mplew.writeInt(1004); - } else { - mplew.writeLong(0); - } - mplew.writeInt(CHAR_MAGIC_SPAWN); - mplew.skip(9); - mplew.writeInt(CHAR_MAGIC_SPAWN); - mplew.writeShort(0); - mplew.writeInt(0); // actually not 0, why is it 0 then? - mplew.skip(10); - mplew.writeInt(CHAR_MAGIC_SPAWN); - mplew.skip(13); - mplew.writeInt(CHAR_MAGIC_SPAWN); - mplew.writeShort(0); - mplew.write(0); - mplew.writeShort(chr.getJob().getId()); - addCharLook(mplew, chr, false); - mplew.writeInt(chr.getInventory(MapleInventoryType.CASH).countById(5110000)); - mplew.writeInt(chr.getItemEffect()); - mplew.writeInt(ItemConstants.getInventoryType(chr.getChair()) == MapleInventoryType.SETUP ? chr.getChair() : 0); - mplew.writePos(chr.getPosition()); - mplew.write(chr.getStance()); - mplew.writeShort(0);//chr.getFh() - mplew.write(0); - MaplePet[] pet = chr.getPets(); - for (int i = 0; i < 3; i++) { - if (pet[i] != null) { - addPetInfo(mplew, pet[i], false); - } - } - mplew.write(0); //end of pets - if (chr.getMount() == null) { - mplew.writeInt(1); // mob level - mplew.writeLong(0); // mob exp + tiredness - } else { - mplew.writeInt(chr.getMount().getLevel()); - mplew.writeInt(chr.getMount().getExp()); - mplew.writeInt(chr.getMount().getTiredness()); - } - if (chr.getPlayerShop() != null && chr.getPlayerShop().isOwner(chr)) { - if (chr.getPlayerShop().hasFreeSlot()) { - addAnnounceBox(mplew, chr.getPlayerShop(), chr.getPlayerShop().getVisitors().length); - } else { - addAnnounceBox(mplew, chr.getPlayerShop(), 1); - } - } else if (chr.getMiniGame() != null && chr.getMiniGame().isOwner(chr)) { - if (chr.getMiniGame().hasFreeSlot()) { - addAnnounceBox(mplew, chr.getMiniGame(), 1, 0, 1, 0); - } else { - addAnnounceBox(mplew, chr.getMiniGame(), 1, 0, 2, 1); - } - } else { - mplew.write(0); - } - if (chr.getChalkboard() != null) { - mplew.write(1); - mplew.writeMapleAsciiString(chr.getChalkboard()); - } else { - mplew.write(0); - } - addRingLook(mplew, chr, true); - addRingLook(mplew, chr, false); - addMarriageRingLook(mplew, chr); - mplew.skip(3); - mplew.write(chr.getTeam());//only needed in specific fields - return mplew.getPacket(); - } - - private static void addRingLook(final MaplePacketLittleEndianWriter mplew, MapleCharacter chr, boolean crush) { - List rings; - if (crush) { - rings = chr.getCrushRings(); - } else { - rings = chr.getFriendshipRings(); - } - boolean yes = false; - for (MapleRing ring : rings) { - if (ring.equipped()) { - if (yes == false) { - yes = true; - mplew.write(1); - } - mplew.writeInt(ring.getRingId()); - mplew.writeInt(0); - mplew.writeInt(ring.getPartnerRingId()); - mplew.writeInt(0); - mplew.writeInt(ring.getItemId()); - } - } - if (yes == false) { - mplew.write(0); - } - } - - private static void addMarriageRingLook(final MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { - if (chr.getMarriageRing() != null && !chr.getMarriageRing().equipped()) { - mplew.write(0); - return; - } - mplew.writeBool(chr.getMarriageRing() != null); - if (chr.getMarriageRing() != null) { - mplew.writeInt(chr.getId()); - mplew.writeInt(chr.getMarriageRing().getPartnerChrId()); - mplew.writeInt(chr.getMarriageRing().getRingId()); - } - } - - /** - * Adds a announcement box to an existing MaplePacketLittleEndianWriter. - * - * @param mplew The MaplePacketLittleEndianWriter to add an announcement box - * to. - * @param shop The shop to announce. - */ - private static void addAnnounceBox(final MaplePacketLittleEndianWriter mplew, MaplePlayerShop shop, int availability) { - mplew.write(4); - mplew.writeInt(shop.getObjectId()); - mplew.writeMapleAsciiString(shop.getDescription()); - mplew.write(0); - mplew.write(0); - mplew.write(1); - mplew.write(availability); - mplew.write(0); - } - - private static void addAnnounceBox(final MaplePacketLittleEndianWriter mplew, MapleMiniGame game, int gametype, int type, int ammount, int joinable) { - mplew.write(gametype); - mplew.writeInt(game.getObjectId()); // gameid/shopid - mplew.writeMapleAsciiString(game.getDescription()); // desc - mplew.write(0); - mplew.write(type); - mplew.write(ammount); - mplew.write(2); - mplew.write(joinable); - } - - public static byte[] facialExpression(MapleCharacter from, int expression) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(10); - mplew.writeShort(SendOpcode.FACIAL_EXPRESSION.getValue()); - mplew.writeInt(from.getId()); - mplew.writeInt(expression); - return mplew.getPacket(); - } - - private static void serializeMovementList(LittleEndianWriter lew, List moves) { - lew.write(moves.size()); - for (LifeMovementFragment move : moves) { - move.serialize(lew); - } - } - - public static byte[] movePlayer(int cid, List moves) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.MOVE_PLAYER.getValue()); - mplew.writeInt(cid); - mplew.writeInt(0); - serializeMovementList(mplew, moves); - return mplew.getPacket(); - } - - public static byte[] moveSummon(int cid, int oid, Point startPos, List moves) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.MOVE_SUMMON.getValue()); - mplew.writeInt(cid); - mplew.writeInt(oid); - mplew.writePos(startPos); - serializeMovementList(mplew, moves); - return mplew.getPacket(); - } - - public static byte[] moveMonster(int useskill, int skill, int skill_1, int skill_2, int skill_3, int skill_4, int oid, Point startPos, List moves) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.MOVE_MONSTER.getValue()); - mplew.writeInt(oid); - mplew.write(0); - mplew.write(useskill); - mplew.write(skill); - mplew.write(skill_1); - mplew.write(skill_2); - mplew.write(skill_3); - mplew.write(skill_4); - mplew.writePos(startPos); - serializeMovementList(mplew, moves); - return mplew.getPacket(); - } - - public static byte[] summonAttack(int cid, int summonSkillId, byte direction, List allDamage) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - //b2 00 29 f7 00 00 9a a3 04 00 c8 04 01 94 a3 04 00 06 ff 2b 00 - mplew.writeShort(SendOpcode.SUMMON_ATTACK.getValue()); - mplew.writeInt(cid); - mplew.writeInt(summonSkillId); - mplew.write(direction); - mplew.write(4); - mplew.write(allDamage.size()); - for (SummonAttackEntry attackEntry : allDamage) { - mplew.writeInt(attackEntry.getMonsterOid()); // oid - mplew.write(6); // who knows - mplew.writeInt(attackEntry.getDamage()); // damage - } - return mplew.getPacket(); - } - - public static byte[] closeRangeAttack(MapleCharacter chr, int skill, int skilllevel, int stance, int numAttackedAndDamage, Map> damage, int speed, int direction, int display) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.CLOSE_RANGE_ATTACK.getValue()); - addAttackBody(mplew, chr, skill, skilllevel, stance, numAttackedAndDamage, 0, damage, speed, direction, display); - return mplew.getPacket(); - } - - public static byte[] rangedAttack(MapleCharacter chr, int skill, int skilllevel, int stance, int numAttackedAndDamage, int projectile, Map> damage, int speed, int direction, int display) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.RANGED_ATTACK.getValue()); - addAttackBody(mplew, chr, skill, skilllevel, stance, numAttackedAndDamage, projectile, damage, speed, direction, display); - mplew.writeInt(0); - return mplew.getPacket(); - } - - public static byte[] magicAttack(MapleCharacter chr, int skill, int skilllevel, int stance, int numAttackedAndDamage, Map> damage, int charge, int speed, int direction, int display) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.MAGIC_ATTACK.getValue()); - addAttackBody(mplew, chr, skill, skilllevel, stance, numAttackedAndDamage, 0, damage, speed, direction, display); - if (charge != -1) { - mplew.writeInt(charge); - } - return mplew.getPacket(); - } - - private static void addAttackBody(LittleEndianWriter lew, MapleCharacter chr, int skill, int skilllevel, int stance, int numAttackedAndDamage, int projectile, Map> damage, int speed, int direction, int display) { - lew.writeInt(chr.getId()); - lew.write(numAttackedAndDamage); - lew.write(0x5B);//? - lew.write(skilllevel); - if (skilllevel > 0) { - lew.writeInt(skill); - } - lew.write(display); - lew.write(direction); - lew.write(stance); - lew.write(speed); - lew.write(0x0A); - lew.writeInt(projectile); - for (Integer oned : damage.keySet()) { - List onedList = damage.get(oned); - if (onedList != null) { - lew.writeInt(oned.intValue()); - lew.write(0xFF); - if (skill == 4211006) { - lew.write(onedList.size()); - } - for (Integer eachd : onedList) { - lew.writeInt(eachd.intValue()); - } - } - } - } - - private static int doubleToShortBits(double d) { - return (int) (Double.doubleToLongBits(d) >> 48); - } - - public static byte[] getNPCShop(MapleClient c, int sid, List items) { - MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance(); - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.OPEN_NPC_SHOP.getValue()); - mplew.writeInt(sid); - mplew.writeShort(items.size()); // item count - for (MapleShopItem item : items) { - mplew.writeInt(item.getItemId()); - mplew.writeInt(item.getPrice()); - mplew.writeInt(item.getPrice() == 0 ? item.getPitch() : 0); //Perfect Pitch - mplew.writeInt(0); //Can be used x minutes after purchase - mplew.writeInt(0); //Hmm - if (!ItemConstants.isRechargable(item.getItemId())) { - mplew.writeShort(1); // stacksize o.o - mplew.writeShort(item.getBuyable()); - } else { - mplew.writeShort(0); - mplew.writeInt(0); - mplew.writeShort(doubleToShortBits(ii.getPrice(item.getItemId()))); - mplew.writeShort(ii.getSlotMax(c, item.getItemId())); - } - } - return mplew.getPacket(); - } - - /* 00 = / - * 01 = You don't have enough in stock - * 02 = You do not have enough mesos - * 03 = Please check if your inventory is full or not - * 05 = You don't have enough in stock - * 06 = Due to an error, the trade did not happen - * 07 = Due to an error, the trade did not happen - * 08 = / - * 0D = You need more items - * 0E = CRASH; LENGTH NEEDS TO BE LONGER :O - */ - public static byte[] shopTransaction(byte code) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(3); - mplew.writeShort(SendOpcode.CONFIRM_SHOP_TRANSACTION.getValue()); - mplew.write(code); - return mplew.getPacket(); - } - - public static byte[] updateInventorySlotLimit(int type, int newLimit) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.INVENTORY_GROW.getValue()); - mplew.write(type); - mplew.write(newLimit); - return mplew.getPacket(); - } - - public static byte[] modifyInventory(boolean updateTick, final List mods) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.INVENTORY_OPERATION.getValue()); - mplew.writeBool(updateTick); - mplew.write(mods.size()); - //mplew.write(0); v104 :) - int addMovement = -1; - for (ModifyInventory mod : mods) { - mplew.write(mod.getMode()); - mplew.write(mod.getInventoryType()); - mplew.writeShort(mod.getMode() == 2 ? mod.getOldPosition() : mod.getPosition()); - switch (mod.getMode()) { - case 0: {//add item - addItemInfo(mplew, mod.getItem(), true); - break; - } - case 1: {//update quantity - mplew.writeShort(mod.getQuantity()); - break; - } - case 2: {//move - mplew.writeShort(mod.getPosition()); - if (mod.getPosition() < 0 || mod.getOldPosition() < 0) { - addMovement = mod.getOldPosition() < 0 ? 1 : 2; - } - break; - } - case 3: {//remove - if (mod.getPosition() < 0) { - addMovement = 2; - } - break; - } - } - mod.clear(); - } - if (addMovement > -1) { - mplew.write(addMovement); - } - return mplew.getPacket(); - } - - public static byte[] getScrollEffect(int chr, ScrollResult scrollSuccess, boolean legendarySpirit) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SHOW_SCROLL_EFFECT.getValue()); - mplew.writeInt(chr); - switch (scrollSuccess) { - case SUCCESS: - mplew.writeShort(1); - mplew.writeShort(legendarySpirit ? 1 : 0); - break; - case FAIL: - mplew.writeShort(0); - mplew.writeShort(legendarySpirit ? 1 : 0); - break; - case CURSE: - mplew.write(0); - mplew.write(1); - mplew.writeShort(legendarySpirit ? 1 : 0); - break; - } - return mplew.getPacket(); - } - - public static byte[] removePlayerFromMap(int cid) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.REMOVE_PLAYER_FROM_MAP.getValue()); - mplew.writeInt(cid); - return mplew.getPacket(); - } - - /** - * animation: 0 - expire
1 - without animation
2 - pickup
4 - - * explode
cid is ignored for 0 and 1 - * - * @param oid - * @param animation - * @param cid - * @return - */ - public static byte[] removeItemFromMap(int oid, int animation, int cid) { - return removeItemFromMap(oid, animation, cid, false, 0); - } - - /** - * animation: 0 - expire
1 - without animation
2 - pickup
4 - - * explode
cid is ignored for 0 and 1.

Flagging pet as true - * will make a pet pick up the item. - * - * @param oid - * @param animation - * @param cid - * @param pet - * @param slot - * @return - */ - public static byte[] removeItemFromMap(int oid, int animation, int cid, boolean pet, int slot) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.REMOVE_ITEM_FROM_MAP.getValue()); - mplew.write(animation); // expire - mplew.writeInt(oid); - if (animation >= 2) { - mplew.writeInt(cid); - if (pet) { - mplew.write(slot); - } - } - return mplew.getPacket(); - } - - public static byte[] updateCharLook(MapleCharacter chr) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.UPDATE_CHAR_LOOK.getValue()); - mplew.writeInt(chr.getId()); - mplew.write(1); - addCharLook(mplew, chr, false); - addRingLook(mplew, chr, true); - addRingLook(mplew, chr, false); - addMarriageRingLook(mplew, chr); - mplew.writeInt(0); - return mplew.getPacket(); - } - - public static byte[] damagePlayer(int skill, int monsteridfrom, int cid, int damage, int fake, int direction, boolean pgmr, int pgmr_1, boolean is_pg, int oid, int pos_x, int pos_y) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.DAMAGE_PLAYER.getValue()); - mplew.writeInt(cid); - mplew.write(skill); - mplew.writeInt(damage); - mplew.writeInt(monsteridfrom); - mplew.write(direction); - if (pgmr) { - mplew.write(pgmr_1); - mplew.write(is_pg ? 1 : 0); - mplew.writeInt(oid); - mplew.write(6); - mplew.writeShort(pos_x); - mplew.writeShort(pos_y); - mplew.write(0); - } else { - mplew.writeShort(0); - } - mplew.writeInt(damage); - if (fake > 0) { - mplew.writeInt(fake); - } - return mplew.getPacket(); - } - - public static byte[] charNameResponse(String charname, boolean nameUsed) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.CHAR_NAME_RESPONSE.getValue()); - mplew.writeMapleAsciiString(charname); - mplew.write(nameUsed ? 1 : 0); - return mplew.getPacket(); - } - - public static byte[] addNewCharEntry(MapleCharacter chr) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.ADD_NEW_CHAR_ENTRY.getValue()); - mplew.write(0); - addCharEntry(mplew, chr, false); - return mplew.getPacket(); - } - - /** - * state 0 = del ok state 12 = invalid bday state 14 = incorrect pic - * - * @param cid - * @param state - * @return - */ - public static byte[] deleteCharResponse(int cid, int state) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.DELETE_CHAR_RESPONSE.getValue()); - mplew.writeInt(cid); - mplew.write(state); - return mplew.getPacket(); - } - - public static byte[] selectWorld(int world) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.LAST_CONNECTED_WORLD.getValue()); - mplew.writeInt(world);//According to GMS, it should be the world that contains the most characters (most active) - return mplew.getPacket(); - } - - public static byte[] sendRecommended(List> worlds) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.RECOMMENDED_WORLD_MESSAGE.getValue()); - mplew.write(worlds.size());//size - for (Iterator> it = worlds.iterator(); it.hasNext();) { - Pair world = it.next(); - mplew.writeInt(world.getLeft()); - mplew.writeMapleAsciiString(world.getRight()); - } - return mplew.getPacket(); - } - - /** - * - * @param chr - * @param isSelf - * @return - */ - public static byte[] charInfo(MapleCharacter chr) { - //3D 00 0A 43 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.CHAR_INFO.getValue()); - mplew.writeInt(chr.getId()); - mplew.write(chr.getLevel()); - mplew.writeShort(chr.getJob().getId()); - mplew.writeShort(chr.getFame()); - mplew.write(chr.getMarriageRing() != null ? 1 : 0); - String guildName = ""; - String allianceName = ""; - MapleGuildSummary gs = chr.getClient().getWorldServer().getGuildSummary(chr.getGuildId(), chr.getWorld()); - if (chr.getGuildId() > 0 && gs != null) { - guildName = gs.getName(); - MapleAlliance alliance = Server.getInstance().getAlliance(gs.getAllianceId()); - if (alliance != null) { - allianceName = alliance.getName(); - } - } - mplew.writeMapleAsciiString(guildName); - mplew.writeMapleAsciiString(allianceName); - mplew.write(0); - MaplePet[] pets = chr.getPets(); - Item inv = chr.getInventory(MapleInventoryType.EQUIPPED).getItem((short) -114); - for (int i = 0; i < 3; i++) { - if (pets[i] != null) { - mplew.write(pets[i].getUniqueId()); - mplew.writeInt(pets[i].getItemId()); // petid - mplew.writeMapleAsciiString(pets[i].getName()); - mplew.write(pets[i].getLevel()); // pet level - mplew.writeShort(pets[i].getCloseness()); // pet closeness - mplew.write(pets[i].getFullness()); // pet fullness - mplew.writeShort(0); - mplew.writeInt(inv != null ? inv.getItemId() : 0); - } - } - mplew.write(0); //end of pets - if (chr.getMount() != null && chr.getInventory(MapleInventoryType.EQUIPPED).getItem((short) -18) != null) { - mplew.write(chr.getMount().getId()); //mount - mplew.writeInt(chr.getMount().getLevel()); //level - mplew.writeInt(chr.getMount().getExp()); //exp - mplew.writeInt(chr.getMount().getTiredness()); //tiredness - } else { - mplew.write(0); - } - mplew.write(chr.getCashShop().getWishList().size()); - for (int sn : chr.getCashShop().getWishList()) { - mplew.writeInt(sn); - } - mplew.writeInt(chr.getMonsterBook().getBookLevel()); - mplew.writeInt(chr.getMonsterBook().getNormalCard()); - mplew.writeInt(chr.getMonsterBook().getSpecialCard()); - mplew.writeInt(chr.getMonsterBook().getTotalCards()); - mplew.writeInt(chr.getMonsterBookCover() > 0 ? MapleItemInformationProvider.getInstance().getCardMobId(chr.getMonsterBookCover()) : 0); - Item medal = chr.getInventory(MapleInventoryType.EQUIPPED).getItem((short) -49); - if (medal != null) { - mplew.writeInt(medal.getItemId()); - } else { - mplew.writeInt(0); - } - ArrayList medalQuests = new ArrayList<>(); - List completed = chr.getCompletedQuests(); - for (MapleQuestStatus q : completed) { - if (q.getQuest().getId() >= 29000) { // && q.getQuest().getId() <= 29923 - medalQuests.add(q.getQuest().getId()); - } - } - - Collections.sort(medalQuests); - mplew.writeShort(medalQuests.size()); - for (Short s : medalQuests) { - mplew.writeShort(s); - } - return mplew.getPacket(); - } - - /** - * It is important that statups is in the correct order (see decleration - * order in MapleBuffStat) since this method doesn't do automagical - * reordering. - * - * @param buffid - * @param bufflength - * @param statups - * @return - */ - //1F 00 00 00 00 00 03 00 00 40 00 00 00 E0 00 00 00 00 00 00 00 00 E0 01 8E AA 4F 00 00 C2 EB 0B E0 01 8E AA 4F 00 00 C2 EB 0B 0C 00 8E AA 4F 00 00 C2 EB 0B 44 02 8E AA 4F 00 00 C2 EB 0B 44 02 8E AA 4F 00 00 C2 EB 0B 00 00 E0 7A 1D 00 8E AA 4F 00 00 00 00 00 00 00 00 03 - public static byte[] giveBuff(int buffid, int bufflength, List> statups) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.GIVE_BUFF.getValue()); - boolean special = false; - writeLongMask(mplew, statups); - for (Pair statup : statups) { - if (statup.getLeft().equals(MapleBuffStat.MONSTER_RIDING) || statup.getLeft().equals(MapleBuffStat.HOMING_BEACON)) { - special = true; - } - mplew.writeShort(statup.getRight().shortValue()); - mplew.writeInt(buffid); - mplew.writeInt(bufflength); - } - mplew.writeInt(0); - mplew.write(0); - mplew.writeInt(statups.get(0).getRight()); //Homing beacon ... - - if (special) { - mplew.skip(3); - } - return mplew.getPacket(); - } - - /** - * - * @param cid - * @param statups - * @param mount - * @return - */ - public static byte[] showMonsterRiding(int cid, MapleMount mount) { //Gtfo with this, this is just giveForeignBuff - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.GIVE_FOREIGN_BUFF.getValue()); - mplew.writeInt(cid); - mplew.writeLong(MapleBuffStat.MONSTER_RIDING.getValue()); //Thanks? - mplew.writeLong(0); - mplew.writeShort(0); - mplew.writeInt(mount.getItemId()); - mplew.writeInt(mount.getSkillId()); - mplew.writeInt(0); //Server Tick value. - mplew.writeShort(0); - mplew.write(0); //Times you have been buffed - return mplew.getPacket(); - } - /* mplew.writeInt(cid); - writeLongMask(mplew, statups); - for (Pair statup : statups) { - if (morph) { - mplew.writeInt(statup.getRight().intValue()); - } else { - mplew.writeShort(statup.getRight().shortValue()); - } - } - mplew.writeShort(0); - mplew.write(0);*/ - - /** - * - * @param c - * @param quest - * @return - */ - public static byte[] forfeitQuest(short quest) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SHOW_STATUS_INFO.getValue()); - mplew.write(1); - mplew.writeShort(quest); - mplew.write(0); - return mplew.getPacket(); - } - - /** - * - * @param c - * @param quest - * @return - */ - public static byte[] completeQuest(short quest, long time) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SHOW_STATUS_INFO.getValue()); - mplew.write(1); - mplew.writeShort(quest); - mplew.write(2); - mplew.writeLong(time); - return mplew.getPacket(); - } - - /** - * - * @param c - * @param quest - * @param npc - * @param progress - * @return - */ - public static byte[] updateQuestInfo(short quest, int npc) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.UPDATE_QUEST_INFO.getValue()); - mplew.write(8); //0x0A in v95 - mplew.writeShort(quest); - mplew.writeInt(npc); - mplew.writeInt(0); - return mplew.getPacket(); - } - - public static byte[] addQuestTimeLimit(final short quest, final int time) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.UPDATE_QUEST_INFO.getValue()); - mplew.write(6); - mplew.writeShort(1);//Size but meh, when will there be 2 at the same time? And it won't even replace the old one :) - mplew.writeShort(quest); - mplew.writeInt(time); - return mplew.getPacket(); - } - - public static byte[] removeQuestTimeLimit(final short quest) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.UPDATE_QUEST_INFO.getValue()); - mplew.write(7); - mplew.writeShort(1);//Position - mplew.writeShort(quest); - return mplew.getPacket(); - } - - public static byte[] updateQuest(MapleQuestStatus q, boolean infoUpdate) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SHOW_STATUS_INFO.getValue()); - mplew.write(1); - mplew.writeShort(infoUpdate ? q.getQuest().getInfoNumber() : q.getQuest().getId()); - if (infoUpdate) { - mplew.write(1); - } else { - mplew.write(q.getStatus().getId()); - } - - mplew.writeMapleAsciiString(q.getQuestData()); - return mplew.getPacket(); - } - - private static void writeLongMaskD(final MaplePacketLittleEndianWriter mplew, List> statups) { - long firstmask = 0; - long secondmask = 0; - for (Pair statup : statups) { - if (statup.getLeft().isFirst()) { - firstmask |= statup.getLeft().getValue(); - } else { - secondmask |= statup.getLeft().getValue(); - } - } - mplew.writeLong(firstmask); - mplew.writeLong(secondmask); - } - - public static byte[] giveDebuff(List> statups, MobSkill skill) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.GIVE_BUFF.getValue()); - writeLongMaskD(mplew, statups); - for (Pair statup : statups) { - mplew.writeShort(statup.getRight().shortValue()); - mplew.writeShort(skill.getSkillId()); - mplew.writeShort(skill.getSkillLevel()); - mplew.writeInt((int) skill.getDuration()); - } - mplew.writeShort(0); // ??? wk charges have 600 here o.o - mplew.writeShort(900);//Delay - mplew.write(1); - return mplew.getPacket(); - } - - public static byte[] giveForeignDebuff(int cid, List> statups, MobSkill skill) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.GIVE_FOREIGN_BUFF.getValue()); - mplew.writeInt(cid); - writeLongMaskD(mplew, statups); - for (int i = 0; i < statups.size(); i++) { - mplew.writeShort(skill.getSkillId()); - mplew.writeShort(skill.getSkillLevel()); - } - mplew.writeShort(0); // same as give_buff - mplew.writeShort(900);//Delay - return mplew.getPacket(); - } - - public static byte[] cancelForeignDebuff(int cid, long mask) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.CANCEL_FOREIGN_BUFF.getValue()); - mplew.writeInt(cid); - mplew.writeLong(0); - mplew.writeLong(mask); - return mplew.getPacket(); - } - - public static byte[] giveForeignBuff(int cid, List> statups) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.GIVE_FOREIGN_BUFF.getValue()); - mplew.writeInt(cid); - writeLongMask(mplew, statups); - for (Pair statup : statups) { - mplew.writeShort(statup.getRight().shortValue()); - } - mplew.writeInt(0); - mplew.writeShort(0); - return mplew.getPacket(); - } - - public static byte[] cancelForeignBuff(int cid, List statups) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.CANCEL_FOREIGN_BUFF.getValue()); - mplew.writeInt(cid); - writeLongMaskFromList(mplew, statups); - return mplew.getPacket(); - } - - public static byte[] cancelBuff(List statups) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.CANCEL_BUFF.getValue()); - writeLongMaskFromList(mplew, statups); - mplew.write(1);//? - return mplew.getPacket(); - } - - private static void writeLongMask(final MaplePacketLittleEndianWriter mplew, List> statups) { - long firstmask = 0; - long secondmask = 0; - for (Pair statup : statups) { - if (statup.getLeft().isFirst()) { - firstmask |= statup.getLeft().getValue(); - } else { - secondmask |= statup.getLeft().getValue(); - } - } - mplew.writeLong(firstmask); - mplew.writeLong(secondmask); - } - - private static void writeLongMaskFromList(final MaplePacketLittleEndianWriter mplew, List statups) { - long firstmask = 0; - long secondmask = 0; - for (MapleBuffStat statup : statups) { - if (statup.isFirst()) { - firstmask |= statup.getValue(); - } else { - secondmask |= statup.getValue(); - } - } - mplew.writeLong(firstmask); - mplew.writeLong(secondmask); - } - - public static byte[] cancelDebuff(long mask) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(19); - mplew.writeShort(SendOpcode.CANCEL_BUFF.getValue()); - mplew.writeLong(0); - mplew.writeLong(mask); - mplew.write(0); - return mplew.getPacket(); - } - - public static byte[] getPlayerShopChat(MapleCharacter c, String chat, boolean owner) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); - mplew.write(PlayerInteractionHandler.Action.CHAT.getCode()); - mplew.write(PlayerInteractionHandler.Action.CHAT_THING.getCode()); - mplew.write(owner ? 0 : 1); - mplew.writeMapleAsciiString(c.getName() + " : " + chat); - return mplew.getPacket(); - } - - public static byte[] getPlayerShopNewVisitor(MapleCharacter c, int slot) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); - mplew.write(PlayerInteractionHandler.Action.VISIT.getCode()); - mplew.write(slot); - addCharLook(mplew, c, false); - mplew.writeMapleAsciiString(c.getName()); - return mplew.getPacket(); - } - - public static byte[] getPlayerShopRemoveVisitor(int slot) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(4); - mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); - mplew.write(PlayerInteractionHandler.Action.EXIT.getCode()); - if (slot > 0) { - mplew.write(slot); - } - return mplew.getPacket(); - } - - public static byte[] getTradePartnerAdd(MapleCharacter c) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); - mplew.write(PlayerInteractionHandler.Action.VISIT.getCode()); - mplew.write(1); - addCharLook(mplew, c, false); - mplew.writeMapleAsciiString(c.getName()); - return mplew.getPacket(); - } - - public static byte[] getTradeInvite(MapleCharacter c) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); - mplew.write(PlayerInteractionHandler.Action.INVITE.getCode()); - mplew.write(3); - mplew.writeMapleAsciiString(c.getName()); - mplew.write(new byte[]{(byte) 0xB7, (byte) 0x50, 0, 0}); - return mplew.getPacket(); - } - - public static byte[] getTradeMesoSet(byte number, int meso) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(8); - mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); - mplew.write(PlayerInteractionHandler.Action.SET_MESO.getCode()); - mplew.write(number); - mplew.writeInt(meso); - return mplew.getPacket(); - } - - public static byte[] getTradeItemAdd(byte number, Item item) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); - mplew.write(PlayerInteractionHandler.Action.SET_ITEMS.getCode()); - mplew.write(number); - mplew.write(item.getPosition()); - addItemInfo(mplew, item, true); - return mplew.getPacket(); - } - - public static byte[] getPlayerShopItemUpdate(MaplePlayerShop shop) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); - mplew.write(PlayerInteractionHandler.Action.UPDATE_MERCHANT.getCode()); - mplew.write(shop.getItems().size()); - for (MaplePlayerShopItem item : shop.getItems()) { - mplew.writeShort(item.getBundles()); - mplew.writeShort(item.getItem().getQuantity()); - mplew.writeInt(item.getPrice()); - addItemInfo(mplew, item.getItem(), true); - } - return mplew.getPacket(); - } - - /** - * - * @param c - * @param shop - * @param owner - * @return - */ - public static byte[] getPlayerShop(MapleClient c, MaplePlayerShop shop, boolean owner) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); - mplew.write(PlayerInteractionHandler.Action.ROOM.getCode()); - mplew.write(4); - mplew.write(4); - mplew.write(owner ? 0 : 1); - mplew.write(0); - addCharLook(mplew, shop.getOwner(), false); - mplew.writeMapleAsciiString(shop.getOwner().getName()); - mplew.write(1); - addCharLook(mplew, shop.getOwner(), false); - mplew.writeMapleAsciiString(shop.getOwner().getName()); - mplew.write(0xFF); - mplew.writeMapleAsciiString(shop.getDescription()); - List items = shop.getItems(); - mplew.write(0x10); - mplew.write(items.size()); - for (MaplePlayerShopItem item : items) { - mplew.writeShort(item.getBundles()); - mplew.writeShort(item.getItem().getQuantity()); - mplew.writeInt(item.getPrice()); - addItemInfo(mplew, item.getItem(), true); - } - return mplew.getPacket(); - } - - public static byte[] getTradeStart(MapleClient c, MapleTrade trade, byte number) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); - mplew.write(PlayerInteractionHandler.Action.ROOM.getCode()); - mplew.write(3); - mplew.write(2); - mplew.write(number); - if (number == 1) { - mplew.write(0); - addCharLook(mplew, trade.getPartner().getChr(), false); - mplew.writeMapleAsciiString(trade.getPartner().getChr().getName()); - } - mplew.write(number); - addCharLook(mplew, c.getPlayer(), false); - mplew.writeMapleAsciiString(c.getPlayer().getName()); - mplew.write(0xFF); - return mplew.getPacket(); - } - - public static byte[] getTradeConfirmation() { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(3); - mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); - mplew.write(PlayerInteractionHandler.Action.CONFIRM.getCode()); - return mplew.getPacket(); - } - - public static byte[] getTradeCompletion(byte number) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(5); - mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); - mplew.write(PlayerInteractionHandler.Action.EXIT.getCode()); - mplew.write(number); - mplew.write(6); - return mplew.getPacket(); - } - - public static byte[] getTradeCancel(byte number) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(5); - mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); - mplew.write(PlayerInteractionHandler.Action.EXIT.getCode()); - mplew.write(number); - mplew.write(2); - return mplew.getPacket(); - } - - public static byte[] addCharBox(MapleCharacter c, int type) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.UPDATE_CHAR_BOX.getValue()); - mplew.writeInt(c.getId()); - addAnnounceBox(mplew, c.getPlayerShop(), type); - return mplew.getPacket(); - } - - public static byte[] removeCharBox(MapleCharacter c) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(7); - mplew.writeShort(SendOpcode.UPDATE_CHAR_BOX.getValue()); - mplew.writeInt(c.getId()); - mplew.write(0); - return mplew.getPacket(); - } - - /** - * Possible values for speaker:
0: Npc talking (left)
- * 1: Npc talking (right)
2: Player talking (left)
3: Player talking - * (left)
- * - * @param npc Npcid - * @param msgType - * @param talk - * @param endBytes - * @param speaker - * @return - */ - public static byte[] getNPCTalk(int npc, byte msgType, String talk, String endBytes, byte speaker) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.NPC_TALK.getValue()); - mplew.write(4); // ? - mplew.writeInt(npc); - mplew.write(msgType); - mplew.write(speaker); - mplew.writeMapleAsciiString(talk); - mplew.write(HexTool.getByteArrayFromHexString(endBytes)); - return mplew.getPacket(); - } - - public static byte[] getDimensionalMirror(String talk) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.NPC_TALK.getValue()); - mplew.write(4); // ? - mplew.writeInt(9010022); - mplew.write(0x0E); - mplew.write(0); - mplew.writeInt(0); - mplew.writeMapleAsciiString(talk); - return mplew.getPacket(); - } - - public static byte[] getNPCTalkStyle(int npc, String talk, int styles[]) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.NPC_TALK.getValue()); - mplew.write(4); // ? - mplew.writeInt(npc); - mplew.write(7); - mplew.write(0); //speaker - mplew.writeMapleAsciiString(talk); - mplew.write(styles.length); - for (int i = 0; i < styles.length; i++) { - mplew.writeInt(styles[i]); - } - return mplew.getPacket(); - } - - public static byte[] getNPCTalkNum(int npc, String talk, int def, int min, int max) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.NPC_TALK.getValue()); - mplew.write(4); // ? - mplew.writeInt(npc); - mplew.write(3); - mplew.write(0); //speaker - mplew.writeMapleAsciiString(talk); - mplew.writeInt(def); - mplew.writeInt(min); - mplew.writeInt(max); - mplew.writeInt(0); - return mplew.getPacket(); - } - - public static byte[] getNPCTalkText(int npc, String talk, String def) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.NPC_TALK.getValue()); - mplew.write(4); // Doesn't matter - mplew.writeInt(npc); - mplew.write(2); - mplew.write(0); //speaker - mplew.writeMapleAsciiString(talk); - mplew.writeMapleAsciiString(def);//:D - mplew.writeInt(0); - return mplew.getPacket(); - } - - public static byte[] showBuffeffect(int cid, int skillid, int effectid) { - return showBuffeffect(cid, skillid, effectid, (byte) 3); - } - - public static byte[] showBuffeffect(int cid, int skillid, int effectid, byte direction) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SHOW_FOREIGN_EFFECT.getValue()); - mplew.writeInt(cid); - mplew.write(effectid); //buff level - mplew.writeInt(skillid); - mplew.write(direction); - mplew.write(1); - mplew.writeLong(0); - return mplew.getPacket(); - } - - public static byte[] showOwnBuffEffect(int skillid, int effectid) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SHOW_ITEM_GAIN_INCHAT.getValue()); - mplew.write(effectid); - mplew.writeInt(skillid); - mplew.write(0xA9); - mplew.write(1); - return mplew.getPacket(); - } - - public static byte[] showOwnBerserk(int skilllevel, boolean Berserk) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SHOW_ITEM_GAIN_INCHAT.getValue()); - mplew.write(1); - mplew.writeInt(1320006); - mplew.write(0xA9); - mplew.write(skilllevel); - mplew.write(Berserk ? 1 : 0); - return mplew.getPacket(); - } - - public static byte[] showBerserk(int cid, int skilllevel, boolean Berserk) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SHOW_FOREIGN_EFFECT.getValue()); - mplew.writeInt(cid); - mplew.write(1); - mplew.writeInt(1320006); - mplew.write(0xA9); - mplew.write(skilllevel); - mplew.write(Berserk ? 1 : 0); - return mplew.getPacket(); - } - - public static byte[] updateSkill(int skillid, int level, int masterlevel, long expiration) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.UPDATE_SKILLS.getValue()); - mplew.write(1); - mplew.writeShort(1); - mplew.writeInt(skillid); - mplew.writeInt(level); - mplew.writeInt(masterlevel); - addExpirationTime(mplew, expiration); - mplew.write(4); - return mplew.getPacket(); - } - - public static byte[] getShowQuestCompletion(int id) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.QUEST_CLEAR.getValue()); - mplew.writeShort(id); - return mplew.getPacket(); - } - - public static byte[] getKeymap(Map keybindings) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.KEYMAP.getValue()); - mplew.write(0); - for (int x = 0; x < 90; x++) { - MapleKeyBinding binding = keybindings.get(Integer.valueOf(x)); - if (binding != null) { - mplew.write(binding.getType()); - mplew.writeInt(binding.getAction()); - } else { - mplew.write(0); - mplew.writeInt(0); - } - } - return mplew.getPacket(); - } - - public static byte[] getWhisper(String sender, int channel, String text) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.WHISPER.getValue()); - mplew.write(0x12); - mplew.writeMapleAsciiString(sender); - mplew.writeShort(channel - 1); // I guess this is the channel - mplew.writeMapleAsciiString(text); - return mplew.getPacket(); - } - - /** - * - * @param target name of the target character - * @param reply error code: 0x0 = cannot find char, 0x1 = success - * @return the MaplePacket - */ - public static byte[] getWhisperReply(String target, byte reply) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.WHISPER.getValue()); - mplew.write(0x0A); // whisper? - mplew.writeMapleAsciiString(target); - mplew.write(reply); - return mplew.getPacket(); - } - - public static byte[] getInventoryFull() { - return modifyInventory(true, Collections.emptyList()); - } - - public static byte[] getShowInventoryFull() { - return getShowInventoryStatus(0xff); - } - - public static byte[] showItemUnavailable() { - return getShowInventoryStatus(0xfe); - } - - public static byte[] getShowInventoryStatus(int mode) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SHOW_STATUS_INFO.getValue()); - mplew.write(0); - mplew.write(mode); - mplew.writeInt(0); - mplew.writeInt(0); - return mplew.getPacket(); - } - - public static byte[] getStorage(int npcId, byte slots, Collection items, int meso) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.STORAGE.getValue()); - mplew.write(0x16); - mplew.writeInt(npcId); - mplew.write(slots); - mplew.writeShort(0x7E); - mplew.writeShort(0); - mplew.writeInt(0); - mplew.writeInt(meso); - mplew.writeShort(0); - mplew.write((byte) items.size()); - for (Item item : items) { - addItemInfo(mplew, item, true); - } - mplew.writeShort(0); - mplew.write(0); - return mplew.getPacket(); - } - - /* - * 0x0A = Inv full - * 0x0B = You do not have enough mesos - * 0x0C = One-Of-A-Kind error - */ - public static byte[] getStorageError(byte i) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.STORAGE.getValue()); - mplew.write(i); - return mplew.getPacket(); - } - - public static byte[] mesoStorage(byte slots, int meso) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.STORAGE.getValue()); - mplew.write(0x13); - mplew.write(slots); - mplew.writeShort(2); - mplew.writeShort(0); - mplew.writeInt(0); - mplew.writeInt(meso); - return mplew.getPacket(); - } - - public static byte[] storeStorage(byte slots, MapleInventoryType type, Collection items) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.STORAGE.getValue()); - mplew.write(0xD); - mplew.write(slots); - mplew.writeShort(type.getBitfieldEncoding()); - mplew.writeShort(0); - mplew.writeInt(0); - mplew.write(items.size()); - for (Item item : items) { - addItemInfo(mplew, item, true); - } - return mplew.getPacket(); - } - - public static byte[] takeOutStorage(byte slots, MapleInventoryType type, Collection items) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.STORAGE.getValue()); - mplew.write(0x9); - mplew.write(slots); - mplew.writeShort(type.getBitfieldEncoding()); - mplew.writeShort(0); - mplew.writeInt(0); - mplew.write(items.size()); - for (Item item : items) { - addItemInfo(mplew, item, true); - } - return mplew.getPacket(); - } - - /** - * - * @param oid - * @param remhppercentage - * @return - */ - public static byte[] showMonsterHP(int oid, int remhppercentage) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SHOW_MONSTER_HP.getValue()); - mplew.writeInt(oid); - mplew.write(remhppercentage); - return mplew.getPacket(); - } - - public static byte[] showBossHP(int oid, int currHP, int maxHP, byte tagColor, byte tagBgColor) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.FIELD_EFFECT.getValue()); - mplew.write(5); - mplew.writeInt(oid); - mplew.writeInt(currHP); - mplew.writeInt(maxHP); - mplew.write(tagColor); - mplew.write(tagBgColor); - return mplew.getPacket(); - } - - public static byte[] giveFameResponse(int mode, String charname, int newfame) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.FAME_RESPONSE.getValue()); - mplew.write(0); - mplew.writeMapleAsciiString(charname); - mplew.write(mode); - mplew.writeShort(newfame); - mplew.writeShort(0); - return mplew.getPacket(); - } - - /** - * status can be:
0: ok, use giveFameResponse
1: the username is - * incorrectly entered
2: users under level 15 are unable to toggle with - * fame.
3: can't raise or drop fame anymore today.
4: can't raise - * or drop fame for this character for this month anymore.
5: received - * fame, use receiveFame()
6: level of fame neither has been raised nor - * dropped due to an unexpected error - * - * @param status - * @return - */ - public static byte[] giveFameErrorResponse(int status) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.FAME_RESPONSE.getValue()); - mplew.write(status); - return mplew.getPacket(); - } - - public static byte[] receiveFame(int mode, String charnameFrom) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.FAME_RESPONSE.getValue()); - mplew.write(5); - mplew.writeMapleAsciiString(charnameFrom); - mplew.write(mode); - return mplew.getPacket(); - } - - public static byte[] partyCreated(MaplePartyCharacter partychar) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.PARTY_OPERATION.getValue()); - mplew.write(8); - mplew.writeShort(0x8b); - mplew.writeShort(1); - if (partychar.getDoors().size() > 0) { - for (MapleDoor doors : partychar.getDoors()) { - mplew.writeInt(doors.getTown().getId()); - mplew.writeInt(doors.getTarget().getId()); - mplew.writeInt(doors.getPosition().x); - mplew.writeInt(doors.getPosition().y); - } - } else { - mplew.writeInt(999999999); - mplew.writeInt(999999999); - mplew.writeInt(0); - mplew.writeInt(0); - } - return mplew.getPacket(); - } - - public static byte[] partyInvite(MapleCharacter from) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.PARTY_OPERATION.getValue()); - mplew.write(4); - mplew.writeInt(from.getParty().getId()); - mplew.writeMapleAsciiString(from.getName()); - mplew.write(0); - return mplew.getPacket(); - } - - /** - * 10: A beginner can't create a party. 1/11/14/19: Your request for a party - * didn't work due to an unexpected error. 13: You have yet to join a party. - * 16: Already have joined a party. 17: The party you're trying to join is - * already in full capacity. 19: Unable to find the requested character in - * this channel. - * - * @param message - * @return - */ - public static byte[] partyStatusMessage(int message) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.PARTY_OPERATION.getValue()); - mplew.write(message); - return mplew.getPacket(); - } - - /** - * 23: 'Char' have denied request to the party. - * - * @param message - * @param charname - * @return - */ - public static byte[] partyStatusMessage(int message, String charname) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.PARTY_OPERATION.getValue()); - mplew.write(message); - mplew.writeMapleAsciiString(charname); - return mplew.getPacket(); - } - - private static void addPartyStatus(int forchannel, MapleParty party, LittleEndianWriter lew, boolean leaving) { - List partymembers = new ArrayList<>(party.getMembers()); - while (partymembers.size() < 6) { - partymembers.add(new MaplePartyCharacter()); - } - for (MaplePartyCharacter partychar : partymembers) { - lew.writeInt(partychar.getId()); - } - for (MaplePartyCharacter partychar : partymembers) { - lew.writeAsciiString(getRightPaddedStr(partychar.getName(), '\0', 13)); - } - for (MaplePartyCharacter partychar : partymembers) { - lew.writeInt(partychar.getJobId()); - } - for (MaplePartyCharacter partychar : partymembers) { - lew.writeInt(partychar.getLevel()); - } - for (MaplePartyCharacter partychar : partymembers) { - if (partychar.isOnline()) { - lew.writeInt(partychar.getChannel() - 1); - } else { - lew.writeInt(-2); - } - } - lew.writeInt(party.getLeader().getId()); - for (MaplePartyCharacter partychar : partymembers) { - if (partychar.getChannel() == forchannel) { - lew.writeInt(partychar.getMapId()); - } else { - lew.writeInt(0); - } - } - for (MaplePartyCharacter partychar : partymembers) { - if (partychar.getChannel() == forchannel && !leaving) { - if (partychar.getDoors().size() > 0) { - for (MapleDoor doors : partychar.getDoors()) { - lew.writeInt(doors.getTown().getId()); - lew.writeInt(doors.getTarget().getId()); - lew.writeInt(doors.getPosition().x); - lew.writeInt(doors.getPosition().y); - } - } else { - lew.writeInt(999999999); - lew.writeInt(999999999); - lew.writeInt(0); - lew.writeInt(0); - } - } else { - lew.writeInt(999999999); - lew.writeInt(999999999); - lew.writeInt(0); - lew.writeInt(0); - } - } - } - - public static byte[] updateParty(int forChannel, MapleParty party, PartyOperation op, MaplePartyCharacter target) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.PARTY_OPERATION.getValue()); - switch (op) { - case DISBAND: - case EXPEL: - case LEAVE: - mplew.write(0x0C); - mplew.writeInt(40546); - mplew.writeInt(target.getId()); - if (op == PartyOperation.DISBAND) { - mplew.write(0); - mplew.writeInt(party.getId()); - } else { - mplew.write(1); - if (op == PartyOperation.EXPEL) { - mplew.write(1); - } else { - mplew.write(0); - } - mplew.writeMapleAsciiString(target.getName()); - addPartyStatus(forChannel, party, mplew, false); - } - break; - case JOIN: - mplew.write(0xF); - mplew.writeInt(40546); - mplew.writeMapleAsciiString(target.getName()); - addPartyStatus(forChannel, party, mplew, false); - break; - case SILENT_UPDATE: - case LOG_ONOFF: - mplew.write(0x7); - mplew.writeInt(party.getId()); - addPartyStatus(forChannel, party, mplew, false); - break; - case CHANGE_LEADER: - mplew.write(0x1B); - mplew.writeInt(target.getId()); - mplew.write(0); - break; - } - return mplew.getPacket(); - } - - public static byte[] partyPortal(int townId, int targetId, Point position) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.PARTY_OPERATION.getValue()); - mplew.writeShort(0x23); - mplew.writeInt(townId); - mplew.writeInt(targetId); - mplew.writePos(position); - return mplew.getPacket(); - } - - public static byte[] updatePartyMemberHP(int cid, int curhp, int maxhp) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.UPDATE_PARTYMEMBER_HP.getValue()); - mplew.writeInt(cid); - mplew.writeInt(curhp); - mplew.writeInt(maxhp); - return mplew.getPacket(); - } - - /** - * mode: 0 buddychat; 1 partychat; 2 guildchat - * - * @param name - * @param chattext - * @param mode - * @return - */ - public static byte[] multiChat(String name, String chattext, int mode) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.MULTICHAT.getValue()); - mplew.write(mode); - mplew.writeMapleAsciiString(name); - mplew.writeMapleAsciiString(chattext); - return mplew.getPacket(); - } - - private static void writeIntMask(final MaplePacketLittleEndianWriter mplew, Map stats) { - int firstmask = 0; - int secondmask = 0; - for (MonsterStatus stat : stats.keySet()) { - if (stat.isFirst()) { - firstmask |= stat.getValue(); - } else { - secondmask |= stat.getValue(); - } - } - mplew.writeInt(firstmask); - mplew.writeInt(secondmask); - } - - public static byte[] applyMonsterStatus(final int oid, final MonsterStatusEffect mse, final List reflection) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.APPLY_MONSTER_STATUS.getValue()); - mplew.writeInt(oid); - mplew.writeLong(0); - writeIntMask(mplew, mse.getStati()); - for (Map.Entry stat : mse.getStati().entrySet()) { - mplew.writeShort(stat.getValue()); - if (mse.isMonsterSkill()) { - mplew.writeShort(mse.getMobSkill().getSkillId()); - mplew.writeShort(mse.getMobSkill().getSkillLevel()); - } else { - mplew.writeInt(mse.getSkill().getId()); - } - mplew.writeShort(-1); // might actually be the buffTime but it's not displayed anywhere - } - int size = mse.getStati().size(); // size - if (reflection != null) { - for (Integer ref : reflection) { - mplew.writeInt(ref); - } - if (reflection.size() > 0) { - size /= 2; // This gives 2 buffs per reflection but it's really one buff - } - } - mplew.write(size); // size - mplew.writeInt(0); - return mplew.getPacket(); - } - - public static byte[] cancelMonsterStatus(int oid, Map stats) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.CANCEL_MONSTER_STATUS.getValue()); - mplew.writeInt(oid); - mplew.writeLong(0); - writeIntMask(mplew, stats); - mplew.writeInt(0); - return mplew.getPacket(); - } - - public static byte[] getClock(int time) { // time in seconds - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.CLOCK.getValue()); - mplew.write(2); // clock type. if you send 3 here you have to send another byte (which does not matter at all) before the timestamp - mplew.writeInt(time); - return mplew.getPacket(); - } - - public static byte[] getClockTime(int hour, int min, int sec) { // Current Time - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.CLOCK.getValue()); - mplew.write(1); //Clock-Type - mplew.write(hour); - mplew.write(min); - mplew.write(sec); - return mplew.getPacket(); - } - - public static byte[] removeClock() { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.STOP_CLOCK.getValue()); - mplew.write(0); - return mplew.getPacket(); - } - - public static byte[] spawnMist(int oid, int ownerCid, int skill, int level, MapleMist mist) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SPAWN_MIST.getValue()); - mplew.writeInt(oid); - mplew.writeInt(mist.isMobMist() ? 0 : mist.isPoisonMist() ? 1 : mist.isRecoveryMist() ? 4 : 2); // mob mist = 0, player poison = 1, smokescreen = 2, unknown = 3, recovery = 4 - mplew.writeInt(ownerCid); - mplew.writeInt(skill); - mplew.write(level); - mplew.writeShort(mist.getSkillDelay()); // Skill delay - mplew.writeInt(mist.getBox().x); - mplew.writeInt(mist.getBox().y); - mplew.writeInt(mist.getBox().x + mist.getBox().width); - mplew.writeInt(mist.getBox().y + mist.getBox().height); - mplew.writeInt(0); - return mplew.getPacket(); - } - - public static byte[] removeMist(int oid) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.REMOVE_MIST.getValue()); - mplew.writeInt(oid); - return mplew.getPacket(); - } - - public static byte[] damageSummon(int cid, int summonSkillId, int damage, int unkByte, int monsterIdFrom) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.DAMAGE_SUMMON.getValue()); - mplew.writeInt(cid); - mplew.writeInt(summonSkillId); - mplew.write(unkByte); - mplew.writeInt(damage); - mplew.writeInt(monsterIdFrom); - mplew.write(0); - return mplew.getPacket(); - } - - public static byte[] damageMonster(int oid, int damage) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.DAMAGE_MONSTER.getValue()); - mplew.writeInt(oid); - mplew.write(0); - mplew.writeInt(damage); - mplew.write(0); - mplew.write(0); - mplew.write(0); - return mplew.getPacket(); - } - - public static byte[] healMonster(int oid, int heal) { - return damageMonster(oid, -heal); - } - - public static byte[] updateBuddylist(Collection buddylist) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.BUDDYLIST.getValue()); - mplew.write(7); - mplew.write(buddylist.size()); - for (BuddylistEntry buddy : buddylist) { - if (buddy.isVisible()) { - mplew.writeInt(buddy.getCharacterId()); // cid - mplew.writeAsciiString(getRightPaddedStr(buddy.getName(), '\0', 13)); - mplew.write(0); // opposite status - mplew.writeInt(buddy.getChannel() - 1); - mplew.writeAsciiString(getRightPaddedStr(buddy.getGroup(), '\0', 13)); - mplew.writeInt(0);//mapid? - } - } - for (int x = 0; x < buddylist.size(); x++) { - mplew.writeInt(0);//mapid? - } - return mplew.getPacket(); - } - - public static byte[] buddylistMessage(byte message) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.BUDDYLIST.getValue()); - mplew.write(message); - return mplew.getPacket(); - } - - public static byte[] requestBuddylistAdd(int cidFrom, int cid, String nameFrom) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.BUDDYLIST.getValue()); - mplew.write(9); - mplew.writeInt(cidFrom); - mplew.writeMapleAsciiString(nameFrom); - mplew.writeInt(cidFrom); - mplew.writeAsciiString(getRightPaddedStr(nameFrom, '\0', 11)); - mplew.write(0x09); - mplew.write(0xf0); - mplew.write(0x01); - mplew.writeInt(0x0f); - mplew.writeNullTerminatedAsciiString("Default Group"); - mplew.writeInt(cid); - return mplew.getPacket(); - } - - public static byte[] updateBuddyChannel(int characterid, int channel) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.BUDDYLIST.getValue()); - mplew.write(0x14); - mplew.writeInt(characterid); - mplew.write(0); - mplew.writeInt(channel); - return mplew.getPacket(); - } - - public static byte[] itemEffect(int characterid, int itemid) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SHOW_ITEM_EFFECT.getValue()); - mplew.writeInt(characterid); - mplew.writeInt(itemid); - return mplew.getPacket(); - } - - public static byte[] updateBuddyCapacity(int capacity) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.BUDDYLIST.getValue()); - mplew.write(0x15); - mplew.write(capacity); - return mplew.getPacket(); - } - - public static byte[] showChair(int characterid, int itemid) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SHOW_CHAIR.getValue()); - mplew.writeInt(characterid); - mplew.writeInt(itemid); - return mplew.getPacket(); - } - - public static byte[] cancelChair(int id) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.CANCEL_CHAIR.getValue()); - if (id == -1) { - mplew.write(0); - } else { - mplew.write(1); - mplew.writeShort(id); - } - return mplew.getPacket(); - } - - // is there a way to spawn reactors non-animated? - public static byte[] spawnReactor(MapleReactor reactor) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - Point pos = reactor.getPosition(); - mplew.writeShort(SendOpcode.REACTOR_SPAWN.getValue()); - mplew.writeInt(reactor.getObjectId()); - mplew.writeInt(reactor.getId()); - mplew.write(reactor.getState()); - mplew.writePos(pos); - mplew.writeShort(0); - mplew.write(0); - return mplew.getPacket(); - } - - public static byte[] triggerReactor(MapleReactor reactor, int stance) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - Point pos = reactor.getPosition(); - mplew.writeShort(SendOpcode.REACTOR_HIT.getValue()); - mplew.writeInt(reactor.getObjectId()); - mplew.write(reactor.getState()); - mplew.writePos(pos); - mplew.writeShort(stance); - mplew.write(0); - mplew.write(5); // frame delay, set to 5 since there doesn't appear to be a fixed formula for it - return mplew.getPacket(); - } - - public static byte[] destroyReactor(MapleReactor reactor) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - Point pos = reactor.getPosition(); - mplew.writeShort(SendOpcode.REACTOR_DESTROY.getValue()); - mplew.writeInt(reactor.getObjectId()); - mplew.write(reactor.getState()); - mplew.writePos(pos); - return mplew.getPacket(); - } - - public static byte[] musicChange(String song) { - return environmentChange(song, 6); - } - - public static byte[] showEffect(String effect) { - return environmentChange(effect, 3); - } - - public static byte[] playSound(String sound) { - return environmentChange(sound, 4); - } - - public static byte[] environmentChange(String env, int mode) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.FIELD_EFFECT.getValue()); - mplew.write(mode); - mplew.writeMapleAsciiString(env); - return mplew.getPacket(); - } - - public static byte[] startMapEffect(String msg, int itemid, boolean active) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.BLOW_WEATHER.getValue()); - mplew.write(active ? 0 : 1); - mplew.writeInt(itemid); - if (active) { - mplew.writeMapleAsciiString(msg); - } - return mplew.getPacket(); - } - - public static byte[] removeMapEffect() { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.BLOW_WEATHER.getValue()); - mplew.write(0); - mplew.writeInt(0); - return mplew.getPacket(); - } - - public static byte[] mapEffect(String path) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.FIELD_EFFECT.getValue()); - mplew.write(3); - mplew.writeMapleAsciiString(path); - return mplew.getPacket(); - } - - public static byte[] mapSound(String path) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.FIELD_EFFECT.getValue()); - mplew.write(4); - mplew.writeMapleAsciiString(path); - return mplew.getPacket(); - } - - public static byte[] showGuildInfo(MapleCharacter c) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.GUILD_OPERATION.getValue()); - mplew.write(0x1A); //signature for showing guild info - if (c == null) { //show empty guild (used for leaving, expelled) - mplew.write(0); - return mplew.getPacket(); - } - MapleGuild g = c.getClient().getWorldServer().getGuild(c.getMGC()); - if (g == null) { //failed to read from DB - don't show a guild - mplew.write(0); - return mplew.getPacket(); - } else { - c.setGuildRank(c.getGuildRank()); - } - mplew.write(1); //bInGuild - mplew.writeInt(g.getId()); - mplew.writeMapleAsciiString(g.getName()); - for (int i = 1; i <= 5; i++) { - mplew.writeMapleAsciiString(g.getRankTitle(i)); - } - Collection members = g.getMembers(); - mplew.write(members.size()); //then it is the size of all the members - for (MapleGuildCharacter mgc : members) {//and each of their character ids o_O - mplew.writeInt(mgc.getId()); - } - for (MapleGuildCharacter mgc : members) { - mplew.writeAsciiString(getRightPaddedStr(mgc.getName(), '\0', 13)); - mplew.writeInt(mgc.getJobId()); - mplew.writeInt(mgc.getLevel()); - mplew.writeInt(mgc.getGuildRank()); - mplew.writeInt(mgc.isOnline() ? 1 : 0); - mplew.writeInt(g.getSignature()); - mplew.writeInt(mgc.getAllianceRank()); - } - mplew.writeInt(g.getCapacity()); - mplew.writeShort(g.getLogoBG()); - mplew.write(g.getLogoBGColor()); - mplew.writeShort(g.getLogo()); - mplew.write(g.getLogoColor()); - mplew.writeMapleAsciiString(g.getNotice()); - mplew.writeInt(g.getGP()); - mplew.writeInt(g.getAllianceId()); - return mplew.getPacket(); - } - - public static byte[] guildMemberOnline(int gid, int cid, boolean bOnline) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.GUILD_OPERATION.getValue()); - mplew.write(0x3d); - mplew.writeInt(gid); - mplew.writeInt(cid); - mplew.write(bOnline ? 1 : 0); - return mplew.getPacket(); - } - - public static byte[] guildInvite(int gid, String charName) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.GUILD_OPERATION.getValue()); - mplew.write(0x05); - mplew.writeInt(gid); - mplew.writeMapleAsciiString(charName); - return mplew.getPacket(); - } - - /** - * 'Char' has denied your guild invitation. - * - * @param charname - * @return - */ - public static byte[] denyGuildInvitation(String charname) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.GUILD_OPERATION.getValue()); - mplew.write(0x37); - mplew.writeMapleAsciiString(charname); - return mplew.getPacket(); - } - - public static byte[] genericGuildMessage(byte code) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.GUILD_OPERATION.getValue()); - mplew.write(code); - return mplew.getPacket(); - } - - public static byte[] newGuildMember(MapleGuildCharacter mgc) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.GUILD_OPERATION.getValue()); - mplew.write(0x27); - mplew.writeInt(mgc.getGuildId()); - mplew.writeInt(mgc.getId()); - mplew.writeAsciiString(getRightPaddedStr(mgc.getName(), '\0', 13)); - mplew.writeInt(mgc.getJobId()); - mplew.writeInt(mgc.getLevel()); - mplew.writeInt(mgc.getGuildRank()); //should be always 5 but whatevs - mplew.writeInt(mgc.isOnline() ? 1 : 0); //should always be 1 too - mplew.writeInt(1); //? could be guild signature, but doesn't seem to matter - mplew.writeInt(3); - return mplew.getPacket(); - } - - //someone leaving, mode == 0x2c for leaving, 0x2f for expelled - public static byte[] memberLeft(MapleGuildCharacter mgc, boolean bExpelled) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.GUILD_OPERATION.getValue()); - mplew.write(bExpelled ? 0x2f : 0x2c); - mplew.writeInt(mgc.getGuildId()); - mplew.writeInt(mgc.getId()); - mplew.writeMapleAsciiString(mgc.getName()); - return mplew.getPacket(); - } - - //rank change - public static byte[] changeRank(MapleGuildCharacter mgc) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.GUILD_OPERATION.getValue()); - mplew.write(0x40); - mplew.writeInt(mgc.getGuildId()); - mplew.writeInt(mgc.getId()); - mplew.write(mgc.getGuildRank()); - return mplew.getPacket(); - } - - public static byte[] guildNotice(int gid, String notice) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.GUILD_OPERATION.getValue()); - mplew.write(0x44); - mplew.writeInt(gid); - mplew.writeMapleAsciiString(notice); - return mplew.getPacket(); - } - - public static byte[] guildMemberLevelJobUpdate(MapleGuildCharacter mgc) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.GUILD_OPERATION.getValue()); - mplew.write(0x3C); - mplew.writeInt(mgc.getGuildId()); - mplew.writeInt(mgc.getId()); - mplew.writeInt(mgc.getLevel()); - mplew.writeInt(mgc.getJobId()); - return mplew.getPacket(); - } - - public static byte[] rankTitleChange(int gid, String[] ranks) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.GUILD_OPERATION.getValue()); - mplew.write(0x3E); - mplew.writeInt(gid); - for (int i = 0; i < 5; i++) { - mplew.writeMapleAsciiString(ranks[i]); - } - return mplew.getPacket(); - } - - public static byte[] guildDisband(int gid) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.GUILD_OPERATION.getValue()); - mplew.write(0x32); - mplew.writeInt(gid); - mplew.write(1); - return mplew.getPacket(); - } - - public static byte[] guildQuestWaitingNotice(byte channel, int waitingPos) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.GUILD_OPERATION.getValue()); - mplew.write(0x4C); - mplew.write(channel - 1); - mplew.write(waitingPos); - return mplew.getPacket(); - } - - public static byte[] guildEmblemChange(int gid, short bg, byte bgcolor, short logo, byte logocolor) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.GUILD_OPERATION.getValue()); - mplew.write(0x42); - mplew.writeInt(gid); - mplew.writeShort(bg); - mplew.write(bgcolor); - mplew.writeShort(logo); - mplew.write(logocolor); - return mplew.getPacket(); - } - - public static byte[] guildCapacityChange(int gid, int capacity) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.GUILD_OPERATION.getValue()); - mplew.write(0x3A); - mplew.writeInt(gid); - mplew.write(capacity); - return mplew.getPacket(); - } - - public static void addThread(final MaplePacketLittleEndianWriter mplew, ResultSet rs) throws SQLException { - mplew.writeInt(rs.getInt("localthreadid")); - mplew.writeInt(rs.getInt("postercid")); - mplew.writeMapleAsciiString(rs.getString("name")); - mplew.writeLong(getTime(rs.getLong("timestamp"))); - mplew.writeInt(rs.getInt("icon")); - mplew.writeInt(rs.getInt("replycount")); - } - - public static byte[] BBSThreadList(ResultSet rs, int start) throws SQLException { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.GUILD_BBS_PACKET.getValue()); - mplew.write(0x06); - if (!rs.last()) { - mplew.write(0); - mplew.writeInt(0); - mplew.writeInt(0); - return mplew.getPacket(); - } - int threadCount = rs.getRow(); - if (rs.getInt("localthreadid") == 0) { //has a notice - mplew.write(1); - addThread(mplew, rs); - threadCount--; //one thread didn't count (because it's a notice) - } else { - mplew.write(0); - } - if (!rs.absolute(start + 1)) { //seek to the thread before where we start - rs.first(); //uh, we're trying to start at a place past possible - start = 0; - } - mplew.writeInt(threadCount); - mplew.writeInt(Math.min(10, threadCount - start)); - for (int i = 0; i < Math.min(10, threadCount - start); i++) { - addThread(mplew, rs); - rs.next(); - } - return mplew.getPacket(); - } - - public static byte[] showThread(int localthreadid, ResultSet threadRS, ResultSet repliesRS) throws SQLException, RuntimeException { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.GUILD_BBS_PACKET.getValue()); - mplew.write(0x07); - mplew.writeInt(localthreadid); - mplew.writeInt(threadRS.getInt("postercid")); - mplew.writeLong(getTime(threadRS.getLong("timestamp"))); - mplew.writeMapleAsciiString(threadRS.getString("name")); - mplew.writeMapleAsciiString(threadRS.getString("startpost")); - mplew.writeInt(threadRS.getInt("icon")); - if (repliesRS != null) { - int replyCount = threadRS.getInt("replycount"); - mplew.writeInt(replyCount); - int i; - for (i = 0; i < replyCount && repliesRS.next(); i++) { - mplew.writeInt(repliesRS.getInt("replyid")); - mplew.writeInt(repliesRS.getInt("postercid")); - mplew.writeLong(getTime(repliesRS.getLong("timestamp"))); - mplew.writeMapleAsciiString(repliesRS.getString("content")); - } - if (i != replyCount || repliesRS.next()) { - throw new RuntimeException(String.valueOf(threadRS.getInt("threadid"))); - } - } else { - mplew.writeInt(0); - } - return mplew.getPacket(); - } - - public static byte[] showGuildRanks(int npcid, ResultSet rs) throws SQLException { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.GUILD_OPERATION.getValue()); - mplew.write(0x49); - mplew.writeInt(npcid); - if (!rs.last()) { //no guilds o.o - mplew.writeInt(0); - return mplew.getPacket(); - } - mplew.writeInt(rs.getRow()); //number of entries - rs.beforeFirst(); - while (rs.next()) { - mplew.writeMapleAsciiString(rs.getString("name")); - mplew.writeInt(rs.getInt("GP")); - mplew.writeInt(rs.getInt("logo")); - mplew.writeInt(rs.getInt("logoColor")); - mplew.writeInt(rs.getInt("logoBG")); - mplew.writeInt(rs.getInt("logoBGColor")); - } - return mplew.getPacket(); - } - - public static byte[] showPlayerRanks(int npcid, ResultSet rs) throws SQLException { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.GUILD_OPERATION.getValue()); - mplew.write(0x49); - mplew.writeInt(npcid); - if (!rs.last()) { - mplew.writeInt(0); - return mplew.getPacket(); - } - mplew.writeInt(rs.getRow()); - rs.beforeFirst(); - while (rs.next()) { - mplew.writeMapleAsciiString(rs.getString("name")); - mplew.writeInt(rs.getInt("level")); - mplew.writeInt(0); - mplew.writeInt(0); - mplew.writeInt(0); - mplew.writeInt(0); - } - return mplew.getPacket(); - } - - public static byte[] updateGP(int gid, int GP) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.GUILD_OPERATION.getValue()); - mplew.write(0x48); - mplew.writeInt(gid); - mplew.writeInt(GP); - return mplew.getPacket(); - } - - public static byte[] skillEffect(MapleCharacter from, int skillId, int level, byte flags, int speed, byte direction) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SKILL_EFFECT.getValue()); - mplew.writeInt(from.getId()); - mplew.writeInt(skillId); - mplew.write(level); - mplew.write(flags); - mplew.write(speed); - mplew.write(direction); //Mmmk - return mplew.getPacket(); - } - - public static byte[] skillCancel(MapleCharacter from, int skillId) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.CANCEL_SKILL_EFFECT.getValue()); - mplew.writeInt(from.getId()); - mplew.writeInt(skillId); - return mplew.getPacket(); - } - - public static byte[] showMagnet(int mobid, byte success) { // Monster Magnet - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SHOW_MAGNET.getValue()); - mplew.writeInt(mobid); - mplew.write(success); - mplew.skip(10); //Mmmk - return mplew.getPacket(); - } - - /** - * Sends a player hint. - * - * @param hint The hint it's going to send. - * @param width How tall the box is going to be. - * @param height How long the box is going to be. - * @return The player hint packet. - */ - public static byte[] sendHint(String hint, int width, int height) { - if (width < 1) { - width = hint.length() * 10; - if (width < 40) { - width = 40; - } - } - if (height < 5) { - height = 5; - } - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.PLAYER_HINT.getValue()); - mplew.writeMapleAsciiString(hint); - mplew.writeShort(width); - mplew.writeShort(height); - mplew.write(1); - return mplew.getPacket(); - } - - public static byte[] messengerInvite(String from, int messengerid) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.MESSENGER.getValue()); - mplew.write(0x03); - mplew.writeMapleAsciiString(from); - mplew.write(0); - mplew.writeInt(messengerid); - mplew.write(0); - return mplew.getPacket(); - } - - public static byte[] sendSpouseChat(MapleCharacter wife, String msg) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SPOUSE_CHAT.getValue()); - mplew.writeMapleAsciiString(wife.getName()); - mplew.writeMapleAsciiString(msg); - return mplew.getPacket(); - } - - public static byte[] addMessengerPlayer(String from, MapleCharacter chr, int position, int channel) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.MESSENGER.getValue()); - mplew.write(0x00); - mplew.write(position); - addCharLook(mplew, chr, true); - mplew.writeMapleAsciiString(from); - mplew.write(channel); - mplew.write(0x00); - return mplew.getPacket(); - } - - public static byte[] removeMessengerPlayer(int position) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.MESSENGER.getValue()); - mplew.write(0x02); - mplew.write(position); - return mplew.getPacket(); - } - - public static byte[] updateMessengerPlayer(String from, MapleCharacter chr, int position, int channel) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.MESSENGER.getValue()); - mplew.write(0x07); - mplew.write(position); - addCharLook(mplew, chr, true); - mplew.writeMapleAsciiString(from); - mplew.write(channel); - mplew.write(0x00); - return mplew.getPacket(); - } - - public static byte[] joinMessenger(int position) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.MESSENGER.getValue()); - mplew.write(0x01); - mplew.write(position); - return mplew.getPacket(); - } - - public static byte[] messengerChat(String text) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.MESSENGER.getValue()); - mplew.write(0x06); - mplew.writeMapleAsciiString(text); - return mplew.getPacket(); - } - - public static byte[] messengerNote(String text, int mode, int mode2) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.MESSENGER.getValue()); - mplew.write(mode); - mplew.writeMapleAsciiString(text); - mplew.write(mode2); - return mplew.getPacket(); - } - - public static void addPetInfo(final MaplePacketLittleEndianWriter mplew, MaplePet pet, boolean showpet) { - mplew.write(1); - if (showpet) { - mplew.write(0); - } - - mplew.writeInt(pet.getItemId()); - mplew.writeMapleAsciiString(pet.getName()); - mplew.writeInt(pet.getUniqueId()); - mplew.writeInt(0); - mplew.writePos(pet.getPos()); - mplew.write(pet.getStance()); - mplew.writeInt(pet.getFh()); - } - - public static byte[] showPet(MapleCharacter chr, MaplePet pet, boolean remove, boolean hunger) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SPAWN_PET.getValue()); - mplew.writeInt(chr.getId()); - mplew.write(chr.getPetIndex(pet)); - if (remove) { - mplew.write(0); - mplew.write(hunger ? 1 : 0); - } else { - addPetInfo(mplew, pet, true); - } - return mplew.getPacket(); - } - - public static byte[] movePet(int cid, int pid, byte slot, List moves) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.MOVE_PET.getValue()); - mplew.writeInt(cid); - mplew.write(slot); - mplew.writeInt(pid); - serializeMovementList(mplew, moves); - return mplew.getPacket(); - } - - public static byte[] petChat(int cid, byte index, int act, String text) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.PET_CHAT.getValue()); - mplew.writeInt(cid); - mplew.write(index); - mplew.write(0); - mplew.write(act); - mplew.writeMapleAsciiString(text); - mplew.write(0); - return mplew.getPacket(); - } - - public static byte[] commandResponse(int cid, byte index, int animation, boolean success) { - //AE 00 01 00 00 00 00 01 00 00 - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.PET_COMMAND.getValue()); - mplew.writeInt(cid); - mplew.write(index); - mplew.write((animation == 1 || !success) ? 1 : 0); - mplew.write(animation); - if (animation == 1) { - mplew.write(0); - } else { - mplew.writeShort(success ? 1 : 0); - } - return mplew.getPacket(); - } - - public static byte[] showOwnPetLevelUp(byte index) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SHOW_ITEM_GAIN_INCHAT.getValue()); - mplew.write(4); - mplew.write(0); - mplew.write(index); // Pet Index - return mplew.getPacket(); - } - - public static byte[] showPetLevelUp(MapleCharacter chr, byte index) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SHOW_FOREIGN_EFFECT.getValue()); - mplew.writeInt(chr.getId()); - mplew.write(4); - mplew.write(0); - mplew.write(index); - return mplew.getPacket(); - } - - public static byte[] changePetName(MapleCharacter chr, String newname, int slot) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.PET_NAMECHANGE.getValue()); - mplew.writeInt(chr.getId()); - mplew.write(0); - mplew.writeMapleAsciiString(newname); - mplew.write(0); - return mplew.getPacket(); - } - - public static byte[] petStatUpdate(MapleCharacter chr) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.STAT_CHANGED.getValue()); - int mask = 0; - mask |= MapleStat.PET.getValue(); - mplew.write(0); - mplew.writeInt(mask); - MaplePet[] pets = chr.getPets(); - for (int i = 0; i < 3; i++) { - if (pets[i] != null) { - mplew.writeInt(pets[i].getUniqueId()); - mplew.writeInt(0); - } else { - mplew.writeLong(0); - } - } - mplew.write(0); - return mplew.getPacket(); - } - - public static byte[] showForcedEquip(int team) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.FORCED_MAP_EQUIP.getValue()); - if (team > -1) { - mplew.write(team); // 00 = red, 01 = blue - } - return mplew.getPacket(); - } - - public static byte[] summonSkill(int cid, int summonSkillId, int newStance) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SUMMON_SKILL.getValue()); - mplew.writeInt(cid); - mplew.writeInt(summonSkillId); - mplew.write(newStance); - return mplew.getPacket(); - } - - public static byte[] skillCooldown(int sid, int time) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.COOLDOWN.getValue()); - mplew.writeInt(sid); - mplew.writeShort(time);//Int in v97 - return mplew.getPacket(); - } - - public static byte[] skillBookSuccess(MapleCharacter chr, int skillid, int maxlevel, boolean canuse, boolean success) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SKILL_LEARN_ITEM_RESULT.getValue()); - mplew.writeInt(chr.getId()); - mplew.write(1); - mplew.writeInt(skillid); - mplew.writeInt(maxlevel); - mplew.write(canuse ? 1 : 0); - mplew.write(success ? 1 : 0); - return mplew.getPacket(); - } - - public static byte[] getMacros(SkillMacro[] macros) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.MACRO_SYS_DATA_INIT.getValue()); - int count = 0; - for (int i = 0; i < 5; i++) { - if (macros[i] != null) { - count++; - } - } - mplew.write(count); - for (int i = 0; i < 5; i++) { - SkillMacro macro = macros[i]; - if (macro != null) { - mplew.writeMapleAsciiString(macro.getName()); - mplew.write(macro.getShout()); - mplew.writeInt(macro.getSkill1()); - mplew.writeInt(macro.getSkill2()); - mplew.writeInt(macro.getSkill3()); - } - } - return mplew.getPacket(); - } - - public static byte[] getPlayerNPC(PlayerNPCs npc) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.IMITATED_NPC_DATA.getValue()); - mplew.write(0x01); - mplew.writeInt(npc.getId()); - mplew.writeMapleAsciiString(npc.getName()); - mplew.write(0); // direction - mplew.write(npc.getSkin()); - mplew.writeInt(npc.getFace()); - mplew.write(0); - mplew.writeInt(npc.getHair()); - Map equip = npc.getEquips(); - Map myEquip = new LinkedHashMap<>(); - for (short position : equip.keySet()) { - short pos = (short) (position * -1); - if (pos > 100) { - pos -= 100; - myEquip.put(pos, equip.get(position)); - } else { - if (myEquip.get(pos) == null) { - myEquip.put(pos, equip.get(position)); - } - } - } - for (Entry entry : myEquip.entrySet()) { - mplew.write(entry.getKey()); - mplew.writeInt(entry.getValue()); - } - mplew.writeShort(-1); - Integer cWeapon = equip.get((byte) -111); - if (cWeapon != null) { - mplew.writeInt(cWeapon); - } else { - mplew.writeInt(0); - } - for (int i = 0; i < 12; i++) { - mplew.write(0); - } - return mplew.getPacket(); - } - - public static byte[] updateAriantPQRanking(String name, int score, boolean empty) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.ARIANT_SCORE.getValue()); - mplew.write(empty ? 0 : 1); - if (!empty) { - mplew.writeMapleAsciiString(name); - mplew.writeInt(score); - } - return mplew.getPacket(); - } - - public static byte[] catchMonster(int monsobid, int itemid, byte success) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.CATCH_MONSTER.getValue()); - mplew.writeInt(monsobid); - mplew.writeInt(itemid); - mplew.write(success); - return mplew.getPacket(); - } - - public static byte[] catchMessage(int message) { // not done, I guess - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.BRIDLE_MOB_CATCH_FAIL.getValue()); - mplew.write(message); // 1 = too strong, 2 = Elemental Rock - mplew.writeInt(0);//Maybe itemid? - mplew.writeInt(0); - return mplew.getPacket(); - } - - public static byte[] showAllCharacter(int chars, int unk) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(11); - mplew.writeShort(SendOpcode.VIEW_ALL_CHAR.getValue()); - mplew.write(1); - mplew.writeInt(chars); - mplew.writeInt(unk); - return mplew.getPacket(); - } - - public static byte[] showAllCharacterInfo(int worldid, List chars) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.VIEW_ALL_CHAR.getValue()); - mplew.write(0); - mplew.write(worldid); - mplew.write(chars.size()); - for (MapleCharacter chr : chars) { - addCharEntry(mplew, chr, true); - } - return mplew.getPacket(); - } - - public static byte[] updateMount(int charid, MapleMount mount, boolean levelup) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SET_TAMING_MOB_INFO.getValue()); - mplew.writeInt(charid); - mplew.writeInt(mount.getLevel()); - mplew.writeInt(mount.getExp()); - mplew.writeInt(mount.getTiredness()); - mplew.write(levelup ? (byte) 1 : (byte) 0); - return mplew.getPacket(); - } - - - public static byte[] boatPacket(boolean type) {//don't think this is correct.. - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.CONTI_STATE.getValue()); - mplew.write(type ? 1 : 2); - mplew.write(0); - return mplew.getPacket(); - } - - public static byte[] getMiniGame(MapleClient c, MapleMiniGame minigame, boolean owner, int piece) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); - mplew.write(PlayerInteractionHandler.Action.ROOM.getCode()); - mplew.write(1); - mplew.write(0); - mplew.write(owner ? 0 : 1); - mplew.write(0); - addCharLook(mplew, minigame.getOwner(), false); - mplew.writeMapleAsciiString(minigame.getOwner().getName()); - if (minigame.getVisitor() != null) { - MapleCharacter visitor = minigame.getVisitor(); - mplew.write(1); - addCharLook(mplew, visitor, false); - mplew.writeMapleAsciiString(visitor.getName()); - } - mplew.write(0xFF); - mplew.write(0); - mplew.writeInt(1); - mplew.writeInt(minigame.getOwner().getMiniGamePoints("wins", true)); - mplew.writeInt(minigame.getOwner().getMiniGamePoints("ties", true)); - mplew.writeInt(minigame.getOwner().getMiniGamePoints("losses", true)); - mplew.writeInt(2000); - if (minigame.getVisitor() != null) { - MapleCharacter visitor = minigame.getVisitor(); - mplew.write(1); - mplew.writeInt(1); - mplew.writeInt(visitor.getMiniGamePoints("wins", true)); - mplew.writeInt(visitor.getMiniGamePoints("ties", true)); - mplew.writeInt(visitor.getMiniGamePoints("losses", true)); - mplew.writeInt(2000); - } - mplew.write(0xFF); - mplew.writeMapleAsciiString(minigame.getDescription()); - mplew.write(piece); - mplew.write(0); - return mplew.getPacket(); - } - - public static byte[] getMiniGameReady(MapleMiniGame game) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(3); - mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); - mplew.write(PlayerInteractionHandler.Action.READY.getCode()); - return mplew.getPacket(); - } - - public static byte[] getMiniGameUnReady(MapleMiniGame game) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(3); - mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); - mplew.write(PlayerInteractionHandler.Action.UN_READY.getCode()); - return mplew.getPacket(); - } - - public static byte[] getMiniGameStart(MapleMiniGame game, int loser) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(4); - mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); - mplew.write(PlayerInteractionHandler.Action.START.getCode()); - mplew.write(loser); - return mplew.getPacket(); - } - - public static byte[] getMiniGameSkipOwner(MapleMiniGame game) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(4); - mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); - mplew.write(PlayerInteractionHandler.Action.SKIP.getCode()); - mplew.write(0x01); - return mplew.getPacket(); - } - - public static byte[] getMiniGameRequestTie(MapleMiniGame game) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(3); - mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); - mplew.write(PlayerInteractionHandler.Action.REQUEST_TIE.getCode()); - return mplew.getPacket(); - } - - public static byte[] getMiniGameDenyTie(MapleMiniGame game) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(3); - mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); - mplew.write(PlayerInteractionHandler.Action.ANSWER_TIE.getCode()); - return mplew.getPacket(); - } - - public static byte[] getMiniGameFull() { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(5); - mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); - mplew.write(PlayerInteractionHandler.Action.ROOM.getCode()); - mplew.write(0); - mplew.write(2); - return mplew.getPacket(); - } - - public static byte[] getMiniGameSkipVisitor(MapleMiniGame game) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(4); - mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); - mplew.writeShort(PlayerInteractionHandler.Action.SKIP.getCode()); - return mplew.getPacket(); - } - - public static byte[] getMiniGameMoveOmok(MapleMiniGame game, int move1, int move2, int move3) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(12); - mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); - mplew.write(PlayerInteractionHandler.Action.MOVE_OMOK.getCode()); - mplew.writeInt(move1); - mplew.writeInt(move2); - mplew.write(move3); - return mplew.getPacket(); - } - - public static byte[] getMiniGameNewVisitor(MapleCharacter c, int slot) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); - mplew.write(PlayerInteractionHandler.Action.VISIT.getCode()); - mplew.write(slot); - addCharLook(mplew, c, false); - mplew.writeMapleAsciiString(c.getName()); - mplew.writeInt(1); - mplew.writeInt(c.getMiniGamePoints("wins", true)); - mplew.writeInt(c.getMiniGamePoints("ties", true)); - mplew.writeInt(c.getMiniGamePoints("losses", true)); - mplew.writeInt(2000); - return mplew.getPacket(); - } - - public static byte[] getMiniGameRemoveVisitor() { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(3); - mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); - mplew.write(PlayerInteractionHandler.Action.EXIT.getCode()); - mplew.write(1); - return mplew.getPacket(); - } - - private static byte[] getMiniGameResult(MapleMiniGame game, int win, int lose, int tie, int result, int forfeit, boolean omok) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); - mplew.write(PlayerInteractionHandler.Action.GET_RESULT.getCode()); - if (tie == 0 && forfeit != 1) { - mplew.write(0); - } else if (tie == 1) { - mplew.write(1); - } else if (forfeit == 1) { - mplew.write(2); - } - mplew.write(0); // owner - mplew.writeInt(1); // unknown - mplew.writeInt(game.getOwner().getMiniGamePoints("wins", omok) + win); // wins - mplew.writeInt(game.getOwner().getMiniGamePoints("ties", omok) + tie); // ties - mplew.writeInt(game.getOwner().getMiniGamePoints("losses", omok) + lose); // losses - mplew.writeInt(2000); // points - mplew.writeInt(1); // start of visitor; unknown - mplew.writeInt(game.getVisitor().getMiniGamePoints("wins", omok) + lose); // wins - mplew.writeInt(game.getVisitor().getMiniGamePoints("ties", omok) + tie); // ties - mplew.writeInt(game.getVisitor().getMiniGamePoints("losses", omok) + win); // losses - mplew.writeInt(2000); // points - game.getOwner().setMiniGamePoints(game.getVisitor(), result, omok); - return mplew.getPacket(); - } - - public static byte[] getMiniGameOwnerWin(MapleMiniGame game) { - return getMiniGameResult(game, 0, 1, 0, 1, 0, true); - } - - public static byte[] getMiniGameVisitorWin(MapleMiniGame game) { - return getMiniGameResult(game, 1, 0, 0, 2, 0, true); - } - - public static byte[] getMiniGameTie(MapleMiniGame game) { - return getMiniGameResult(game, 0, 0, 1, 3, 0, true); - } - - public static byte[] getMiniGameOwnerForfeit(MapleMiniGame game) { - return getMiniGameResult(game, 0, 1, 0, 2, 1, true); - } - - public static byte[] getMiniGameVisitorForfeit(MapleMiniGame game) { - return getMiniGameResult(game, 1, 0, 0, 1, 1, true); - } - - public static byte[] getMiniGameClose() { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(5); - mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); - mplew.write(PlayerInteractionHandler.Action.EXIT.getCode()); - mplew.write(1); - mplew.write(3); - return mplew.getPacket(); - } - - public static byte[] getMatchCard(MapleClient c, MapleMiniGame minigame, boolean owner, int piece) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); - mplew.write(PlayerInteractionHandler.Action.ROOM.getCode()); - mplew.write(2); - mplew.write(2); - mplew.write(owner ? 0 : 1); - mplew.write(0); - addCharLook(mplew, minigame.getOwner(), false); - mplew.writeMapleAsciiString(minigame.getOwner().getName()); - if (minigame.getVisitor() != null) { - MapleCharacter visitor = minigame.getVisitor(); - mplew.write(1); - addCharLook(mplew, visitor, false); - mplew.writeMapleAsciiString(visitor.getName()); - } - mplew.write(0xFF); - mplew.write(0); - mplew.writeInt(2); - mplew.writeInt(minigame.getOwner().getMiniGamePoints("wins", false)); - mplew.writeInt(minigame.getOwner().getMiniGamePoints("ties", false)); - mplew.writeInt(minigame.getOwner().getMiniGamePoints("losses", false)); - mplew.writeInt(2000); - if (minigame.getVisitor() != null) { - MapleCharacter visitor = minigame.getVisitor(); - mplew.write(1); - mplew.writeInt(2); - mplew.writeInt(visitor.getMiniGamePoints("wins", false)); - mplew.writeInt(visitor.getMiniGamePoints("ties", false)); - mplew.writeInt(visitor.getMiniGamePoints("losses", false)); - mplew.writeInt(2000); - } - mplew.write(0xFF); - mplew.writeMapleAsciiString(minigame.getDescription()); - mplew.write(piece); - mplew.write(0); - return mplew.getPacket(); - } - - public static byte[] getMatchCardStart(MapleMiniGame game, int loser) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); - mplew.write(PlayerInteractionHandler.Action.START.getCode()); - mplew.write(loser); - mplew.write(0x0C); - int last = 13; - if (game.getMatchesToWin() > 10) { - last = 31; - } else if (game.getMatchesToWin() > 6) { - last = 21; - } - for (int i = 1; i < last; i++) { - mplew.writeInt(game.getCardId(i)); - } - return mplew.getPacket(); - } - - public static byte[] getMatchCardNewVisitor(MapleCharacter c, int slot) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); - mplew.write(PlayerInteractionHandler.Action.VISIT.getCode()); - mplew.write(slot); - addCharLook(mplew, c, false); - mplew.writeMapleAsciiString(c.getName()); - mplew.writeInt(1); - mplew.writeInt(c.getMiniGamePoints("wins", false)); - mplew.writeInt(c.getMiniGamePoints("ties", false)); - mplew.writeInt(c.getMiniGamePoints("losses", false)); - mplew.writeInt(2000); - return mplew.getPacket(); - } - - public static byte[] getMatchCardSelect(MapleMiniGame game, int turn, int slot, int firstslot, int type) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(6); - mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); - mplew.write(PlayerInteractionHandler.Action.SELECT_CARD.getCode()); - mplew.write(turn); - if (turn == 1) { - mplew.write(slot); - } else if (turn == 0) { - mplew.write(slot); - mplew.write(firstslot); - mplew.write(type); - } - return mplew.getPacket(); - } - - public static byte[] getMatchCardOwnerWin(MapleMiniGame game) { - return getMiniGameResult(game, 1, 0, 0, 1, 0, false); - } - - public static byte[] getMatchCardVisitorWin(MapleMiniGame game) { - return getMiniGameResult(game, 0, 1, 0, 2, 0, false); - } - - public static byte[] getMatchCardTie(MapleMiniGame game) { - return getMiniGameResult(game, 0, 0, 1, 3, 0, false); - } - - public static byte[] fredrickMessage(byte operation) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.FREDRICK_MESSAGE.getValue()); - mplew.write(operation); - return mplew.getPacket(); - } - - public static byte[] getFredrick(byte op) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.FREDRICK.getValue()); - mplew.write(op); - - switch (op) { - case 0x24: - mplew.skip(8); - break; - default: - mplew.write(0); - break; - } - - return mplew.getPacket(); - } - - public static byte[] getFredrick(MapleCharacter chr) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.FREDRICK.getValue()); - mplew.write(0x23); - mplew.writeInt(9030000); // Fredrick - mplew.writeInt(32272); //id - mplew.skip(5); - mplew.writeInt(chr.getMerchantMeso()); - mplew.write(0); - try { - List> items = ItemFactory.MERCHANT.loadItems(chr.getId(), false); - mplew.write(items.size()); - - for (int i = 0; i < items.size(); i++) { - addItemInfo(mplew, items.get(i).getLeft(), true); - } - } catch (SQLException e) { - e.printStackTrace(); - } - mplew.skip(3); - return mplew.getPacket(); - } - - public static byte[] addOmokBox(MapleCharacter c, int ammount, int type) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.UPDATE_CHAR_BOX.getValue()); - mplew.writeInt(c.getId()); - addAnnounceBox(mplew, c.getMiniGame(), 1, 0, ammount, type); - return mplew.getPacket(); - } - - public static byte[] removeOmokBox(MapleCharacter c) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(7); - mplew.writeShort(SendOpcode.UPDATE_CHAR_BOX.getValue()); - mplew.writeInt(c.getId()); - mplew.write(0); - return mplew.getPacket(); - } - - public static byte[] addMatchCardBox(MapleCharacter c, int ammount, int type) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.UPDATE_CHAR_BOX.getValue()); - mplew.writeInt(c.getId()); - addAnnounceBox(mplew, c.getMiniGame(), 2, 0, ammount, type); - return mplew.getPacket(); - } - - public static byte[] removeMatchcardBox(MapleCharacter c) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.UPDATE_CHAR_BOX.getValue()); - mplew.writeInt(c.getId()); - mplew.write(0); - return mplew.getPacket(); - } - - public static byte[] getPlayerShopChat(MapleCharacter c, String chat, byte slot) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); - mplew.write(PlayerInteractionHandler.Action.CHAT.getCode()); - mplew.write(PlayerInteractionHandler.Action.CHAT_THING.getCode()); - mplew.write(slot); - mplew.writeMapleAsciiString(c.getName() + " : " + chat); - return mplew.getPacket(); - } - - public static byte[] getTradeChat(MapleCharacter c, String chat, boolean owner) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); - mplew.write(PlayerInteractionHandler.Action.CHAT.getCode()); - mplew.write(PlayerInteractionHandler.Action.CHAT_THING.getCode()); - mplew.write(owner ? 0 : 1); - mplew.writeMapleAsciiString(c.getName() + " : " + chat); - return mplew.getPacket(); - } - - public static byte[] hiredMerchantBox() { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.ENTRUSTED_SHOP_CHECK_RESULT.getValue()); // header. - mplew.write(0x07); - return mplew.getPacket(); - } - - public static byte[] owlOfMinerva(MapleClient c, int itemid, List hms, List items) { //Thanks moongra, you save me some time :) - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SHOP_SCANNER_RESULT.getValue()); // header. - mplew.write(6); - mplew.writeInt(0); - mplew.writeInt(itemid); - mplew.writeInt(hms.size()); - for (HiredMerchant hm : hms) { - for (MaplePlayerShopItem item : items) { - mplew.writeMapleAsciiString(hm.getOwner()); - mplew.writeInt(hm.getMapId()); - mplew.writeMapleAsciiString(hm.getDescription()); - mplew.writeInt(item.getItem().getQuantity()); - mplew.writeInt(item.getBundles()); - mplew.writeInt(item.getPrice()); - mplew.writeInt(hm.getOwnerId()); - mplew.write(hm.getFreeSlot() == -1 ? 1 : 0); - MapleCharacter chr = c.getChannelServer().getPlayerStorage().getCharacterById(hm.getOwnerId()); - if ((chr != null) && (c.getChannel() == hm.getChannel())) { - mplew.write(1); - } else { - mplew.write(2); - } - - if (item.getItem().getItemId() / 1000000 == 1) { - addItemInfo(mplew, item.getItem(), true); - } - } - } - return mplew.getPacket(); - } - - public static byte[] retrieveFirstMessage() { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.ENTRUSTED_SHOP_CHECK_RESULT.getValue()); // header. - mplew.write(0x09); - return mplew.getPacket(); - } - - public static byte[] remoteChannelChange(byte ch) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.ENTRUSTED_SHOP_CHECK_RESULT.getValue()); // header. - mplew.write(0x10); - mplew.writeInt(0);//No idea yet - mplew.write(ch); - return mplew.getPacket(); - } - /* - * Possible things for ENTRUSTED_SHOP_CHECK_RESULT - * 0x0E = 00 = Renaming Failed - Can't find the merchant, 01 = Renaming succesful - * 0x10 = Changes channel to the store (Store is open at Channel 1, do you want to change channels?) - * 0x11 = You cannot sell any items when managing.. blabla - * 0x12 = FKING POPUP LOL - */ - - public static byte[] getHiredMerchant(MapleCharacter chr, HiredMerchant hm, boolean firstTime) {//Thanks Dustin - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); - mplew.write(PlayerInteractionHandler.Action.ROOM.getCode()); - mplew.write(0x05); - mplew.write(0x04); - mplew.writeShort(hm.getVisitorSlot(chr) + 1); - mplew.writeInt(hm.getItemId()); - mplew.writeMapleAsciiString("Hired Merchant"); - for (int i = 0; i < 3; i++) { - if (hm.getVisitors()[i] != null) { - mplew.write(i + 1); - addCharLook(mplew, hm.getVisitors()[i], false); - mplew.writeMapleAsciiString(hm.getVisitors()[i].getName()); - } - } - mplew.write(-1); - if (hm.isOwner(chr)) { - mplew.writeShort(hm.getMessages().size()); - for (int i = 0; i < hm.getMessages().size(); i++) { - mplew.writeMapleAsciiString(hm.getMessages().get(i).getLeft()); - mplew.write(hm.getMessages().get(i).getRight()); - } - } else { - mplew.writeShort(0); - } - mplew.writeMapleAsciiString(hm.getOwner()); - if (hm.isOwner(chr)) { - mplew.writeInt(hm.getTimeLeft()); - mplew.write(firstTime ? 1 : 0); - //List sold = hm.getSold(); - mplew.write(0);//sold.size() - /*for (SoldItem s : sold) { fix this - mplew.writeInt(s.getItemId()); - mplew.writeShort(s.getQuantity()); - mplew.writeInt(s.getMesos()); - mplew.writeMapleAsciiString(s.getBuyer()); - }*/ - mplew.writeInt(chr.getMerchantMeso());//:D? - } - mplew.writeMapleAsciiString(hm.getDescription()); - mplew.write(0x10); //TODO SLOTS, which is 16 for most stores...slotMax - mplew.writeInt(chr.getMeso()); - mplew.write(hm.getItems().size()); - if (hm.getItems().isEmpty()) { - mplew.write(0);//Hmm?? - } else { - for (MaplePlayerShopItem item : hm.getItems()) { - mplew.writeShort(item.getBundles()); - mplew.writeShort(item.getItem().getQuantity()); - mplew.writeInt(item.getPrice()); - addItemInfo(mplew, item.getItem(), true); - } - } - return mplew.getPacket(); - } - - public static byte[] updateHiredMerchant(HiredMerchant hm, MapleCharacter chr) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); - mplew.write(PlayerInteractionHandler.Action.UPDATE_MERCHANT.getCode()); - mplew.writeInt(chr.getMeso()); - mplew.write(hm.getItems().size()); - for (MaplePlayerShopItem item : hm.getItems()) { - mplew.writeShort(item.getBundles()); - mplew.writeShort(item.getItem().getQuantity()); - mplew.writeInt(item.getPrice()); - addItemInfo(mplew, item.getItem(), true); - } - return mplew.getPacket(); - } - - public static byte[] hiredMerchantChat(String message, byte slot) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); - mplew.write(PlayerInteractionHandler.Action.CHAT.getCode()); - mplew.write(PlayerInteractionHandler.Action.CHAT_THING.getCode()); - mplew.write(slot); - mplew.writeMapleAsciiString(message); - return mplew.getPacket(); - } - - public static byte[] hiredMerchantVisitorLeave(int slot) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); - mplew.write(PlayerInteractionHandler.Action.EXIT.getCode()); - if (slot != 0) { - mplew.write(slot); - } - return mplew.getPacket(); - } - - public static byte[] hiredMerchantOwnerLeave() { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); - mplew.write(PlayerInteractionHandler.Action.REAL_CLOSE_MERCHANT.getCode()); - mplew.write(0); - return mplew.getPacket(); - } - - public static byte[] leaveHiredMerchant(int slot, int status2) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); - mplew.write(PlayerInteractionHandler.Action.EXIT.getCode()); - mplew.write(slot); - mplew.write(status2); - return mplew.getPacket(); - } - - public static byte[] hiredMerchantVisitorAdd(MapleCharacter chr, int slot) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); - mplew.write(PlayerInteractionHandler.Action.VISIT.getCode()); - mplew.write(slot); - addCharLook(mplew, chr, false); - mplew.writeMapleAsciiString(chr.getName()); - return mplew.getPacket(); - } - - public static byte[] spawnHiredMerchant(HiredMerchant hm) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SPAWN_HIRED_MERCHANT.getValue()); - mplew.writeInt(hm.getOwnerId()); - mplew.writeInt(hm.getItemId()); - mplew.writeShort((short) hm.getPosition().getX()); - mplew.writeShort((short) hm.getPosition().getY()); - mplew.writeShort(0); - mplew.writeMapleAsciiString(hm.getOwner()); - mplew.write(0x05); - mplew.writeInt(hm.getObjectId()); - mplew.writeMapleAsciiString(hm.getDescription()); - mplew.write(hm.getItemId() % 10); - mplew.write(new byte[]{1, 4}); - return mplew.getPacket(); - } - - public static byte[] destroyHiredMerchant(int id) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.DESTROY_HIRED_MERCHANT.getValue()); - mplew.writeInt(id); - return mplew.getPacket(); - } - - public static byte[] spawnPlayerNPC(PlayerNPCs npc) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SPAWN_NPC_REQUEST_CONTROLLER.getValue()); - mplew.write(1); - mplew.writeInt(npc.getObjectId()); - mplew.writeInt(npc.getId()); - mplew.writeShort(npc.getPosition().x); - mplew.writeShort(npc.getCY()); - mplew.write(1); - mplew.writeShort(npc.getFH()); - mplew.writeShort(npc.getRX0()); - mplew.writeShort(npc.getRX1()); - mplew.write(1); - return mplew.getPacket(); - } - - public static byte[] sendYellowTip(String tip) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SET_WEEK_EVENT_MESSAGE.getValue()); - mplew.write(0xFF); - mplew.writeMapleAsciiString(tip); - mplew.writeShort(0); - return mplew.getPacket(); - } - - public static byte[] givePirateBuff(List> statups, int buffid, int duration) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - boolean infusion = buffid == Buccaneer.SPEED_INFUSION || buffid == ThunderBreaker.SPEED_INFUSION || buffid == Corsair.SPEED_INFUSION; - mplew.writeShort(SendOpcode.GIVE_BUFF.getValue()); - writeLongMask(mplew, statups); - mplew.writeShort(0); - for (Pair stat : statups) { - mplew.writeInt(stat.getRight().shortValue()); - mplew.writeInt(buffid); - mplew.skip(infusion ? 10 : 5); - mplew.writeShort(duration); - } - mplew.skip(3); - return mplew.getPacket(); - } - - public static byte[] giveForgeinPirateBuff(int cid, int buffid, int time, List> statups) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - boolean infusion = buffid == Buccaneer.SPEED_INFUSION || buffid == ThunderBreaker.SPEED_INFUSION || buffid == Corsair.SPEED_INFUSION; - mplew.writeShort(SendOpcode.GIVE_FOREIGN_BUFF.getValue()); - mplew.writeInt(cid); - writeLongMask(mplew, statups); - mplew.writeShort(0); - for (Pair statup : statups) { - mplew.writeInt(statup.getRight().shortValue()); - mplew.writeInt(buffid); - mplew.skip(infusion ? 10 : 5); - mplew.writeShort(time); - } - mplew.writeShort(0); - mplew.write(2); - return mplew.getPacket(); - } - - public static byte[] sendMTS(List items, int tab, int type, int page, int pages) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.MTS_OPERATION.getValue()); - mplew.write(0x15); //operation - mplew.writeInt(pages * 16); //testing, change to 10 if fails - mplew.writeInt(items.size()); //number of items - mplew.writeInt(tab); - mplew.writeInt(type); - mplew.writeInt(page); - mplew.write(1); - mplew.write(1); - for (int i = 0; i < items.size(); i++) { - MTSItemInfo item = items.get(i); - addItemInfo(mplew, item.getItem(), true); - mplew.writeInt(item.getID()); //id - mplew.writeInt(item.getTaxes()); //this + below = price - mplew.writeInt(item.getPrice()); //price - mplew.writeInt(0); - mplew.writeLong(getTime(item.getEndingDate())); - mplew.writeMapleAsciiString(item.getSeller()); //account name (what was nexon thinking?) - mplew.writeMapleAsciiString(item.getSeller()); //char name - for (int j = 0; j < 28; j++) { - mplew.write(0); - } - } - mplew.write(1); - return mplew.getPacket(); - } - - public static byte[] noteSendMsg() { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(3); - mplew.writeShort(SendOpcode.MEMO_RESULT.getValue()); - mplew.write(4); - return mplew.getPacket(); - } - - /* - * 0 = Player online, use whisper - * 1 = Check player's name - * 2 = Receiver inbox full - */ - public static byte[] noteError(byte error) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(4); - mplew.writeShort(SendOpcode.MEMO_RESULT.getValue()); - mplew.write(5); - mplew.write(error); - return mplew.getPacket(); - } - - public static byte[] showNotes(ResultSet notes, int count) throws SQLException { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.MEMO_RESULT.getValue()); - mplew.write(3); - mplew.write(count); - for (int i = 0; i < count; i++) { - mplew.writeInt(notes.getInt("id")); - mplew.writeMapleAsciiString(notes.getString("from") + " ");//Stupid nexon forgot space lol - mplew.writeMapleAsciiString(notes.getString("message")); - mplew.writeLong(getTime(notes.getLong("timestamp"))); - mplew.write(notes.getByte("fame"));//FAME :D - notes.next(); - } - return mplew.getPacket(); - } - - public static byte[] useChalkboard(MapleCharacter chr, boolean close) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.CHALKBOARD.getValue()); - mplew.writeInt(chr.getId()); - if (close) { - mplew.write(0); - } else { - mplew.write(1); - mplew.writeMapleAsciiString(chr.getChalkboard()); - } - return mplew.getPacket(); - } - - public static byte[] trockRefreshMapList(MapleCharacter chr, boolean delete, boolean vip) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.MAP_TRANSFER_RESULT.getValue()); - mplew.write(delete ? 2 : 3); - if (vip) { - mplew.write(1); - List map = chr.getVipTrockMaps(); - for (int i = 0; i < 10; i++) { - mplew.writeInt(map.get(i)); - } - } else { - mplew.write(0); - List map = chr.getTrockMaps(); - for (int i = 0; i < 5; i++) { - mplew.writeInt(map.get(i)); - } - } - return mplew.getPacket(); - } - - public static byte[] showMTSCash(MapleCharacter p) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.MTS_OPERATION2.getValue()); - mplew.writeInt(p.getCashShop().getCash(4)); - mplew.writeInt(p.getCashShop().getCash(2)); - return mplew.getPacket(); - } - - public static byte[] MTSWantedListingOver(int nx, int items) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.MTS_OPERATION.getValue()); - mplew.write(0x3D); - mplew.writeInt(nx); - mplew.writeInt(items); - return mplew.getPacket(); - } - - public static byte[] MTSConfirmSell() { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.MTS_OPERATION.getValue()); - mplew.write(0x1D); - return mplew.getPacket(); - } - - public static byte[] MTSConfirmBuy() { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.MTS_OPERATION.getValue()); - mplew.write(0x33); - return mplew.getPacket(); - } - - public static byte[] MTSFailBuy() { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.MTS_OPERATION.getValue()); - mplew.write(0x34); - mplew.write(0x42); - return mplew.getPacket(); - } - - public static byte[] MTSConfirmTransfer(int quantity, int pos) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.MTS_OPERATION.getValue()); - mplew.write(0x27); - mplew.writeInt(quantity); - mplew.writeInt(pos); - return mplew.getPacket(); - } - - public static byte[] notYetSoldInv(List items) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.MTS_OPERATION.getValue()); - mplew.write(0x23); - mplew.writeInt(items.size()); - if (!items.isEmpty()) { - for (MTSItemInfo item : items) { - addItemInfo(mplew, item.getItem(), true); - mplew.writeInt(item.getID()); //id - mplew.writeInt(item.getTaxes()); //this + below = price - mplew.writeInt(item.getPrice()); //price - mplew.writeInt(0); - mplew.writeLong(getTime(item.getEndingDate())); - mplew.writeMapleAsciiString(item.getSeller()); //account name (what was nexon thinking?) - mplew.writeMapleAsciiString(item.getSeller()); //char name - for (int i = 0; i < 28; i++) { - mplew.write(0); - } - } - } else { - mplew.writeInt(0); - } - return mplew.getPacket(); - } - - public static byte[] transferInventory(List items) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.MTS_OPERATION.getValue()); - mplew.write(0x21); - mplew.writeInt(items.size()); - if (!items.isEmpty()) { - for (MTSItemInfo item : items) { - addItemInfo(mplew, item.getItem(), true); - mplew.writeInt(item.getID()); //id - mplew.writeInt(item.getTaxes()); //taxes - mplew.writeInt(item.getPrice()); //price - mplew.writeInt(0); - mplew.writeLong(getTime(item.getEndingDate())); - mplew.writeMapleAsciiString(item.getSeller()); //account name (what was nexon thinking?) - mplew.writeMapleAsciiString(item.getSeller()); //char name - for (int i = 0; i < 28; i++) { - mplew.write(0); - } - } - } - mplew.write(0xD0 + items.size()); - mplew.write(new byte[]{-1, -1, -1, 0}); - return mplew.getPacket(); - } - - public static byte[] showCouponRedeemedItem(int itemid) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.CASHSHOP_OPERATION.getValue()); - mplew.writeShort(0x49); //v72 - mplew.writeInt(0); - mplew.writeInt(1); - mplew.writeShort(1); - mplew.writeShort(0x1A); - mplew.writeInt(itemid); - mplew.writeInt(0); - return mplew.getPacket(); - } - - public static byte[] showCash(MapleCharacter mc) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.QUERY_CASH_RESULT.getValue()); - - mplew.writeInt(mc.getCashShop().getCash(1)); - mplew.writeInt(mc.getCashShop().getCash(2)); - mplew.writeInt(mc.getCashShop().getCash(4)); - - return mplew.getPacket(); - } - - public static byte[] enableCSUse() { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.write(0x12); - mplew.skip(6); - return mplew.getPacket(); - } - - /** - * - * @param target - * @param mapid - * @param MTSmapCSchannel 0: MTS 1: Map 2: CS 3: Different Channel - * @return - */ - public static byte[] getFindReply(String target, int mapid, int MTSmapCSchannel) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.WHISPER.getValue()); - mplew.write(9); - mplew.writeMapleAsciiString(target); - mplew.write(MTSmapCSchannel); // 0: mts 1: map 2: cs - mplew.writeInt(mapid); // -1 if mts, cs - if (MTSmapCSchannel == 1) { - mplew.write(new byte[8]); - } - return mplew.getPacket(); - } - - public static byte[] sendAutoHpPot(int itemId) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.AUTO_HP_POT.getValue()); - mplew.writeInt(itemId); - return mplew.getPacket(); - } - - public static byte[] sendAutoMpPot(int itemId) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(6); - mplew.writeShort(SendOpcode.AUTO_MP_POT.getValue()); - mplew.writeInt(itemId); - return mplew.getPacket(); - } - - public static byte[] showOXQuiz(int questionSet, int questionId, boolean askQuestion) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(6); - mplew.writeShort(SendOpcode.OX_QUIZ.getValue()); - mplew.write(askQuestion ? 1 : 0); - mplew.write(questionSet); - mplew.writeShort(questionId); - return mplew.getPacket(); - } - - public static byte[] updateGender(MapleCharacter chr) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(3); - mplew.writeShort(SendOpcode.SET_GENDER.getValue()); - mplew.write(chr.getGender()); - return mplew.getPacket(); - } - - public static byte[] enableReport() { // by snow - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(3); - mplew.writeShort(SendOpcode.CLAIM_STATUS_CHANGED.getValue()); - mplew.write(1); - return mplew.getPacket(); - } - - public static byte[] giveFinalAttack(int skillid, int time) {//packets found by lailainoob - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.GIVE_BUFF.getValue()); - mplew.writeLong(0); - mplew.writeShort(0); - mplew.write(0);//some 80 and 0 bs DIRECTION - mplew.write(0x80);//let's just do 80, then 0 - mplew.writeInt(0); - mplew.writeShort(1); - mplew.writeInt(skillid); - mplew.writeInt(time); - mplew.writeInt(0); - return mplew.getPacket(); - } - - public static byte[] loadFamily(MapleCharacter player) { - String[] title = {"Family Reunion", "Summon Family", "My Drop Rate 1.5x (15 min)", "My EXP 1.5x (15 min)", "Family Bonding (30 min)", "My Drop Rate 2x (15 min)", "My EXP 2x (15 min)", "My Drop Rate 2x (30 min)", "My EXP 2x (30 min)", "My Party Drop Rate 2x (30 min)", "My Party EXP 2x (30 min)"}; - String[] description = {"[Target] Me\n[Effect] Teleport directly to the Family member of your choice.", "[Target] 1 Family member\n[Effect] Summon a Family member of choice to the map you're in.", "[Target] Me\n[Time] 15 min.\n[Effect] Monster drop rate will be increased #c1.5x#.\n* If the Drop Rate event is in progress, this will be nullified.", "[Target] Me\n[Time] 15 min.\n[Effect] EXP earned from hunting will be increased #c1.5x#.\n* If the EXP event is in progress, this will be nullified.", "[Target] At least 6 Family members online that are below me in the Pedigree\n[Time] 30 min.\n[Effect] Monster drop rate and EXP earned will be increased #c2x#. \n* If the EXP event is in progress, this will be nullified.", "[Target] Me\n[Time] 15 min.\n[Effect] Monster drop rate will be increased #c2x#.\n* If the Drop Rate event is in progress, this will be nullified.", "[Target] Me\n[Time] 15 min.\n[Effect] EXP earned from hunting will be increased #c2x#.\n* If the EXP event is in progress, this will be nullified.", "[Target] Me\n[Time] 30 min.\n[Effect] Monster drop rate will be increased #c2x#.\n* If the Drop Rate event is in progress, this will be nullified.", "[Target] Me\n[Time] 30 min.\n[Effect] EXP earned from hunting will be increased #c2x#. \n* If the EXP event is in progress, this will be nullified.", "[Target] My party\n[Time] 30 min.\n[Effect] Monster drop rate will be increased #c2x#.\n* If the Drop Rate event is in progress, this will be nullified.", "[Target] My party\n[Time] 30 min.\n[Effect] EXP earned from hunting will be increased #c2x#.\n* If the EXP event is in progress, this will be nullified."}; - int[] repCost = {3, 5, 7, 8, 10, 12, 15, 20, 25, 40, 50}; - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.FAMILY_PRIVILEGE_LIST.getValue()); - mplew.writeInt(11); - for (int i = 0; i < 11; i++) { - mplew.write(i > 4 ? (i % 2) + 1 : i); - mplew.writeInt(repCost[i] * 100); - mplew.writeInt(1); - mplew.writeMapleAsciiString(title[i]); - mplew.writeMapleAsciiString(description[i]); - } - return mplew.getPacket(); - } - - /** - * Family Result Message - * - * Possible values for type:
- * 67: You do not belong to the same family.
- * 69: The character you wish to add as\r\na Junior must be in the same - * map.
- * 70: This character is already a Junior of another character.
- * 71: The Junior you wish to add\r\nmust be at a lower rank.
- * 72: The gap between you and your\r\njunior must be within 20 levels.
- * 73: Another character has requested to add this character.\r\nPlease try - * again later.
- * 74: Another character has requested a summon.\r\nPlease try again - * later.
- * 75: The summons has failed. Your current location or state does not allow - * a summons.
- * 76: The family cannot extend more than 1000 generations from above and - * below.
- * 77: The Junior you wish to add\r\nmust be over Level 10.
- * 78: You cannot add a Junior \r\nthat has requested to change worlds.
- * 79: You cannot add a Junior \r\nsince you've requested to change - * worlds.
- * 80: Separation is not possible due to insufficient Mesos.\r\nYou will - * need %d Mesos to\r\nseparate with a Senior.
- * 81: Separation is not possible due to insufficient Mesos.\r\nYou will - * need %d Mesos to\r\nseparate with a Junior.
- * 82: The Entitlement does not apply because your level does not match the - * corresponding area.
- * - * @param type The type - * @return Family Result packet - */ - public static byte[] sendFamilyMessage(int type, int mesos) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(6); - mplew.writeShort(SendOpcode.FAMILY_RESULT.getValue()); - mplew.writeInt(type); - mplew.writeInt(mesos); - return mplew.getPacket(); - } - - public static byte[] getFamilyInfo(MapleFamilyEntry f) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.FAMILY_INFO_RESULT.getValue()); - mplew.writeInt(f.getReputation()); // cur rep left - mplew.writeInt(f.getTotalReputation()); // tot rep left - mplew.writeInt(f.getTodaysRep()); // todays rep - mplew.writeShort(f.getJuniors()); // juniors added - mplew.writeShort(f.getTotalJuniors()); // juniors allowed - mplew.writeShort(0); //Unknown - mplew.writeInt(f.getId()); // id? - mplew.writeMapleAsciiString(f.getFamilyName()); - mplew.writeInt(0); - mplew.writeShort(0); - return mplew.getPacket(); - } - - public static byte[] showPedigree(int chrid, Map members) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.FAMILY_CHART_RESULT.getValue()); - //Hmmm xD - return mplew.getPacket(); - } - - public static byte[] updateAreaInfo(int area, String info) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SHOW_STATUS_INFO.getValue()); - mplew.write(0x0A); //0x0B in v95 - mplew.writeShort(area);//infoNumber - mplew.writeMapleAsciiString(info); - return mplew.getPacket(); - } - - public static byte[] getGPMessage(int gpChange) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(7); - mplew.writeShort(SendOpcode.SHOW_STATUS_INFO.getValue()); - mplew.write(6); - mplew.writeInt(gpChange); - return mplew.getPacket(); - } - - public static byte[] getItemMessage(int itemid) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(7); - mplew.writeShort(SendOpcode.SHOW_STATUS_INFO.getValue()); - mplew.write(7); - mplew.writeInt(itemid); - return mplew.getPacket(); - } - - public static byte[] addCard(boolean full, int cardid, int level) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(11); - mplew.writeShort(SendOpcode.MONSTER_BOOK_SET_CARD.getValue()); - mplew.write(full ? 0 : 1); - mplew.writeInt(cardid); - mplew.writeInt(level); - return mplew.getPacket(); - } - - public static byte[] showGainCard() { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(3); - mplew.writeShort(SendOpcode.SHOW_ITEM_GAIN_INCHAT.getValue()); - mplew.write(0x0D); - return mplew.getPacket(); - } - - public static byte[] showForeginCardEffect(int id) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(7); - mplew.writeShort(SendOpcode.SHOW_FOREIGN_EFFECT.getValue()); - mplew.writeInt(id); - mplew.write(0x0D); - return mplew.getPacket(); - } - - public static byte[] changeCover(int cardid) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(6); - mplew.writeShort(SendOpcode.MONSTER_BOOK_SET_COVER.getValue()); - mplew.writeInt(cardid); - return mplew.getPacket(); - } - - public static byte[] aranGodlyStats() { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.FORCED_STAT_SET.getValue()); - mplew.write(new byte[]{(byte) 0x1F, (byte) 0x0F, 0, 0, (byte) 0xE7, 3, (byte) 0xE7, 3, (byte) 0xE7, 3, (byte) 0xE7, 3, (byte) 0xFF, 0, (byte) 0xE7, 3, (byte) 0xE7, 3, (byte) 0x78, (byte) 0x8C}); - return mplew.getPacket(); - } - - public static byte[] showIntro(String path) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SHOW_ITEM_GAIN_INCHAT.getValue()); - mplew.write(0x12); - mplew.writeMapleAsciiString(path); - return mplew.getPacket(); - } - - public static byte[] showInfo(String path) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SHOW_ITEM_GAIN_INCHAT.getValue()); - mplew.write(0x17); - mplew.writeMapleAsciiString(path); - mplew.writeInt(1); - return mplew.getPacket(); - } - - /** - * Sends a UI utility. 0x01 - Equipment Inventory. 0x02 - Stat Window. 0x03 - * - Skill Window. 0x05 - Keyboard Settings. 0x06 - Quest window. 0x09 - - * Monsterbook Window. 0x0A - Char Info 0x0B - Guild BBS 0x12 - Monster - * Carnival Window 0x16 - Party Search. 0x17 - Item Creation Window. 0x1A - - * My Ranking O.O 0x1B - Family Window 0x1C - Family Pedigree 0x1D - GM - * Story Board /funny shet 0x1E - Envelop saying you got mail from an admin. - * lmfao 0x1F - Medal Window 0x20 - Maple Event (???) 0x21 - Invalid Pointer - * Crash - * - * @param ui - * @return - */ - public static byte[] openUI(byte ui) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(3); - mplew.writeShort(SendOpcode.OPEN_UI.getValue()); - mplew.write(ui); - return mplew.getPacket(); - } - - public static byte[] lockUI(boolean enable) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(3); - mplew.writeShort(SendOpcode.LOCK_UI.getValue()); - mplew.write(enable ? 1 : 0); - return mplew.getPacket(); - } - - public static byte[] disableUI(boolean enable) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.DISABLE_UI.getValue()); - mplew.write(enable ? 1 : 0); - return mplew.getPacket(); - } - - public static byte[] itemMegaphone(String msg, boolean whisper, int channel, Item item) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SERVERMESSAGE.getValue()); - mplew.write(8); - mplew.writeMapleAsciiString(msg); - mplew.write(channel - 1); - mplew.write(whisper ? 1 : 0); - if (item == null) { - mplew.write(0); - } else { - mplew.write(item.getPosition()); - addItemInfo(mplew, item, true); - } - return mplew.getPacket(); - } - - public static byte[] removeNPC(int oid) { //Make npc's invisible - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SPAWN_NPC_REQUEST_CONTROLLER.getValue()); - mplew.write(0); - mplew.writeInt(oid); - return mplew.getPacket(); - } - - /** - * Sends a report response - * - * Possible values for mode:
0: You have succesfully - * reported the user.
1: Unable to locate the user.
2: You may only - * report users 10 times a day.
3: You have been reported to the GM's by - * a user.
4: Your request did not go through for unknown reasons. - * Please try again later.
- * - * @param mode The mode - * @return Report Reponse packet - */ - public static byte[] reportResponse(byte mode) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SUE_CHARACTER_RESULT.getValue()); - mplew.write(mode); - return mplew.getPacket(); - } - - public static byte[] sendHammerData(int hammerUsed) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.VICIOUS_HAMMER.getValue()); - mplew.write(0x39); - mplew.writeInt(0); - mplew.writeInt(hammerUsed); - return mplew.getPacket(); - } - - public static byte[] sendHammerMessage() { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.VICIOUS_HAMMER.getValue()); - mplew.write(0x3D); - mplew.writeInt(0); - return mplew.getPacket(); - } - - public static byte[] playPortalSound() { - return showSpecialEffect(7); - } - - public static byte[] showMonsterBookPickup() { - return showSpecialEffect(14); - } - - public static byte[] showEquipmentLevelUp() { - return showSpecialEffect(15); - } - - public static byte[] showItemLevelup() { - return showSpecialEffect(15); - } - - /** - * 6 = Exp did not drop (Safety Charms) 7 = Enter portal sound 8 = Job - * change 9 = Quest complete 10 = Recovery 14 = Monster book pickup 15 = - * Equipment levelup 16 = Maker Skill Success 19 = Exp card [500, 200, 50] - * - * @param effect - * @return - */ - public static byte[] showSpecialEffect(int effect) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SHOW_ITEM_GAIN_INCHAT.getValue()); - mplew.write(effect); - return mplew.getPacket(); - } - - public static byte[] showForeignEffect(int cid, int effect) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SHOW_FOREIGN_EFFECT.getValue()); - mplew.writeInt(cid); - mplew.write(effect); - return mplew.getPacket(); - } - - public static byte[] showOwnRecovery(byte heal) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SHOW_ITEM_GAIN_INCHAT.getValue()); - mplew.write(0x0A); - mplew.write(heal); - return mplew.getPacket(); - } - - public static byte[] showRecovery(int cid, byte amount) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SHOW_FOREIGN_EFFECT.getValue()); - mplew.writeInt(cid); - mplew.write(0x0A); - mplew.write(amount); - return mplew.getPacket(); - } - - public static byte[] showWheelsLeft(int left) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SHOW_ITEM_GAIN_INCHAT.getValue()); - mplew.write(0x15); - mplew.write(left); - return mplew.getPacket(); - } - - public static byte[] updateQuestFinish(short quest, int npc, short nextquest) { //Check - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.UPDATE_QUEST_INFO.getValue()); //0xF2 in v95 - mplew.write(8);//0x0A in v95 - mplew.writeShort(quest); - mplew.writeInt(npc); - mplew.writeShort(nextquest); - return mplew.getPacket(); - } - - public static byte[] showInfoText(String text) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SHOW_STATUS_INFO.getValue()); - mplew.write(9); - mplew.writeMapleAsciiString(text); - return mplew.getPacket(); - } - - public static byte[] questError(short quest) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.UPDATE_QUEST_INFO.getValue()); - mplew.write(0x0A); - mplew.writeShort(quest); - return mplew.getPacket(); - } - - public static byte[] questFailure(byte type) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.UPDATE_QUEST_INFO.getValue()); - mplew.write(type);//0x0B = No meso, 0x0D = Worn by character, 0x0E = Not having the item ? - return mplew.getPacket(); - } - - public static byte[] questExpire(short quest) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.UPDATE_QUEST_INFO.getValue()); - mplew.write(0x0F); - mplew.writeShort(quest); - return mplew.getPacket(); - } - - public static byte[] getMultiMegaphone(String[] messages, int channel, boolean showEar) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SERVERMESSAGE.getValue()); - mplew.write(0x0A); - if (messages[0] != null) { - mplew.writeMapleAsciiString(messages[0]); - } - mplew.write(messages.length); - for (int i = 1; i < messages.length; i++) { - if (messages[i] != null) { - mplew.writeMapleAsciiString(messages[i]); - } - } - for (int i = 0; i < 10; i++) { - mplew.write(channel - 1); - } - mplew.write(showEar ? 1 : 0); - mplew.write(1); - return mplew.getPacket(); - } - - /** - * Gets a gm effect packet (ie. hide, banned, etc.) - * - * Possible values for type:
0x04: You have successfully - * blocked access.
- * 0x05: The unblocking has been successful.
0x06 with Mode 0: You have - * successfully removed the name from the ranks.
0x06 with Mode 1: You - * have entered an invalid character name.
0x10: GM Hide, mode - * determines whether or not it is on.
0x1E: Mode 0: Failed to send - * warning Mode 1: Sent warning
0x13 with Mode 0: + mapid 0x13 with Mode - * 1: + ch (FF = Unable to find merchant) - * - * @param type The type - * @param mode The mode - * @return The gm effect packet - */ - public static byte[] getGMEffect(int type, byte mode) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.ADMIN_RESULT.getValue()); - mplew.write(type); - mplew.write(mode); - return mplew.getPacket(); - } - - public static byte[] findMerchantResponse(boolean map, int extra) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.ADMIN_RESULT.getValue()); - mplew.write(0x13); - mplew.write(map ? 0 : 1); //00 = mapid, 01 = ch - if (map) { - mplew.writeInt(extra); - } else { - mplew.write(extra); //-1 = unable to find - } - mplew.write(0); - return mplew.getPacket(); - } - - public static byte[] disableMinimap() { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.ADMIN_RESULT.getValue()); - mplew.writeShort(0x1C); - return mplew.getPacket(); - } - - public static byte[] sendFamilyInvite(int playerId, String inviter) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.FAMILY_JOIN_REQUEST.getValue()); - mplew.writeInt(playerId); - mplew.writeMapleAsciiString(inviter); - return mplew.getPacket(); - } - - public static byte[] showBoughtCashPackage(List cashPackage, int accountId) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.CASHSHOP_OPERATION.getValue()); - - mplew.write(0x89); - mplew.write(cashPackage.size()); - - for (Item item : cashPackage) { - addCashItemInformation(mplew, item, accountId); - } - - mplew.writeShort(0); - - return mplew.getPacket(); - } - - public static byte[] showBoughtQuestItem(int itemId) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.CASHSHOP_OPERATION.getValue()); - - mplew.write(0x8D); - mplew.writeInt(1); - mplew.writeShort(1); - mplew.write(0x0B); - mplew.write(0); - mplew.writeInt(itemId); - - return mplew.getPacket(); - } - - private static void getGuildInfo(final MaplePacketLittleEndianWriter mplew, MapleGuild guild) { - mplew.writeInt(guild.getId()); - mplew.writeMapleAsciiString(guild.getName()); - for (int i = 1; i <= 5; i++) { - mplew.writeMapleAsciiString(guild.getRankTitle(i)); - } - Collection members = guild.getMembers(); - mplew.write(members.size()); - for (MapleGuildCharacter mgc : members) { - mplew.writeInt(mgc.getId()); - } - for (MapleGuildCharacter mgc : members) { - mplew.writeAsciiString(getRightPaddedStr(mgc.getName(), '\0', 13)); - mplew.writeInt(mgc.getJobId()); - mplew.writeInt(mgc.getLevel()); - mplew.writeInt(mgc.getGuildRank()); - mplew.writeInt(mgc.isOnline() ? 1 : 0); - mplew.writeInt(guild.getSignature()); - mplew.writeInt(mgc.getAllianceRank()); - } - mplew.writeInt(guild.getCapacity()); - mplew.writeShort(guild.getLogoBG()); - mplew.write(guild.getLogoBGColor()); - mplew.writeShort(guild.getLogo()); - mplew.write(guild.getLogoColor()); - mplew.writeMapleAsciiString(guild.getNotice()); - mplew.writeInt(guild.getGP()); - mplew.writeInt(guild.getAllianceId()); - } - - public static byte[] getAllianceInfo(MapleAlliance alliance) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.ALLIANCE_OPERATION.getValue()); - mplew.write(0x0C); - mplew.write(1); - mplew.writeInt(alliance.getId()); - mplew.writeMapleAsciiString(alliance.getName()); - for (int i = 1; i <= 5; i++) { - mplew.writeMapleAsciiString(alliance.getRankTitle(i)); - } - mplew.write(alliance.getGuilds().size()); - mplew.writeInt(2); // probably capacity - for (Integer guild : alliance.getGuilds()) { - mplew.writeInt(guild); - } - mplew.writeMapleAsciiString(alliance.getNotice()); - return mplew.getPacket(); - } - - public static byte[] makeNewAlliance(MapleAlliance alliance, MapleClient c) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.ALLIANCE_OPERATION.getValue()); - mplew.write(0x0F); - mplew.writeInt(alliance.getId()); - mplew.writeMapleAsciiString(alliance.getName()); - for (int i = 1; i <= 5; i++) { - mplew.writeMapleAsciiString(alliance.getRankTitle(i)); - } - mplew.write(alliance.getGuilds().size()); - for (Integer guild : alliance.getGuilds()) { - mplew.writeInt(guild); - } - mplew.writeInt(2); // probably capacity - mplew.writeShort(0); - for (Integer guildd : alliance.getGuilds()) { - getGuildInfo(mplew, Server.getInstance().getGuild(guildd, c.getWorld(), c.getPlayer().getMGC())); - } - return mplew.getPacket(); - } - - public static byte[] getGuildAlliances(MapleAlliance alliance, MapleClient c) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.ALLIANCE_OPERATION.getValue()); - mplew.write(0x0D); - mplew.writeInt(alliance.getGuilds().size()); - for (Integer guild : alliance.getGuilds()) { - getGuildInfo(mplew, Server.getInstance().getGuild(guild, c.getWorld(), null)); - } - return mplew.getPacket(); - } - - public static byte[] addGuildToAlliance(MapleAlliance alliance, int newGuild, MapleClient c) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.ALLIANCE_OPERATION.getValue()); - mplew.write(0x12); - mplew.writeInt(alliance.getId()); - mplew.writeMapleAsciiString(alliance.getName()); - for (int i = 1; i <= 5; i++) { - mplew.writeMapleAsciiString(alliance.getRankTitle(i)); - } - mplew.write(alliance.getGuilds().size()); - for (Integer guild : alliance.getGuilds()) { - mplew.writeInt(guild); - } - mplew.writeInt(2); - mplew.writeMapleAsciiString(alliance.getNotice()); - mplew.writeInt(newGuild); - getGuildInfo(mplew, Server.getInstance().getGuild(newGuild, c.getWorld(), null)); - return mplew.getPacket(); - } - - public static byte[] allianceMemberOnline(MapleCharacter mc, boolean online) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.ALLIANCE_OPERATION.getValue()); - mplew.write(0x0E); - mplew.writeInt(mc.getGuild().getAllianceId()); - mplew.writeInt(mc.getGuildId()); - mplew.writeInt(mc.getId()); - mplew.write(online ? 1 : 0); - return mplew.getPacket(); - } - - public static byte[] allianceNotice(int id, String notice) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.ALLIANCE_OPERATION.getValue()); - mplew.write(0x1C); - mplew.writeInt(id); - mplew.writeMapleAsciiString(notice); - return mplew.getPacket(); - } - - public static byte[] changeAllianceRankTitle(int alliance, String[] ranks) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.ALLIANCE_OPERATION.getValue()); - mplew.write(0x1A); - mplew.writeInt(alliance); - for (int i = 0; i < 5; i++) { - mplew.writeMapleAsciiString(ranks[i]); - } - return mplew.getPacket(); - } - - public static byte[] updateAllianceJobLevel(MapleCharacter mc) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.ALLIANCE_OPERATION.getValue()); - mplew.write(0x18); - mplew.writeInt(mc.getGuild().getAllianceId()); - mplew.writeInt(mc.getGuildId()); - mplew.writeInt(mc.getId()); - mplew.writeInt(mc.getLevel()); - mplew.writeInt(mc.getJob().getId()); - return mplew.getPacket(); - } - - public static byte[] removeGuildFromAlliance(MapleAlliance alliance, int expelledGuild, MapleClient c) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.ALLIANCE_OPERATION.getValue()); - mplew.write(0x10); - mplew.writeInt(alliance.getId()); - mplew.writeMapleAsciiString(alliance.getName()); - for (int i = 1; i <= 5; i++) { - mplew.writeMapleAsciiString(alliance.getRankTitle(i)); - } - mplew.write(alliance.getGuilds().size()); - for (Integer guild : alliance.getGuilds()) { - mplew.writeInt(guild); - } - mplew.writeInt(2); - mplew.writeMapleAsciiString(alliance.getNotice()); - mplew.writeInt(expelledGuild); - getGuildInfo(mplew, Server.getInstance().getGuild(expelledGuild, c.getWorld(), null)); - mplew.write(0x01); - return mplew.getPacket(); - } - - public static byte[] disbandAlliance(int alliance) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.ALLIANCE_OPERATION.getValue()); - mplew.write(0x1D); - mplew.writeInt(alliance); - return mplew.getPacket(); - } - - public static byte[] sendMesoLimit() { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.TRADE_MONEY_LIMIT.getValue()); //Players under level 15 can only trade 1m per day - return mplew.getPacket(); - } - - public static byte[] sendEngagementRequest(String name) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.MARRIAGE_REQUEST.getValue()); // has requested engagement. Will you accept this proposal? - mplew.write(0); - mplew.writeMapleAsciiString(name); // name - mplew.writeInt(10); // playerid - return mplew.getPacket(); - } - - public static byte[] sendGroomWishlist() { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.MARRIAGE_REQUEST.getValue()); // has requested engagement. Will you accept this proposal? - mplew.write(9); - return mplew.getPacket(); - } - - public static byte[] sendBrideWishList(List items) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.WEDDING_GIFT_RESULT.getValue()); - mplew.write(0x0A); - mplew.writeLong(-1); // ? - mplew.writeInt(0); // ? - mplew.write(items.size()); - for (Item item : items) { - addItemInfo(mplew, item, true); - } - return mplew.getPacket(); - } - - public static byte[] addItemToWeddingRegistry(MapleCharacter chr, Item item) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.WEDDING_GIFT_RESULT.getValue()); - mplew.write(0x0B); - mplew.writeInt(0); - for (int i = 0; i < 0; i++) // f4 - { - mplew.write(0); - } - - addItemInfo(mplew, item, true); - return mplew.getPacket(); - } - - public static byte[] sendFamilyJoinResponse(boolean accepted, String added) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.FAMILY_JOIN_REQUEST_RESULT.getValue()); - mplew.write(accepted ? 1 : 0); - mplew.writeMapleAsciiString(added); - return mplew.getPacket(); - } - - public static byte[] getSeniorMessage(String name) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.FAMILY_JOIN_ACCEPTED.getValue()); - mplew.writeMapleAsciiString(name); - mplew.writeInt(0); - return mplew.getPacket(); - } - - public static byte[] sendGainRep(int gain, int mode) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.FAMILY_FAMOUS_POINT_INC_RESULT.getValue()); - mplew.writeInt(gain); - mplew.writeShort(0); - return mplew.getPacket(); - } - - public static byte[] removeItemFromDuey(boolean remove, int Package) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.PARCEL.getValue()); - mplew.write(0x17); - mplew.writeInt(Package); - mplew.write(remove ? 3 : 4); - return mplew.getPacket(); - } - - public static byte[] sendDueyMSG(byte operation) { - return sendDuey(operation, null); - } - - public static byte[] sendDuey(byte operation, List packages) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.PARCEL.getValue()); - mplew.write(operation); - if (operation == 8) { - mplew.write(0); - mplew.write(packages.size()); - for (DueyPackages dp : packages) { - mplew.writeInt(dp.getPackageId()); - mplew.writeAsciiString(dp.getSender()); - for (int i = dp.getSender().length(); i < 13; i++) { - mplew.write(0); - } - mplew.writeInt(dp.getMesos()); - mplew.writeLong(getTime(dp.sentTimeInMilliseconds())); - mplew.writeLong(0); // Contains message o____o. - for (int i = 0; i < 48; i++) { - mplew.writeInt(Randomizer.nextInt(Integer.MAX_VALUE)); - } - mplew.writeInt(0); - mplew.write(0); - if (dp.getItem() != null) { - mplew.write(1); - addItemInfo(mplew, dp.getItem(), true); - } else { - mplew.write(0); - } - } - mplew.write(0); - } - - return mplew.getPacket(); - } - - public static byte[] sendDojoAnimation(byte firstByte, String animation) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.FIELD_EFFECT.getValue()); - mplew.write(firstByte); - mplew.writeMapleAsciiString(animation); - return mplew.getPacket(); - } - - public static byte[] getDojoInfo(String info) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SHOW_STATUS_INFO.getValue()); - mplew.write(10); - mplew.write(new byte[]{(byte) 0xB7, 4});//QUEST ID f5 - mplew.writeMapleAsciiString(info); - return mplew.getPacket(); - } - - public static byte[] getDojoInfoMessage(String message) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SHOW_STATUS_INFO.getValue()); - mplew.write(9); - mplew.writeMapleAsciiString(message); - return mplew.getPacket(); - } - - /** - * Gets a "block" packet (ie. the cash shop is unavailable, etc) - * - * Possible values for type:
1: The portal is closed for - * now.
2: You cannot go to that place.
3: Unable to approach due to - * the force of the ground.
4: You cannot teleport to or on this - * map.
5: Unable to approach due to the force of the ground.
6: - * This map can only be entered by party members.
7: The Cash Shop is - * currently not available. Stay tuned...
- * - * @param type The type - * @return The "block" packet. - */ - public static byte[] blockedMessage(int type) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.BLOCKED_MAP.getValue()); - mplew.write(type); - return mplew.getPacket(); - } - - /** - * Gets a "block" packet (ie. the cash shop is unavailable, etc) - * - * Possible values for type:
1: You cannot move that - * channel. Please try again later.
2: You cannot go into the cash shop. - * Please try again later.
3: The Item-Trading Shop is currently - * unavailable. Please try again later.
4: You cannot go into the trade - * shop, due to limitation of user count.
5: You do not meet the minimum - * level requirement to access the Trade Shop.
- * - * @param type The type - * @return The "block" packet. - */ - public static byte[] blockedMessage2(int type) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.BLOCKED_SERVER.getValue()); - mplew.write(type); - return mplew.getPacket(); - } - - public static byte[] updateDojoStats(MapleCharacter chr, int belt) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SHOW_STATUS_INFO.getValue()); - mplew.write(10); - mplew.write(new byte[]{(byte) 0xB7, 4}); //? - mplew.writeMapleAsciiString("pt=" + chr.getDojoPoints() + ";belt=" + belt + ";tuto=" + (chr.getFinishedDojoTutorial() ? "1" : "0")); - return mplew.getPacket(); - } - - /** - * Sends a "levelup" packet to the guild or family. - * - * Possible values for type:
0: ? has reached Lv. - * ?.
- The Reps you have received from ? will be reduced in half. 1: - * ? has reached Lv. ?.
2: ? has reached Lv. ?.
- * - * @param type The type - * @return The "levelup" packet. - */ - public static byte[] levelUpMessage(int type, int level, String charname) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.NOTIFY_LEVELUP.getValue()); - mplew.write(type); - mplew.writeInt(level); - mplew.writeMapleAsciiString(charname); - - return mplew.getPacket(); - } - - /** - * Sends a "married" packet to the guild or family. - * - * Possible values for type:
0: 1: - * - * @param type The type - * @return The "married" packet. - */ - public static byte[] marriageMessage(int type, String charname) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.NOTIFY_MARRIAGE.getValue()); - mplew.write(type); - mplew.writeMapleAsciiString("> " + charname); //To fix the stupid packet lol - - return mplew.getPacket(); - } - - /** - * Sends a "job advance" packet to the guild or family. - * - * Possible values for type:
0: 1: - * - * @param type The type - * @return The "job advance" packet. - */ - public static byte[] jobMessage(int type, int job, String charname) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.NOTIFY_JOB_CHANGE.getValue()); - mplew.write(type); - mplew.writeInt(job); //Why fking int? - mplew.writeMapleAsciiString("> " + charname); //To fix the stupid packet lol - - return mplew.getPacket(); - } - - /** - * - * @param type - (0:Light&Long 1:Heavy&Short) - * @param delay - seconds - * @return - */ - public static byte[] trembleEffect(int type, int delay) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.FIELD_EFFECT.getValue()); - mplew.write(1); - mplew.write(type); - mplew.writeInt(delay); - return mplew.getPacket(); - } - - public static byte[] getEnergy(String info, int amount) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SESSION_VALUE.getValue()); - mplew.writeMapleAsciiString(info); - mplew.writeMapleAsciiString(Integer.toString(amount)); - return mplew.getPacket(); - } - - public static byte[] dojoWarpUp() { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.DOJO_WARP_UP.getValue()); - mplew.write(0); - mplew.write(6); - return mplew.getPacket(); - } - - public static byte[] itemExpired(int itemid) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SHOW_STATUS_INFO.getValue()); - mplew.write(2); - mplew.writeInt(itemid); - return mplew.getPacket(); - } - - private static String getRightPaddedStr(String in, char padchar, int length) { - StringBuilder builder = new StringBuilder(in); - for (int x = in.length(); x < length; x++) { - builder.append(padchar); - } - return builder.toString(); - } - - public static byte[] MobDamageMobFriendly(MapleMonster mob, int damage) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.DAMAGE_MONSTER.getValue()); - mplew.writeInt(mob.getObjectId()); - mplew.write(1); // direction ? - mplew.writeInt(damage); - int remainingHp = mob.getHp() - damage; - if (remainingHp <= 1) { - remainingHp = 0; - mob.getMap().removeMapObject(mob); - } - mob.setHp(remainingHp); - mplew.writeInt(remainingHp); - mplew.writeInt(mob.getMaxHp()); - return mplew.getPacket(); - } - - public static byte[] shopErrorMessage(int error, int type) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); - mplew.write(0x0A); - mplew.write(type); - mplew.write(error); - return mplew.getPacket(); - } - - private static void addRingInfo(final MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { - mplew.writeShort(chr.getCrushRings().size()); - for (MapleRing ring : chr.getCrushRings()) { - mplew.writeInt(ring.getPartnerChrId()); - mplew.writeAsciiString(getRightPaddedStr(ring.getPartnerName(), '\0', 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(), '\0', 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(StringUtil.getRightPaddedStr(chr.getGender() == 0 ? chr.getName() : chr.getMarriageRing().getPartnerName(), '\0', 13)); - mplew.writeAsciiString(StringUtil.getRightPaddedStr(chr.getGender() == 0 ? chr.getMarriageRing().getPartnerName() : chr.getName(), '\0', 13)); - } - } - - public static byte[] finishedSort(int inv) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(4); - mplew.writeShort(SendOpcode.GATHER_ITEM_RESULT.getValue()); - mplew.write(0); - mplew.write(inv); - return mplew.getPacket(); - } - - public static byte[] finishedSort2(int inv) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(4); - mplew.writeShort(SendOpcode.SORT_ITEM_RESULT.getValue()); - mplew.write(0); - mplew.write(inv); - return mplew.getPacket(); - } - - public static byte[] bunnyPacket() { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SHOW_STATUS_INFO.getValue()); - mplew.write(9); - mplew.writeAsciiString("Protect the Moon Bunny!!!"); - return mplew.getPacket(); - } - - public static byte[] hpqMessage(String text) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.BLOW_WEATHER.getValue()); // not 100% sure - mplew.write(0); - mplew.writeInt(5120016); - mplew.writeAsciiString(text); - return mplew.getPacket(); - } - - public static byte[] showEventInstructions() { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.GMEVENT_INSTRUCTIONS.getValue()); - mplew.write(0); - return mplew.getPacket(); - } - - public static byte[] leftKnockBack() { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(2); - mplew.writeShort(SendOpcode.LEFT_KNOCK_BACK.getValue()); - return mplew.getPacket(); - } - - public static byte[] rollSnowBall(boolean entermap, int state, MapleSnowball ball0, MapleSnowball ball1) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SNOWBALL_STATE.getValue()); - if (entermap) { - mplew.skip(21); - } else { - mplew.write(state);// 0 = move, 1 = roll, 2 is down disappear, 3 is up disappear - mplew.writeInt(ball0.getSnowmanHP() / 75); - mplew.writeInt(ball1.getSnowmanHP() / 75); - mplew.writeShort(ball0.getPosition());//distance snowball down, 84 03 = max - mplew.write(-1); - mplew.writeShort(ball1.getPosition());//distance snowball up, 84 03 = max - mplew.write(-1); - } - return mplew.getPacket(); - } - - public static byte[] hitSnowBall(int what, int damage) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(7); - mplew.writeShort(SendOpcode.HIT_SNOWBALL.getValue()); - mplew.write(what); - mplew.writeInt(damage); - return mplew.getPacket(); - } - - /** - * Sends a Snowball Message
- * - * Possible values for message:
1: ... Team's snowball has - * passed the stage 1.
2: ... Team's snowball has passed the stage - * 2.
3: ... Team's snowball has passed the stage 3.
4: ... Team is - * attacking the snowman, stopping the progress
5: ... Team is moving - * again
- * - * @param message - * - */ - public static byte[] snowballMessage(int team, int message) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(7); - mplew.writeShort(SendOpcode.SNOWBALL_MESSAGE.getValue()); - mplew.write(team);// 0 is down, 1 is up - mplew.writeInt(message); - return mplew.getPacket(); - } - - public static byte[] coconutScore(int team1, int team2) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(6); - mplew.writeShort(SendOpcode.COCONUT_SCORE.getValue()); - mplew.writeShort(team1); - mplew.writeShort(team2); - return mplew.getPacket(); - } - - public static byte[] hitCoconut(boolean spawn, int id, int type) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(7); - mplew.writeShort(SendOpcode.COCONUT_HIT.getValue()); - if (spawn) { - mplew.writeShort(-1); - mplew.writeShort(5000); - mplew.write(0); - } else { - mplew.writeShort(id); - mplew.writeShort(1000);//delay till you can attack again! - mplew.write(type); // What action to do for the coconut. - } - return mplew.getPacket(); - } - - public static byte[] customPacket(String packet) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.write(HexTool.getByteArrayFromHexString(packet)); - return mplew.getPacket(); - } - - public static byte[] customPacket(byte[] packet) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(packet.length); - mplew.write(packet); - return mplew.getPacket(); - } - - public static byte[] spawnGuide(boolean spawn) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(3); - mplew.writeShort(SendOpcode.SPAWN_GUIDE.getValue()); - if (spawn) { - mplew.write(1); - } else { - mplew.write(0); - } - return mplew.getPacket(); - } - - public static byte[] talkGuide(String talk) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.TALK_GUIDE.getValue()); - mplew.write(0); - mplew.writeMapleAsciiString(talk); - mplew.write(new byte[]{(byte) 0xC8, 0, 0, 0, (byte) 0xA0, (byte) 0x0F, 0, 0}); - return mplew.getPacket(); - } - - public static byte[] guideHint(int hint) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(11); - mplew.writeShort(SendOpcode.TALK_GUIDE.getValue()); - mplew.write(1); - mplew.writeInt(hint); - mplew.writeInt(7000); - return mplew.getPacket(); - } - - public static void addCashItemInformation(final MaplePacketLittleEndianWriter mplew, Item item, int accountId) { - addCashItemInformation(mplew, item, accountId, null); - } - - public static void addCashItemInformation(final MaplePacketLittleEndianWriter mplew, Item item, int accountId, String giftMessage) { - boolean isGift = giftMessage != null; - boolean isRing = false; - Equip equip = null; - if (item.getType() == 1) { - equip = (Equip) item; - isRing = equip.getRingId() > -1; - } - mplew.writeLong(item.getPetId() > -1 ? item.getPetId() : isRing ? equip.getRingId() : item.getCashId()); - if (!isGift) { - mplew.writeInt(accountId); - mplew.writeInt(0); - } - mplew.writeInt(item.getItemId()); - if (!isGift) { - mplew.writeInt(item.getSN()); - mplew.writeShort(item.getQuantity()); - } - mplew.writeAsciiString(StringUtil.getRightPaddedStr(item.getGiftFrom(), '\0', 13)); - if (isGift) { - mplew.writeAsciiString(StringUtil.getRightPaddedStr(giftMessage, '\0', 73)); - return; - } - addExpirationTime(mplew, item.getExpiration()); - mplew.writeLong(0); - } - - public static byte[] showWishList(MapleCharacter mc, boolean update) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.CASHSHOP_OPERATION.getValue()); - - if (update) { - mplew.write(0x55); - } else { - mplew.write(0x4F); - } - - for (int sn : mc.getCashShop().getWishList()) { - mplew.writeInt(sn); - } - - for (int i = mc.getCashShop().getWishList().size(); i < 10; i++) { - mplew.writeInt(0); - } - - return mplew.getPacket(); - } - - public static byte[] showBoughtCashItem(Item item, int accountId) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.CASHSHOP_OPERATION.getValue()); - - mplew.write(0x57); - addCashItemInformation(mplew, item, accountId); - - return mplew.getPacket(); - } - - /* - * 00 = Due to an unknown error, failed - * A4 = Due to an unknown error, failed + warpout - * A5 = You don't have enough cash. - * A6 = long as shet msg - * A7 = You have exceeded the allotted limit of price for gifts. - * A8 = You cannot send a gift to your own account. Log in on the char and purchase - * A9 = Please confirm whether the character's name is correct. - * AA = Gender restriction! - * //Skipped a few - * B0 = Wrong Coupon Code - * B1 = Disconnect from CS because of 3 wrong coupon codes < lol - * B2 = Expired Coupon - * B3 = Coupon has been used already - * B4 = Nexon internet cafes? lolfk - * - * BB = inv full - * C2 = not enough mesos? Lol not even 1 mesos xD - */ - public static byte[] showCashShopMessage(byte message) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(4); - mplew.writeShort(SendOpcode.CASHSHOP_OPERATION.getValue()); - - mplew.write(0x5C); - mplew.write(message); - - return mplew.getPacket(); - } - - public static byte[] showCashInventory(MapleClient c) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.CASHSHOP_OPERATION.getValue()); - - mplew.write(0x4B); - mplew.writeShort(c.getPlayer().getCashShop().getInventory().size()); - - for (Item item : c.getPlayer().getCashShop().getInventory()) { - addCashItemInformation(mplew, item, c.getAccID()); - } - - mplew.writeShort(c.getPlayer().getStorage().getSlots()); - mplew.writeShort(c.getCharacterSlots()); - - return mplew.getPacket(); - } - - public static byte[] showGifts(List> gifts) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.CASHSHOP_OPERATION.getValue()); - - mplew.write(0x4D); - mplew.writeShort(gifts.size()); - - for (Pair gift : gifts) { - addCashItemInformation(mplew, gift.getLeft(), 0, gift.getRight()); - } - - return mplew.getPacket(); - } - - public static byte[] showGiftSucceed(String to, CashItem item) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.CASHSHOP_OPERATION.getValue()); - - mplew.write(0x5E); //0x5D, Couldn't be sent - mplew.writeMapleAsciiString(to); - mplew.writeInt(item.getItemId()); - mplew.writeShort(item.getCount()); - mplew.writeInt(item.getPrice()); - - return mplew.getPacket(); - } - - public static byte[] showBoughtInventorySlots(int type, short slots) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(6); - mplew.writeShort(SendOpcode.CASHSHOP_OPERATION.getValue()); - - mplew.write(0x60); - mplew.write(type); - mplew.writeShort(slots); - - return mplew.getPacket(); - } - - public static byte[] showBoughtStorageSlots(short slots) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(5); - mplew.writeShort(SendOpcode.CASHSHOP_OPERATION.getValue()); - - mplew.write(0x62); - mplew.writeShort(slots); - - return mplew.getPacket(); - } - - public static byte[] showBoughtCharacterSlot(short slots) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(5); - mplew.writeShort(SendOpcode.CASHSHOP_OPERATION.getValue()); - - mplew.write(0x64); - mplew.writeShort(slots); - - return mplew.getPacket(); - } - - public static byte[] takeFromCashInventory(Item item) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.CASHSHOP_OPERATION.getValue()); - - mplew.write(0x68); - mplew.writeShort(item.getPosition()); - addItemInfo(mplew, item, true); - - return mplew.getPacket(); - } - - public static byte[] putIntoCashInventory(Item item, int accountId) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.CASHSHOP_OPERATION.getValue()); - - mplew.write(0x6A); - addCashItemInformation(mplew, item, accountId); - - return mplew.getPacket(); - } - - public static byte[] openCashShop(MapleClient c, boolean mts) throws Exception { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(mts ? SendOpcode.SET_ITC.getValue() : SendOpcode.SET_CASH_SHOP.getValue()); - - addCharacterInfo(mplew, c.getPlayer()); - - if (!mts) { - mplew.write(1); - } - - mplew.writeMapleAsciiString(c.getAccountName()); - if (mts) { - mplew.write(new byte[]{(byte) 0x88, 19, 0, 0, 7, 0, 0, 0, (byte) 0xF4, 1, 0, 0, (byte) 0x18, 0, 0, 0, (byte) 0xA8, 0, 0, 0, (byte) 0x70, (byte) 0xAA, (byte) 0xA7, (byte) 0xC5, (byte) 0x4E, (byte) 0xC1, (byte) 0xCA, 1}); - } else { - mplew.writeInt(0); - List lsci = CashItemFactory.getSpecialCashItems(); - mplew.writeShort(lsci.size());//Guess what - for (SpecialCashItem sci : lsci) { - mplew.writeInt(sci.getSN()); - mplew.writeInt(sci.getModifier()); - mplew.write(sci.getInfo()); - } - mplew.skip(121); - - for (int i = 1; i <= 8; i++) { - for (int j = 0; j < 2; j++) { - mplew.writeInt(i); - mplew.writeInt(j); - mplew.writeInt(50200004); - - mplew.writeInt(i); - mplew.writeInt(j); - mplew.writeInt(50200069); - - mplew.writeInt(i); - mplew.writeInt(j); - mplew.writeInt(50200117); - - mplew.writeInt(i); - mplew.writeInt(j); - mplew.writeInt(50100008); - - mplew.writeInt(i); - mplew.writeInt(j); - mplew.writeInt(50000047); - } - } - - mplew.writeInt(0); - mplew.writeShort(0); - mplew.write(0); - mplew.writeInt(75); - } - return mplew.getPacket(); - } - - public static byte[] resetForcedStats() { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(2); - mplew.writeShort(SendOpcode.FORCED_STAT_RESET.getValue()); - return mplew.getPacket(); - } - - public static byte[] showCombo(int count) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(6); - mplew.writeShort(SendOpcode.SHOW_COMBO.getValue()); - mplew.writeInt(count); - return mplew.getPacket(); - } - - public static byte[] earnTitleMessage(String msg) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SCRIPT_PROGRESS_MESSAGE.getValue()); - mplew.writeMapleAsciiString(msg); - return mplew.getPacket(); - } - - public static byte[] startCPQ(MapleCharacter chr, MonsterCarnivalParty enemy) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(25); - mplew.writeShort(SendOpcode.MONSTER_CARNIVAL_START.getValue()); - mplew.write(chr.getTeam()); //team - mplew.writeShort(chr.getCP()); //Obtained CP - Used CP - mplew.writeShort(chr.getObtainedCP()); //Total Obtained CP - mplew.writeShort(chr.getCarnivalParty().getAvailableCP()); //Obtained CP - Used CP of the team - mplew.writeShort(chr.getCarnivalParty().getTotalCP()); //Total Obtained CP of the team - mplew.writeShort(enemy.getAvailableCP()); //Obtained CP - Used CP of the team - mplew.writeShort(enemy.getTotalCP()); //Total Obtained CP of the team - mplew.writeShort(0); //Probably useless nexon shit - mplew.writeLong(0); //Probably useless nexon shit - return mplew.getPacket(); - } - - public static byte[] updateCP(int cp, int tcp) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(6); - mplew.writeShort(SendOpcode.MONSTER_CARNIVAL_OBTAINED_CP.getValue()); - mplew.writeShort(cp); //Obtained CP - Used CP - mplew.writeShort(tcp); //Total Obtained CP - return mplew.getPacket(); - } - - public static byte[] updatePartyCP(MonsterCarnivalParty party) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(7); - mplew.writeShort(SendOpcode.MONSTER_CARNIVAL_PARTY_CP.getValue()); - mplew.write(party.getTeam()); //Team where the points are given to. - mplew.writeShort(party.getAvailableCP()); //Obtained CP - Used CP - mplew.writeShort(party.getTotalCP()); //Total Obtained CP - return mplew.getPacket(); - } - - public static byte[] CPQSummon(int tab, int number, String name) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.MONSTER_CARNIVAL_SUMMON.getValue()); - mplew.write(tab); //Tab - mplew.writeShort(number); //Number of summon inside the tab - mplew.writeMapleAsciiString(name); //Name of the player that summons - return mplew.getPacket(); - } - - public static byte[] CPQDied(MapleCharacter chr) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.MONSTER_CARNIVAL_SUMMON.getValue()); - mplew.write(chr.getTeam()); //Team - mplew.writeMapleAsciiString(chr.getName()); //Name of the player that died - mplew.write(chr.getAndRemoveCP()); //Lost CP - return mplew.getPacket(); - } - - /** - * Sends a CPQ Message
- * - * Possible values for message:
1: You don't have enough CP - * to continue.
2: You can no longer summon the Monster.
3: You can - * no longer summon the being.
4: This being is already summoned.
5: - * This request has failed due to an unknown error.
- * - * @param message Displays a message inside Carnival PQ - * - */ - public static byte[] CPQMessage(byte message) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(3); - mplew.writeShort(SendOpcode.MONSTER_CARNIVAL_MESSAGE.getValue()); - mplew.write(message); //Message - return mplew.getPacket(); - } - - public static byte[] leaveCPQ(MapleCharacter chr) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.MONSTER_CARNIVAL_LEAVE.getValue()); - mplew.write(0); //Something - mplew.write(chr.getTeam()); //Team - mplew.writeMapleAsciiString(chr.getName()); //Player name - return mplew.getPacket(); - } - - public static byte[] sheepRanchInfo(byte wolf, byte sheep) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SHEEP_RANCH_INFO.getValue()); - mplew.write(wolf); - mplew.write(sheep); - return mplew.getPacket(); - } - //Know what this is? ?? >=) - - public static byte[] sheepRanchClothes(int id, byte clothes) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SHEEP_RANCH_CLOTHES.getValue()); - mplew.writeInt(id); //Character id - mplew.write(clothes); //0 = sheep, 1 = wolf, 2 = Spectator (wolf without wool) - return mplew.getPacket(); - } - - public static byte[] incubatorResult() {//lol - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(8); - mplew.writeShort(SendOpcode.INCUBATOR_RESULT.getValue()); - mplew.skip(6); - return mplew.getPacket(); - } - - public static byte[] pyramidGauge(int gauge) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(6); - mplew.writeShort(SendOpcode.PYRAMID_GAUGE.getValue()); - mplew.writeInt(gauge); - return mplew.getPacket(); - } - // f2 - - public static byte[] pyramidScore(byte score, int exp) {//Type cannot be higher than 4 (Rank D), otherwise you'll crash - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(7); - mplew.writeShort(SendOpcode.PYRAMID_SCORE.getValue()); - mplew.write(score); - mplew.writeInt(exp); - return mplew.getPacket(); - } - - public static byte[] spawnDragon(MapleDragon dragon) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SPAWN_DRAGON.getValue()); - mplew.writeInt(dragon.getOwner().getId());//objectid = owner id - mplew.writeShort(dragon.getPosition().x); - mplew.writeShort(0); - mplew.writeShort(dragon.getPosition().y); - mplew.writeShort(0); - mplew.write(dragon.getStance()); - mplew.write(0); - mplew.writeShort(dragon.getOwner().getJob().getId()); - return mplew.getPacket(); - } - - public static byte[] moveDragon(MapleDragon dragon, Point startPos, List res) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.MOVE_DRAGON.getValue()); - mplew.writeInt(dragon.getOwner().getId()); - mplew.writePos(startPos); - serializeMovementList(mplew, res); - return mplew.getPacket(); - } - - /** - * Sends a request to remove Mir
- * - * @param charid - Needs the specific Character ID - * @return The packet - * - */ - public static byte[] removeDragon(int chrid) { - final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.REMOVE_DRAGON.getValue()); - mplew.writeInt(chrid); - return mplew.getPacket(); - } - - /** - * Changes the current background effect to either being rendered or not. - * Data is still missing, so this is pretty binary at the moment in how it - * behaves. - * - * @param remove whether or not the remove or add the specified layer. - * @param layer the targeted layer for removal or addition. - * @param transition the time it takes to transition the effect. - * - * @return a packet to change the background effect of a specified layer. - */ - public static byte[] changeBackgroundEffect(boolean remove, int layer, int transition) { - MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); - mplew.writeShort(SendOpcode.SET_BACK_EFFECT.getValue()); - mplew.writeBool(remove); - mplew.writeInt(0); // not sure what this int32 does yet - mplew.write(layer); - mplew.writeInt(transition); - return mplew.getPacket(); - } + private static void addCharStats(final MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { + mplew.writeInt(chr.getId()); // character id + mplew.writeAsciiString(StringUtil.getRightPaddedStr(chr.getName(), '\0', 13)); + mplew.write(chr.getGender()); // gender (0 = male, 1 = female) + mplew.write(chr.getSkinColor().getId()); // skin color + mplew.writeInt(chr.getFace()); // face + mplew.writeInt(chr.getHair()); // hair + + for (int i = 0; i < 3; i++) { + if (chr.getPet(i) != null) //Checked GMS.. and your pets stay when going into the cash shop. + { + mplew.writeLong(chr.getPet(i).getUniqueId()); + } else { + mplew.writeLong(0); + } + } + + mplew.write(chr.getLevel()); // level + mplew.writeShort(chr.getJob().getId()); // job + mplew.writeShort(chr.getStr()); // str + mplew.writeShort(chr.getDex()); // dex + mplew.writeShort(chr.getInt()); // int + mplew.writeShort(chr.getLuk()); // luk + mplew.writeShort(chr.getHp()); // hp (?) + mplew.writeShort(chr.getMaxHp()); // maxhp + mplew.writeShort(chr.getMp()); // mp (?) + mplew.writeShort(chr.getMaxMp()); // maxmp + mplew.writeShort(chr.getRemainingAp()); // remaining ap + if (GameConstants.hasSPTable(chr.getJob())) { + mplew.write(chr.getRemainingSpSize()); + for (int i = 0; i < chr.getRemainingSps().length; i++) { + if (chr.getRemainingSpBySkill(i) > 0) { + mplew.write(i + 1); + mplew.write(chr.getRemainingSpBySkill(i)); + } + } + } else { + mplew.writeShort(chr.getRemainingSp()); // remaining sp + } + mplew.writeInt(chr.getExp()); // current exp + mplew.writeShort(chr.getFame()); // fame + mplew.writeInt(chr.getGachaExp()); //Gacha Exp + mplew.writeInt(chr.getMapId()); // current map id + mplew.write(chr.getInitialSpawnpoint()); // spawnpoint + mplew.writeInt(0); + } + + private static void addCharLook(final MaplePacketLittleEndianWriter mplew, MapleCharacter chr, boolean mega) { + mplew.write(chr.getGender()); + mplew.write(chr.getSkinColor().getId()); // skin color + mplew.writeInt(chr.getFace()); // face + mplew.write(mega ? 0 : 1); + mplew.writeInt(chr.getHair()); // hair + addCharEquips(mplew, chr); + } + + private static void addCharacterInfo(final MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { + mplew.writeLong(-1); + 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);//have fun! + addAreaInfo(mplew, chr);//assuming it stayed here xd + mplew.writeShort(0); + } + + private static void addNewYearInfo(final MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { + mplew.writeShort(0); + /* + *(_DWORD *)this = CInPacket::Decode4(a2); + *((_DWORD *)v2 + 1) = CInPacket::Decode4(a2); + CInPacket::DecodeStr(&v7); + v9 = 0; + (*(void (__stdcall **)(char *, int))((char *)&loc_B1410B + 1))((char *)v2 + 8, v7); + *(_DWORD *)((char *)v2 + 21) = (unsigned __int8)CInPacket::Decode1(a2); + CInPacket::DecodeBuffer((char *)v2 + 25, 8); + *(_DWORD *)((char *)v2 + 33) = CInPacket::Decode4(a2); + CInPacket::DecodeStr(&v6); + LOBYTE(v8) = 1; + (*(void (__stdcall **)(char *, int))((char *)&loc_B1410B + 1))((char *)v2 + 37, v6); + *(_DWORD *)((char *)v2 + 50) = (unsigned __int8)CInPacket::Decode1(a2); + *(_DWORD *)((char *)v2 + 54) = (unsigned __int8)CInPacket::Decode1(a2); + CInPacket::DecodeBuffer((char *)v2 + 58, 8); + CInPacket::DecodeStr(&v9); + */ + } + + private static void addTeleportInfo(final MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { + final List tele = chr.getTrockMaps(); + final List viptele = chr.getVipTrockMaps(); + for (int i = 0; i < 5; i++) { + mplew.writeInt(tele.get(i)); + } + for (int i = 0; i < 10; i++) { + mplew.writeInt(viptele.get(i)); + } + } + + private static void addMiniGameInfo(final MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { + mplew.writeShort(0); + /*for (int m = size; m > 0; m--) {//nexon does this :P + mplew.writeInt(0); + mplew.writeInt(0); + mplew.writeInt(0); + mplew.writeInt(0); + mplew.writeInt(0); + }*/ + } + + private static void addAreaInfo(final MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { + Map areaInfos = chr.getAreaInfos(); + mplew.writeShort(areaInfos.size()); + for (Short area : areaInfos.keySet()) { + mplew.writeShort(area); + mplew.writeMapleAsciiString(areaInfos.get(area)); + } + } + + private static void addCharEquips(final MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { + MapleInventory equip = chr.getInventory(MapleInventoryType.EQUIPPED); + Collection ii = MapleItemInformationProvider.getInstance().canWearEquipment(chr, equip.list()); + Map myEquip = new LinkedHashMap<>(); + Map maskedEquip = new LinkedHashMap<>(); + for (Item item : ii) { + short pos = (byte) (item.getPosition() * -1); + if (pos < 100 && myEquip.get(pos) == null) { + myEquip.put(pos, item.getItemId()); + } else if (pos > 100 && pos != 111) { // don't ask. o.o + 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 (Entry entry : myEquip.entrySet()) { + mplew.write(entry.getKey()); + mplew.writeInt(entry.getValue()); + } + mplew.write(0xFF); + for (Entry entry : maskedEquip.entrySet()) { + mplew.write(entry.getKey()); + mplew.writeInt(entry.getValue()); + } + mplew.write(0xFF); + Item cWeapon = equip.getItem((short) -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).getItemId()); + } else { + mplew.writeInt(0); + } + } + } + + private static void addCharEntry(final MaplePacketLittleEndianWriter mplew, MapleCharacter chr, boolean viewall) { + addCharStats(mplew, chr); + addCharLook(mplew, chr, false); + if (!viewall) { + mplew.write(0); + } + if (chr.isGM()) { + mplew.write(0); + return; + } + mplew.write(1); // world rank enabled (next 4 ints are not sent if disabled) Short?? + mplew.writeInt(chr.getRank()); // world rank + mplew.writeInt(chr.getRankMove()); // move (negative is downwards) + mplew.writeInt(chr.getJobRank()); // job rank + mplew.writeInt(chr.getJobRankMove()); // move (negative is downwards) + } + + private static void addQuestInfo(final MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { + 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(q.getQuestData()); + } + } + List completed = chr.getCompletedQuests(); + mplew.writeShort(completed.size()); + for (MapleQuestStatus q : completed) { + mplew.writeShort(q.getQuest().getId()); + mplew.writeLong(getTime(q.getCompletionTime())); + } + } + + private static void addItemInfo(final MaplePacketLittleEndianWriter mplew, Item item) { + addItemInfo(mplew, item, false); + } + + private static void addExpirationTime(final MaplePacketLittleEndianWriter mplew, long time) { + mplew.writeLong(getTime(time)); + } + + private static void addItemInfo(final MaplePacketLittleEndianWriter mplew, Item item, boolean zeroPosition) { + MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance(); + boolean isCash = ii.isCash(item.getItemId()); + boolean isPet = item.getPetId() > -1; + boolean isRing = false; + Equip equip = null; + short pos = item.getPosition(); + if (item.getType() == 1) { + equip = (Equip) item; + isRing = equip.getRingId() > -1; + } + if (!zeroPosition) { + if (equip != null) { + if (pos < 0) { + pos *= -1; + } + mplew.writeShort(pos > 100 ? pos - 100 : pos); + } else { + mplew.write(pos); + } + } + mplew.write(item.getType()); + mplew.writeInt(item.getItemId()); + mplew.writeBool(isCash); + if (isCash) { + mplew.writeLong(isPet ? item.getPetId() : isRing ? equip.getRingId() : item.getCashId()); + } + addExpirationTime(mplew, item.getExpiration()); + if (isPet) { + MaplePet pet = item.getPet(); + mplew.writeAsciiString(StringUtil.getRightPaddedStr(pet.getName(), '\0', 13)); + mplew.write(pet.getLevel()); + mplew.writeShort(pet.getCloseness()); + mplew.write(pet.getFullness()); + addExpirationTime(mplew, item.getExpiration()); + mplew.writeInt(0); + mplew.write(new byte[]{(byte) 0x50, (byte) 0x46}); //wonder what this is + mplew.writeInt(0); + return; + } + if (equip == null) { + mplew.writeShort(item.getQuantity()); + mplew.writeMapleAsciiString(item.getOwner()); + mplew.writeShort(item.getFlag()); // flag + + if (ItemConstants.isRechargable(item.getItemId())) { + mplew.writeInt(2); + mplew.write(new byte[]{(byte) 0x54, 0, 0, (byte) 0x34}); + } + return; + } + mplew.write(equip.getUpgradeSlots()); // upgrade slots + mplew.write(equip.getLevel()); // level + mplew.writeShort(equip.getStr()); // str + mplew.writeShort(equip.getDex()); // dex + mplew.writeShort(equip.getInt()); // int + mplew.writeShort(equip.getLuk()); // luk + mplew.writeShort(equip.getHp()); // hp + mplew.writeShort(equip.getMp()); // mp + mplew.writeShort(equip.getWatk()); // watk + mplew.writeShort(equip.getMatk()); // matk + mplew.writeShort(equip.getWdef()); // wdef + mplew.writeShort(equip.getMdef()); // mdef + mplew.writeShort(equip.getAcc()); // accuracy + mplew.writeShort(equip.getAvoid()); // avoid + mplew.writeShort(equip.getHands()); // hands + mplew.writeShort(equip.getSpeed()); // speed + mplew.writeShort(equip.getJump()); // jump + mplew.writeMapleAsciiString(equip.getOwner()); // owner name + mplew.writeShort(equip.getFlag()); //Item Flags + + if (isCash) { + for (int i = 0; i < 10; i++) { + mplew.write(0x40); + } + } else { + mplew.write(0); + mplew.write(equip.getItemLevel()); //Item Level + mplew.writeShort(0); + mplew.writeShort(equip.getItemExp()); //Works pretty weird :s + mplew.writeInt(equip.getVicious()); //WTF NEXON ARE YOU SERIOUS? + mplew.writeLong(0); + } + mplew.writeLong(getTime(-2)); + mplew.writeInt(-1); + + } + + private static void addInventoryInfo(final MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { + for (byte i = 1; i <= 5; i++) { + mplew.write(chr.getInventory(MapleInventoryType.getByType(i)).getSlotLimit()); + } + mplew.writeLong(getTime(-2)); + MapleInventory iv = chr.getInventory(MapleInventoryType.EQUIPPED); + Collection equippedC = iv.list(); + List equipped = new ArrayList<>(equippedC.size()); + List equippedCash = new ArrayList<>(equippedC.size()); + for (Item 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.writeShort(0); // start of equip cash + for (Item item : equippedCash) { + addItemInfo(mplew, item); + } + mplew.writeShort(0); // start of equip inventory + for (Item item : chr.getInventory(MapleInventoryType.EQUIP).list()) { + addItemInfo(mplew, item); + } + mplew.writeInt(0); + for (Item item : chr.getInventory(MapleInventoryType.USE).list()) { + addItemInfo(mplew, item); + } + mplew.write(0); + for (Item item : chr.getInventory(MapleInventoryType.SETUP).list()) { + addItemInfo(mplew, item); + } + mplew.write(0); + for (Item item : chr.getInventory(MapleInventoryType.ETC).list()) { + addItemInfo(mplew, item); + } + mplew.write(0); + for (Item item : chr.getInventory(MapleInventoryType.CASH).list()) { + addItemInfo(mplew, item); + } + } + + private static void addSkillInfo(final MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { + mplew.write(0); // start of skills + Map skills = chr.getSkills(); + int skillsSize = skills.size(); + // We don't want to include any hidden skill in this, so subtract them from the size list and ignore them. + for (Iterator> it = skills.entrySet().iterator(); it.hasNext();) { + Entry skill = it.next(); + if (GameConstants.isHiddenSkills(skill.getKey().getId())) { + skillsSize--; + } + } + mplew.writeShort(skillsSize); + for (Iterator> it = skills.entrySet().iterator(); it.hasNext();) { + Entry skill = it.next(); + if (GameConstants.isHiddenSkills(skill.getKey().getId())) { + continue; + } + mplew.writeInt(skill.getKey().getId()); + mplew.writeInt(skill.getValue().skillevel); + addExpirationTime(mplew, skill.getValue().expiration); + if (skill.getKey().isFourthJob()) { + mplew.writeInt(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.writeShort(timeLeft / 1000); + } + } + + private static void addMonsterBookInfo(final MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { + mplew.writeInt(chr.getMonsterBookCover()); // cover + mplew.write(0); + Map cards = chr.getMonsterBook().getCards(); + mplew.writeShort(cards.size()); + for (Entry all : cards.entrySet()) { + mplew.writeShort(all.getKey() % 10000); // Id + mplew.write(all.getValue()); // Level + } + } + + public static byte[] sendGuestTOS() { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.GUEST_ID_LOGIN.getValue()); + mplew.writeShort(0x100); + mplew.writeInt(Randomizer.nextInt(999999)); + mplew.writeLong(0); + mplew.writeLong(getTime(-2)); + mplew.writeLong(getTime(System.currentTimeMillis())); + mplew.writeInt(0); + mplew.writeMapleAsciiString("http://maplesolaxia.com"); + return mplew.getPacket(); + } + + /** + * Sends a hello packet. + * + * @param mapleVersion The maple client version. + * @param sendIv the IV used by the server for sending + * @param recvIv the IV used by the server for receiving + * @return + */ + public static byte[] getHello(short mapleVersion, byte[] sendIv, byte[] recvIv) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(8); + mplew.writeShort(0x0E); + mplew.writeShort(mapleVersion); + mplew.writeShort(1); + mplew.write(49); + mplew.write(recvIv); + mplew.write(sendIv); + mplew.write(8); + return mplew.getPacket(); + } + + /** + * Sends a ping packet. + * + * @return The packet. + */ + public static byte[] getPing() { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(2); + mplew.writeShort(SendOpcode.PING.getValue()); + return mplew.getPacket(); + } + + /** + * Gets a login failed packet. + * + * Possible values for reason:
3: ID deleted or blocked
+ * 4: Incorrect password
5: Not a registered id
6: System error
+ * 7: Already logged in
8: System error
9: System error
10: + * Cannot process so many connections
11: Only users older than 20 can + * use this channel
13: Unable to log on as master at this ip
14: + * Wrong gateway or personal info and weird korean button
15: Processing + * request with that korean button!
16: Please verify your account + * through email...
17: Wrong gateway or personal info
21: Please + * verify your account through email...
23: License agreement
25: + * Maple Europe notice =[ FUCK YOU NEXON
27: Some weird full client + * notice, probably for trial versions
+ * + * @param reason The reason logging in failed. + * @return The login failed packet. + */ + public static byte[] getLoginFailed(int reason) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(8); + mplew.writeShort(SendOpcode.LOGIN_STATUS.getValue()); + mplew.write(reason); + mplew.write(0); + mplew.writeInt(0); + return mplew.getPacket(); + } + + /** + * Gets a login failed packet. + * + * Possible values for reason:
2: ID deleted or blocked
+ * 3: ID deleted or blocked
4: Incorrect password
5: Not a + * registered id
6: Trouble logging into the game?
7: Already logged + * in
8: Trouble logging into the game?
9: Trouble logging into the + * game?
10: Cannot process so many connections
11: Only users older + * than 20 can use this channel
12: Trouble logging into the game?
+ * 13: Unable to log on as master at this ip
14: Wrong gateway or + * personal info and weird korean button
15: Processing request with + * that korean button!
16: Please verify your account through + * email...
17: Wrong gateway or personal info
21: Please verify + * your account through email...
23: Crashes
25: Maple Europe notice + * =[ FUCK YOU NEXON
27: Some weird full client notice, probably for + * trial versions
+ * + * @param reason The reason logging in failed. + * @return The login failed packet. + */ + public static byte[] getAfterLoginError(int reason) {//same as above o.o + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(8); + mplew.writeShort(SendOpcode.SELECT_CHARACTER_BY_VAC.getValue()); + mplew.writeShort(reason);//using other types then stated above = CRASH + return mplew.getPacket(); + } + + public static byte[] sendPolice() { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.FAKE_GM_NOTICE.getValue()); + mplew.write(0);//doesn't even matter what value + return mplew.getPacket(); + } + + public static byte[] sendPolice(String text) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.DATA_CRC_CHECK_FAILED.getValue()); + mplew.writeMapleAsciiString(text); + return mplew.getPacket(); + } + + public static byte[] getPermBan(byte reason) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.LOGIN_STATUS.getValue()); + mplew.write(2); // Account is banned + mplew.write(0); + mplew.writeInt(0); + mplew.write(0); + mplew.writeLong(getTime(-1)); + + return mplew.getPacket(); + } + + public static byte[] getTempBan(long timestampTill, byte reason) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(17); + mplew.writeShort(SendOpcode.LOGIN_STATUS.getValue()); + mplew.write(2); + mplew.write(0); + mplew.writeInt(0); + mplew.write(reason); + mplew.writeLong(getTime(timestampTill)); // Tempban date is handled as a 64-bit long, number of 100NS intervals since 1/1/1601. Lulz. + + return mplew.getPacket(); + } + + /** + * Gets a successful authentication and PIN Request packet. + * + * @param c + * @param account The account name. + * @return The PIN request packet. + */ + public static byte[] getAuthSuccess(MapleClient c) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.LOGIN_STATUS.getValue()); + mplew.writeInt(0); + mplew.writeShort(0); + mplew.writeInt(c.getAccID()); //user id + mplew.write(c.getGender()); + mplew.writeBool(c.getGMLevel() > 0); //admin byte + short toWrite = (short) (c.getGMLevel() * 64); + //toWrite = toWrite |= 0x100; only in higher versions + mplew.write(toWrite >= 0x80 ? 0x80 : 0);//0x80 is admin, 0x20 and 0x40 = subgm + mplew.writeBool(c.getGMLevel() > 0); + //mplew.writeShort(toWrite > 0x80 ? 0x80 : toWrite); only in higher versions... + mplew.writeMapleAsciiString(c.getAccountName()); + mplew.write(0); + mplew.write(0); //isquietbanned + mplew.writeLong(0);//isquietban time + mplew.writeLong(c.getSessionId()); //creation time + mplew.writeInt(0); + mplew.writeShort(2);//PIN + + return mplew.getPacket(); + } + + /** + * Gets a packet detailing a PIN operation. + * + * Possible values for mode:
0 - PIN was accepted
1 - + * Register a new PIN
2 - Invalid pin / Reenter
3 - Connection + * failed due to system error
4 - Enter the pin + * + * @param mode The mode. + * @return + */ + private static byte[] pinOperation(byte mode) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(3); + mplew.writeShort(SendOpcode.CHECK_PINCODE.getValue()); + mplew.write(mode); + return mplew.getPacket(); + } + + public static byte[] pinRegistered() { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(3); + mplew.writeShort(SendOpcode.UPDATE_PINCODE.getValue()); + mplew.write(0); + return mplew.getPacket(); + } + + public static byte[] requestPin() { + return pinOperation((byte) 4); + } + + public static byte[] requestPinAfterFailure() { + return pinOperation((byte) 2); + } + + public static byte[] registerPin() { + return pinOperation((byte) 1); + } + + public static byte[] pinAccepted() { + return pinOperation((byte) 0); + } + + public static byte[] wrongPic() { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(3); + mplew.writeShort(SendOpcode.CHECK_SPW_RESULT.getValue()); + mplew.write(0); + return mplew.getPacket(); + } + + /** + * Gets a packet detailing a server and its channels. + * + * @param serverId + * @param serverName The name of the server. + * @param channelLoad Load of the channel - 1200 seems to be max. + * @return The server info packet. + */ + public static byte[] getServerList(int serverId, String serverName, int flag, String eventmsg, List channelLoad) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SERVERLIST.getValue()); + mplew.write(serverId); + mplew.writeMapleAsciiString(serverName); + mplew.write(flag); + mplew.writeMapleAsciiString(eventmsg); + mplew.write(100); // rate modifier, don't ask O.O! + mplew.write(0); // event xp * 2.6 O.O! + mplew.write(100); // rate modifier, don't ask O.O! + mplew.write(0); // drop rate * 2.6 + mplew.write(0); + mplew.write(channelLoad.size()); + for (Channel ch : channelLoad) { + mplew.writeMapleAsciiString(serverName + "-" + ch.getId()); + mplew.writeInt((ch.getConnectedClients() * 1200) / ServerConstants.CHANNEL_LOAD); + mplew.write(1); + mplew.writeShort(ch.getId() - 1); + } + mplew.writeShort(0); + return mplew.getPacket(); + } + + /** + * Gets a packet saying that the server list is over. + * + * @return The end of server list packet. + */ + public static byte[] getEndOfServerList() { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(3); + mplew.writeShort(SendOpcode.SERVERLIST.getValue()); + mplew.write(0xFF); + return mplew.getPacket(); + } + + /** + * Gets a packet detailing a server status message. + * + * Possible values for status:
0 - Normal
1 - Highly + * populated
2 - Full + * + * @param status The server status. + * @return The server status packet. + */ + public static byte[] getServerStatus(int status) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(4); + mplew.writeShort(SendOpcode.SERVERSTATUS.getValue()); + mplew.writeShort(status); + return mplew.getPacket(); + } + + /** + * Gets a packet telling the client the IP of the channel server. + * + * @param inetAddr The InetAddress of the requested channel server. + * @param port The port the channel is on. + * @param clientId The ID of the client. + * @return The server IP packet. + */ + public static byte[] getServerIP(InetAddress inetAddr, int port, int clientId) { + final 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.write(new byte[]{0, 0, 0, 0, 0}); + return mplew.getPacket(); + } + + /** + * Gets a packet telling the client the IP of the new channel. + * + * @param inetAddr The InetAddress of the requested channel server. + * @param port The port the channel is on. + * @return The server IP packet. + */ + public static byte[] getChannelChange(InetAddress inetAddr, int port) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.CHANGE_CHANNEL.getValue()); + mplew.write(1); + byte[] addr = inetAddr.getAddress(); + mplew.write(addr); + mplew.writeShort(port); + return mplew.getPacket(); + } + + /** + * Gets a packet with a list of characters. + * + * @param c The MapleClient to load characters of. + * @param serverId The ID of the server requested. + * @return The character list packet. + */ + public static byte[] getCharList(MapleClient c, int serverId) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.CHARLIST.getValue()); + mplew.write(0); + List chars = c.loadCharacters(serverId); + mplew.write((byte) chars.size()); + for (MapleCharacter chr : chars) { + addCharEntry(mplew, chr, false); + } + if (ServerConstants.ENABLE_PIC) { + mplew.write(c.getPic() == null || c.getPic().length() == 0 ? 0 : 1); + } else { + mplew.write(2); + } + + mplew.writeInt(c.getCharacterSlots()); + return mplew.getPacket(); + } + + public static byte[] enableTV() { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(7); + mplew.writeShort(SendOpcode.ENABLE_TV.getValue()); + mplew.writeInt(0); + mplew.write(0); + return mplew.getPacket(); + } + + /** + * Removes TV + * + * @return The Remove TV Packet + */ + public static byte[] removeTV() { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(2); + mplew.writeShort(SendOpcode.REMOVE_TV.getValue()); + return mplew.getPacket(); + } + + /** + * Sends MapleTV + * + * @param chr The character shown in TV + * @param messages The message sent with the TV + * @param type The type of TV + * @param partner The partner shown with chr + * @return the SEND_TV packet + */ + public static byte[] sendTV(MapleCharacter chr, List messages, int type, MapleCharacter partner) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SEND_TV.getValue()); + mplew.write(partner != null ? 3 : 1); + mplew.write(type); //Heart = 2 Star = 1 Normal = 0 + addCharLook(mplew, chr, false); + mplew.writeMapleAsciiString(chr.getName()); + if (partner != null) { + mplew.writeMapleAsciiString(partner.getName()); + } else { + mplew.writeShort(0); + } + for (int i = 0; i < messages.size(); i++) { + if (i == 4 && messages.get(4).length() > 15) { + mplew.writeMapleAsciiString(messages.get(4).substring(0, 15)); + } else { + mplew.writeMapleAsciiString(messages.get(i)); + } + } + mplew.writeInt(1337); // time limit shit lol 'Your thing still start in blah blah seconds' + if (partner != null) { + addCharLook(mplew, partner, false); + } + return mplew.getPacket(); + } + + /** + * Gets character info for a character. + * + * @param chr The character to get info about. + * @return The character info packet. + */ + public static byte[] getCharInfo(MapleCharacter chr) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SET_FIELD.getValue()); + mplew.writeInt(chr.getClient().getChannel() - 1); + mplew.write(1); + mplew.write(1); + mplew.writeShort(0); + for (int i = 0; i < 3; i++) { + mplew.writeInt(Randomizer.nextInt()); + } + addCharacterInfo(mplew, chr); + mplew.writeLong(getTime(System.currentTimeMillis())); + return mplew.getPacket(); + } + + /** + * Gets an empty stat update. + * + * @return The empy stat update packet. + */ + public static byte[] enableActions() { + return updatePlayerStats(EMPTY_STATUPDATE, true, null); + } + + /** + * Gets an update for specified stats. + * + * @param stats The stats to update. + * @return The stat update packet. + */ + public static byte[] updatePlayerStats(List> stats, MapleCharacter chr) { + return updatePlayerStats(stats, false, chr); + } + + /** + * Gets an update for specified stats. + * + * @param stats The list of stats to update. + * @param itemReaction Result of an item reaction(?) + * @return The stat update packet. + */ + public static byte[] updatePlayerStats(List> stats, boolean itemReaction, MapleCharacter chr) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.STAT_CHANGED.getValue()); + mplew.write(itemReaction ? 1 : 0); + int updateMask = 0; + for (Pair statupdate : stats) { + updateMask |= statupdate.getLeft().getValue(); + } + List> mystats = stats; + if (mystats.size() > 1) { + Collections.sort(mystats, new Comparator>() { + @Override + public int compare(Pair o1, Pair o2) { + int val1 = o1.getLeft().getValue(); + int val2 = o2.getLeft().getValue(); + return (val1 < val2 ? -1 : (val1 == val2 ? 0 : 1)); + } + }); + } + mplew.writeInt(updateMask); + for (Pair statupdate : mystats) { + if (statupdate.getLeft().getValue() >= 1) { + if (statupdate.getLeft().getValue() == 0x1) { + mplew.writeShort(statupdate.getRight().shortValue()); + } else if (statupdate.getLeft().getValue() <= 0x4) { + mplew.writeInt(statupdate.getRight()); + } else if (statupdate.getLeft().getValue() < 0x20) { + mplew.write(statupdate.getRight().shortValue()); + } else if (statupdate.getLeft().getValue() == 0x8000) { + if (GameConstants.hasSPTable(chr.getJob())) { + mplew.write(chr.getRemainingSpSize()); + for (int i = 0; i < chr.getRemainingSps().length; i++) { + if (chr.getRemainingSpBySkill(i) > 0) { + mplew.write(i + 1); + mplew.write(chr.getRemainingSpBySkill(i)); + } + } + } else { + mplew.writeShort(statupdate.getRight().shortValue()); + } + } else if (statupdate.getLeft().getValue() < 0xFFFF) { + mplew.writeShort(statupdate.getRight().shortValue()); + } else { + mplew.writeInt(statupdate.getRight().intValue()); + } + } + } + return mplew.getPacket(); + } + + /** + * Gets a packet telling the client to change maps. + * + * @param to The MapleMap to warp to. + * @param spawnPoint The spawn portal number to spawn at. + * @param chr The character warping to to + * @return The map change packet. + */ + public static byte[] getWarpToMap(MapleMap to, int spawnPoint, MapleCharacter chr) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SET_FIELD.getValue()); + mplew.writeInt(chr.getClient().getChannel() - 1); + mplew.writeInt(0);//updated + mplew.write(0);//updated + mplew.writeInt(to.getId()); + mplew.write(spawnPoint); + mplew.writeShort(chr.getHp()); + mplew.write(0); + mplew.writeLong(getTime(System.currentTimeMillis())); + return mplew.getPacket(); + } + + /** + * Gets a packet to spawn a portal. + * + * @param townId The ID of the town the portal goes to. + * @param targetId The ID of the target. + * @param pos Where to put the portal. + * @return The portal spawn packet. + */ + public static byte[] spawnPortal(int townId, int targetId, Point pos) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(14); + mplew.writeShort(SendOpcode.SPAWN_PORTAL.getValue()); + mplew.writeInt(townId); + mplew.writeInt(targetId); + if (pos != null) { + mplew.writePos(pos); + } + return mplew.getPacket(); + } + + /** + * Gets a packet to spawn a door. + * + * @param oid The door's object ID. + * @param pos The position of the door. + * @param town + * @return The remove door packet. + */ + public static byte[] spawnDoor(int oid, Point pos, boolean town) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(11); + mplew.writeShort(SendOpcode.SPAWN_DOOR.getValue()); + mplew.writeBool(town); + mplew.writeInt(oid); + mplew.writePos(pos); + return mplew.getPacket(); + } + + /** + * Gets a packet to remove a door. + * + * @param oid The door's ID. + * @param town + * @return The remove door packet. + */ + public static byte[] removeDoor(int oid, boolean town) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(10); + if (town) { + mplew.writeShort(SendOpcode.SPAWN_PORTAL.getValue()); + mplew.writeInt(999999999); + mplew.writeInt(999999999); + } else { + mplew.writeShort(SendOpcode.REMOVE_DOOR.getValue()); + mplew.write(0); + mplew.writeInt(oid); + } + return mplew.getPacket(); + } + + /** + * Gets a packet to spawn a special map object. + * + * @param summon + * @param skillLevel The level of the skill used. + * @param animated Animated spawn? + * @return The spawn packet for the map object. + */ + public static byte[] spawnSummon(MapleSummon summon, boolean animated) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(25); + mplew.writeShort(SendOpcode.SPAWN_SPECIAL_MAPOBJECT.getValue()); + mplew.writeInt(summon.getOwner().getId()); + mplew.writeInt(summon.getObjectId()); + mplew.writeInt(summon.getSkill()); + mplew.write(0x0A); //v83 + mplew.write(summon.getSkillLevel()); + mplew.writePos(summon.getPosition()); + mplew.skip(3); + mplew.write(summon.getMovementType().getValue()); // 0 = don't move, 1 = follow (4th mage summons?), 2/4 = only tele follow, 3 = bird follow + mplew.write(summon.isPuppet() ? 0 : 1); // 0 and the summon can't attack - but puppets don't attack with 1 either ^.- + mplew.write(animated ? 0 : 1); + return mplew.getPacket(); + } + + /** + * Gets a packet to remove a special map object. + * + * @param summon + * @param animated Animated removal? + * @return The packet removing the object. + */ + public static byte[] removeSummon(MapleSummon summon, boolean animated) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(11); + mplew.writeShort(SendOpcode.REMOVE_SPECIAL_MAPOBJECT.getValue()); + mplew.writeInt(summon.getOwner().getId()); + mplew.writeInt(summon.getObjectId()); + mplew.write(animated ? 4 : 1); // ? + return mplew.getPacket(); + } + + /** + * Gets the response to a relog request. + * + * @return The relog response packet. + */ + public static byte[] getRelogResponse() { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(3); + mplew.writeShort(SendOpcode.RELOG_RESPONSE.getValue()); + mplew.write(1);//1 O.O Must be more types ): + return mplew.getPacket(); + } + + /** + * Gets a server message packet. + * + * @param message The message to convey. + * @return The server message packet. + */ + public static byte[] serverMessage(String message) { + return serverMessage(4, (byte) 0, message, true, false, 0); + } + + /** + * Gets a server notice packet. + * + * Possible values for type:
0: [Notice]
1: Popup
+ * 2: Megaphone
3: Super Megaphone
4: Scrolling message at top
+ * 5: Pink Text
6: Lightblue Text + * + * @param type The type of the notice. + * @param message The message to convey. + * @return The server notice packet. + */ + public static byte[] serverNotice(int type, String message) { + return serverMessage(type, (byte) 0, message, false, false, 0); + } + + /** + * Gets a server notice packet. + * + * Possible values for type:
0: [Notice]
1: Popup
+ * 2: Megaphone
3: Super Megaphone
4: Scrolling message at top
+ * 5: Pink Text
6: Lightblue Text + * + * @param type The type of the notice. + * @param channel The channel this notice was sent on. + * @param message The message to convey. + * @return The server notice packet. + */ + public static byte[] serverNotice(int type, String message, int npc) { + return serverMessage(type, 0, message, false, false, npc); + } + + public static byte[] serverNotice(int type, int channel, String message) { + return serverMessage(type, channel, message, false, false, 0); + } + + public static byte[] serverNotice(int type, int channel, String message, boolean smegaEar) { + return serverMessage(type, channel, message, false, smegaEar, 0); + } + + /** + * Gets a server message packet. + * + * Possible values for type:
0: [Notice]
1: Popup
+ * 2: Megaphone
3: Super Megaphone
4: Scrolling message at top
+ * 5: Pink Text
6: Lightblue Text
7: BroadCasting NPC + * + * @param type The type of the notice. + * @param channel The channel this notice was sent on. + * @param message The message to convey. + * @param servermessage Is this a scrolling ticker? + * @return The server notice packet. + */ + private static byte[] serverMessage(int type, int channel, String message, boolean servermessage, boolean megaEar, int npc) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SERVERMESSAGE.getValue()); + mplew.write(type); + if (servermessage) { + mplew.write(1); + } + mplew.writeMapleAsciiString(message); + if (type == 3) { + mplew.write(channel - 1); // channel + mplew.writeBool(megaEar); + } else if (type == 6) { + mplew.writeInt(0); + } else if (type == 7) { // npc + mplew.writeInt(npc); + } + return mplew.getPacket(); + } + + /** + * Sends a Avatar Super Megaphone packet. + * + * @param chr The character name. + * @param medal The medal text. + * @param channel Which channel. + * @param itemId Which item used. + * @param message The message sent. + * @param ear Whether or not the ear is shown for whisper. + * @return + */ + public static byte[] getAvatarMega(MapleCharacter chr, String medal, int channel, int itemId, List message, boolean ear) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SET_AVATAR_MEGAPHONE.getValue()); + mplew.writeInt(itemId); + mplew.writeMapleAsciiString(medal + chr.getName()); + for (String s : message) { + mplew.writeMapleAsciiString(s); + } + mplew.writeInt(channel - 1); // channel + mplew.writeBool(ear); + addCharLook(mplew, chr, true); + return mplew.getPacket(); + } + + /* + * Sends a packet to remove the tiger megaphone + * @return + */ + public static byte[] byeAvatarMega() { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.CLEAR_AVATAR_MEGAPHONE.getValue()); + mplew.write(1); + return mplew.getPacket(); + } + + /** + * Sends the Gachapon green message when a user uses a gachapon ticket. + * + * @param item + * @param town + * @param player + * @return + */ + public static byte[] gachaponMessage(Item item, String town, MapleCharacter player) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SERVERMESSAGE.getValue()); + mplew.write(0x0B); + mplew.writeMapleAsciiString(player.getName() + " : got a(n)"); + mplew.writeInt(0); //random? + mplew.writeMapleAsciiString(town); + addItemInfo(mplew, item, true); + return mplew.getPacket(); + } + + public static byte[] spawnNPC(MapleNPC life) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(24); + mplew.writeShort(SendOpcode.SPAWN_NPC.getValue()); + mplew.writeInt(life.getObjectId()); + mplew.writeInt(life.getId()); + mplew.writeShort(life.getPosition().x); + mplew.writeShort(life.getCy()); + if (life.getF() == 1) { + mplew.write(0); + } else { + mplew.write(1); + } + mplew.writeShort(life.getFh()); + mplew.writeShort(life.getRx0()); + mplew.writeShort(life.getRx1()); + mplew.write(1); + return mplew.getPacket(); + } + + public static byte[] spawnNPCRequestController(MapleNPC life, boolean MiniMap) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(23); + mplew.writeShort(SendOpcode.SPAWN_NPC_REQUEST_CONTROLLER.getValue()); + mplew.write(1); + mplew.writeInt(life.getObjectId()); + mplew.writeInt(life.getId()); + mplew.writeShort(life.getPosition().x); + mplew.writeShort(life.getCy()); + if (life.getF() == 1) { + mplew.write(0); + } else { + mplew.write(1); + } + mplew.writeShort(life.getFh()); + mplew.writeShort(life.getRx0()); + mplew.writeShort(life.getRx1()); + mplew.writeBool(MiniMap); + return mplew.getPacket(); + } + + /** + * Gets a spawn monster packet. + * + * @param life The monster to spawn. + * @param newSpawn Is it a new spawn? + * @return The spawn monster packet. + */ + public static byte[] spawnMonster(MapleMonster life, boolean newSpawn) { + return spawnMonsterInternal(life, false, newSpawn, false, 0, false); + } + + /** + * Gets a spawn monster packet. + * + * @param life The monster to spawn. + * @param newSpawn Is it a new spawn? + * @return The spawn monster packet. + */ + public static byte[] spawnHPQMonster(MapleMonster life, boolean newSpawn) { + return spawnMonsterInternal(life, false, newSpawn, false, 0, false); + } + + /** + * Gets a spawn monster packet. + * + * @param life The monster to spawn. + * @param newSpawn Is it a new spawn? + * @param effect The spawn effect. + * @return The spawn monster packet. + */ + public static byte[] spawnMonster(MapleMonster life, boolean newSpawn, int effect) { + return spawnMonsterInternal(life, false, newSpawn, false, effect, false); + } + + /** + * Gets a control monster packet. + * + * @param life The monster to give control to. + * @param newSpawn Is it a new spawn? + * @param aggro Aggressive monster? + * @return The monster control packet. + */ + public static byte[] controlMonster(MapleMonster life, boolean newSpawn, boolean aggro) { + return spawnMonsterInternal(life, true, newSpawn, aggro, 0, false); + } + + /** + * Removes a monster invisibility. + * + * @param life + * @return + */ + public static byte[] removeMonsterInvisibility(MapleMonster life) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SPAWN_MONSTER_CONTROL.getValue()); + mplew.write(1); + mplew.writeInt(life.getObjectId()); + return mplew.getPacket(); + //return spawnMonsterInternal(life, true, false, false, 0, false); + } + + /** + * Makes a monster invisible for Ariant PQ. + * + * @param life + * @return + */ + public static byte[] makeMonsterInvisible(MapleMonster life) { + return spawnMonsterInternal(life, true, false, false, 0, true); + } + + /** + * Internal function to handler monster spawning and controlling. + * + * @param life The mob to perform operations with. + * @param requestController Requesting control of mob? + * @param newSpawn New spawn (fade in?) + * @param aggro Aggressive mob? + * @param effect The spawn effect to use. + * @return The spawn/control packet. + */ + private static byte[] spawnMonsterInternal(MapleMonster life, boolean requestController, boolean newSpawn, boolean aggro, int effect, boolean makeInvis) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + if (makeInvis) { + mplew.writeShort(SendOpcode.SPAWN_MONSTER_CONTROL.getValue()); + mplew.write(0); + mplew.writeInt(life.getObjectId()); + return mplew.getPacket(); + } + if (requestController) { + mplew.writeShort(SendOpcode.SPAWN_MONSTER_CONTROL.getValue()); + mplew.write(aggro ? 2 : 1); + } else { + mplew.writeShort(SendOpcode.SPAWN_MONSTER.getValue()); + } + mplew.writeInt(life.getObjectId()); + mplew.write(life.getController() == null ? 5 : 1); + mplew.writeInt(life.getId()); + mplew.skip(15); + mplew.write(0x88); + mplew.skip(6); + mplew.writePos(life.getPosition()); + mplew.write(life.getStance()); + mplew.writeShort(0); //Origin FH //life.getStartFh() + mplew.writeShort(life.getFh()); + + if (effect > 0) { + mplew.write(effect); + mplew.write(0); + mplew.writeShort(0); + if (effect == 15) { + mplew.write(0); + } + } + mplew.write(newSpawn ? -2 : -1); + mplew.write(life.getTeam()); + mplew.writeInt(0); + return mplew.getPacket(); + } + + /** + * Handles monsters not being targettable, such as Zakum's first body. + * + * @param life The mob to spawn as non-targettable. + * @param effect The effect to show when spawning. + * @return The packet to spawn the mob as non-targettable. + */ + public static byte[] spawnFakeMonster(MapleMonster life, int effect) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SPAWN_MONSTER_CONTROL.getValue()); + mplew.write(1); + mplew.writeInt(life.getObjectId()); + mplew.write(5); + mplew.writeInt(life.getId()); + mplew.skip(15); + mplew.write(0x88); + mplew.skip(6); + mplew.writePos(life.getPosition()); + mplew.write(life.getStance()); + mplew.writeShort(0);//life.getStartFh() + mplew.writeShort(life.getFh()); + if (effect > 0) { + mplew.write(effect); + mplew.write(0); + mplew.writeShort(0); + } + mplew.writeShort(-2); + mplew.write(life.getTeam()); + mplew.writeInt(0); + return mplew.getPacket(); + } + + /** + * Makes a monster previously spawned as non-targettable, targettable. + * + * @param life The mob to make targettable. + * @return The packet to make the mob targettable. + */ + public static byte[] makeMonsterReal(MapleMonster life) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SPAWN_MONSTER.getValue()); + mplew.writeInt(life.getObjectId()); + mplew.write(5); + mplew.writeInt(life.getId()); + mplew.skip(15); + mplew.write(0x88); + mplew.skip(6); + mplew.writePos(life.getPosition()); + mplew.write(life.getStance()); + mplew.writeShort(0);//life.getStartFh() + mplew.writeShort(life.getFh()); + mplew.writeShort(-1); + mplew.writeInt(0); + return mplew.getPacket(); + } + + /** + * Gets a stop control monster packet. + * + * @param oid The ObjectID of the monster to stop controlling. + * @return The stop control monster packet. + */ + public static byte[] stopControllingMonster(int oid) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(7); + mplew.writeShort(SendOpcode.SPAWN_MONSTER_CONTROL.getValue()); + mplew.write(0); + mplew.writeInt(oid); + return mplew.getPacket(); + } + + /** + * Gets a response to a move monster packet. + * + * @param objectid The ObjectID of the monster being moved. + * @param moveid The movement ID. + * @param currentMp The current MP of the monster. + * @param useSkills Can the monster use skills? + * @return The move response packet. + */ + public static byte[] moveMonsterResponse(int objectid, short moveid, int currentMp, boolean useSkills) { + return moveMonsterResponse(objectid, moveid, currentMp, useSkills, 0, 0); + } + + /** + * Gets a response to a move monster packet. + * + * @param objectid The ObjectID of the monster being moved. + * @param moveid The movement ID. + * @param currentMp The current MP of the monster. + * @param useSkills Can the monster use skills? + * @param skillId The skill ID for the monster to use. + * @param skillLevel The level of the skill to use. + * @return The move response packet. + */ + public static byte[] moveMonsterResponse(int objectid, short moveid, int currentMp, boolean useSkills, int skillId, int skillLevel) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(13); + mplew.writeShort(SendOpcode.MOVE_MONSTER_RESPONSE.getValue()); + mplew.writeInt(objectid); + mplew.writeShort(moveid); + mplew.writeBool(useSkills); + mplew.writeShort(currentMp); + mplew.write(skillId); + mplew.write(skillLevel); + return mplew.getPacket(); + } + + /** + * Gets a general chat packet. + * + * @param cidfrom The character ID who sent the chat. + * @param text The text of the chat. + * @param whiteBG + * @param show + * @return The general chat packet. + */ + public static byte[] getChatText(int cidfrom, String text, boolean gm, int show) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.CHATTEXT.getValue()); + mplew.writeInt(cidfrom); + mplew.writeBool(gm); + mplew.writeMapleAsciiString(text); + mplew.write(show); + return mplew.getPacket(); + } + + /** + * Gets a packet telling the client to show an EXP increase. + * + * @param gain The amount of EXP gained. + * @param inChat In the chat box? + * @param white White text or yellow? + * @return The exp gained packet. + */ + public static byte[] getShowExpGain(int gain, int equip, int party, boolean inChat, boolean white) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SHOW_STATUS_INFO.getValue()); + mplew.write(3); // 3 = exp, 4 = fame, 5 = mesos, 6 = guildpoints + mplew.writeBool(white); + mplew.writeInt(gain); + mplew.writeBool(inChat); + mplew.writeInt(0); // monster book bonus (Bonus Event Exp) + mplew.write(0); // third monster kill event + mplew.write(0); // RIP byte, this is always a 0 + mplew.writeInt(0); //wedding bonus + if (inChat) { // quest bonus rate stuff + mplew.write(0); + } + + int mod = ServerConstants.PARTY_EXPERIENCE_MOD != 1 ? ServerConstants.PARTY_EXPERIENCE_MOD * 100 : 0; + + mplew.write(mod); //0 = party bonus, 100 = 1x Bonus EXP, 200 = 2x Bonus EXP + mplew.writeInt(party); // party bonus + mplew.writeInt(equip); //equip bonus + mplew.writeInt(0); //Internet Cafe Bonus + mplew.writeInt(0); //Rainbow Week Bonus + return mplew.getPacket(); + } + + /** + * Gets a packet telling the client to show a fame gain. + * + * @param gain How many fame gained. + * @return The meso gain packet. + */ + public static byte[] getShowFameGain(int gain) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SHOW_STATUS_INFO.getValue()); + mplew.write(4); + mplew.writeInt(gain); + return mplew.getPacket(); + } + + /** + * Gets a packet telling the client to show a meso gain. + * + * @param gain How many mesos gained. + * @return The meso gain packet. + */ + public static byte[] getShowMesoGain(int gain) { + return getShowMesoGain(gain, false); + } + + /** + * Gets a packet telling the client to show a meso gain. + * + * @param gain How many mesos gained. + * @param inChat Show in the chat window? + * @return The meso gain packet. + */ + public static byte[] getShowMesoGain(int gain, boolean inChat) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SHOW_STATUS_INFO.getValue()); + if (!inChat) { + mplew.write(0); + mplew.writeShort(1); //v83 + } else { + mplew.write(5); + } + mplew.writeInt(gain); + mplew.writeShort(0); + return mplew.getPacket(); + } + + /** + * Gets a packet telling the client to show a item gain. + * + * @param itemId The ID of the item gained. + * @param quantity How many items gained. + * @return The item gain packet. + */ + public static byte[] getShowItemGain(int itemId, short quantity) { + return getShowItemGain(itemId, quantity, false); + } + + /** + * Gets a packet telling the client to show an item gain. + * + * @param itemId The ID of the item gained. + * @param quantity The number of items gained. + * @param inChat Show in the chat window? + * @return The item gain packet. + */ + public static byte[] getShowItemGain(int itemId, short quantity, boolean inChat) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + if (inChat) { + mplew.writeShort(SendOpcode.SHOW_ITEM_GAIN_INCHAT.getValue()); + mplew.write(3); + mplew.write(1); + mplew.writeInt(itemId); + mplew.writeInt(quantity); + } else { + mplew.writeShort(SendOpcode.SHOW_STATUS_INFO.getValue()); + mplew.writeShort(0); + mplew.writeInt(itemId); + mplew.writeInt(quantity); + mplew.writeInt(0); + mplew.writeInt(0); + } + return mplew.getPacket(); + } + + public static byte[] killMonster(int oid, boolean animation) { + return killMonster(oid, animation ? 1 : 0); + } + + /** + * Gets a packet telling the client that a monster was killed. + * + * @param oid The objectID of the killed monster. + * @param animation 0 = dissapear, 1 = fade out, 2+ = special + * @return The kill monster packet. + */ + public static byte[] killMonster(int oid, int animation) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.KILL_MONSTER.getValue()); + mplew.writeInt(oid); + mplew.write(animation); + mplew.write(animation); + return mplew.getPacket(); + } + + public static byte[] dropItemFromMapObject(MapleMapItem drop, Point dropfrom, Point dropto, byte mod) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.DROP_ITEM_FROM_MAPOBJECT.getValue()); + mplew.write(mod); + mplew.writeInt(drop.getObjectId()); + mplew.writeBool(drop.getMeso() > 0); // 1 mesos, 0 item, 2 and above all item meso bag, + mplew.writeInt(drop.getItemId()); // drop object ID + mplew.writeInt(drop.getOwner()); // owner charid/paryid :) + mplew.write(drop.getDropType()); // 0 = timeout for non-owner, 1 = timeout for non-owner's party, 2 = FFA, 3 = explosive/FFA + mplew.writePos(dropto); + mplew.writeInt(drop.getDropType() == 0 ? drop.getOwner() : 0); //test + + if (mod != 2) { + mplew.writePos(dropfrom); + mplew.writeShort(0);//Fh? + } + if (drop.getMeso() == 0) { + addExpirationTime(mplew, drop.getItem().getExpiration()); + } + mplew.write(drop.isPlayerDrop() ? 0 : 1); //pet EQP pickup + return mplew.getPacket(); + } + + /** + * Gets a packet spawning a player as a mapobject to other clients. + * + * @param chr The character to spawn to other clients. + * @return The spawn player packet. + */ + public static byte[] spawnPlayerMapobject(MapleCharacter chr) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SPAWN_PLAYER.getValue()); + mplew.writeInt(chr.getId()); + mplew.write(chr.getLevel()); //v83 + mplew.writeMapleAsciiString(chr.getName()); + if (chr.getGuildId() < 1) { + mplew.writeMapleAsciiString(""); + mplew.write(new byte[6]); + } else { + MapleGuildSummary gs = chr.getClient().getWorldServer().getGuildSummary(chr.getGuildId(), chr.getWorld()); + if (gs != null) { + mplew.writeMapleAsciiString(gs.getName()); + mplew.writeShort(gs.getLogoBG()); + mplew.write(gs.getLogoBGColor()); + mplew.writeShort(gs.getLogo()); + mplew.write(gs.getLogoColor()); + } else { + mplew.writeMapleAsciiString(""); + mplew.write(new byte[6]); + } + } + mplew.writeInt(0); + mplew.writeShort(0); //v83 + mplew.write(0xFC); + mplew.write(1); + if (chr.getBuffedValue(MapleBuffStat.MORPH) != null) { + mplew.writeInt(2); + } else { + mplew.writeInt(0); + } + long buffmask = 0; + Integer buffvalue = null; + if (chr.getBuffedValue(MapleBuffStat.DARKSIGHT) != null && !chr.isHidden()) { + buffmask |= MapleBuffStat.DARKSIGHT.getValue(); + } + if (chr.getBuffedValue(MapleBuffStat.COMBO) != null) { + buffmask |= MapleBuffStat.COMBO.getValue(); + buffvalue = Integer.valueOf(chr.getBuffedValue(MapleBuffStat.COMBO).intValue()); + } + if (chr.getBuffedValue(MapleBuffStat.SHADOWPARTNER) != null) { + buffmask |= MapleBuffStat.SHADOWPARTNER.getValue(); + } + if (chr.getBuffedValue(MapleBuffStat.SOULARROW) != null) { + buffmask |= MapleBuffStat.SOULARROW.getValue(); + } + if (chr.getBuffedValue(MapleBuffStat.MORPH) != null) { + buffvalue = Integer.valueOf(chr.getBuffedValue(MapleBuffStat.MORPH).intValue()); + } + if (chr.getBuffedValue(MapleBuffStat.ENERGY_CHARGE) != null) { + buffmask |= MapleBuffStat.ENERGY_CHARGE.getValue(); + buffvalue = Integer.valueOf(chr.getBuffedValue(MapleBuffStat.ENERGY_CHARGE).intValue()); + }//AREN'T THESE + mplew.writeInt((int) ((buffmask >> 32) & 0xffffffffL)); + if (buffvalue != null) { + if (chr.getBuffedValue(MapleBuffStat.MORPH) != null) { //TEST + mplew.writeShort(buffvalue); + } else { + mplew.write(buffvalue.byteValue()); + } + } + mplew.writeInt((int) (buffmask & 0xffffffffL)); + int CHAR_MAGIC_SPAWN = Randomizer.nextInt(); + mplew.skip(6); + mplew.writeInt(CHAR_MAGIC_SPAWN); + mplew.skip(11); + mplew.writeInt(CHAR_MAGIC_SPAWN);//v74 + mplew.skip(11); + mplew.writeInt(CHAR_MAGIC_SPAWN); + mplew.writeShort(0); + mplew.write(0); + final Item mount = chr.getInventory(MapleInventoryType.EQUIPPED).getItem((short) -18); + if (chr.getBuffedValue(MapleBuffStat.MONSTER_RIDING) != null && mount != null) { + mplew.writeInt(mount.getItemId()); + mplew.writeInt(1004); + } else { + mplew.writeLong(0); + } + mplew.writeInt(CHAR_MAGIC_SPAWN); + mplew.skip(9); + mplew.writeInt(CHAR_MAGIC_SPAWN); + mplew.writeShort(0); + mplew.writeInt(0); // actually not 0, why is it 0 then? + mplew.skip(10); + mplew.writeInt(CHAR_MAGIC_SPAWN); + mplew.skip(13); + mplew.writeInt(CHAR_MAGIC_SPAWN); + mplew.writeShort(0); + mplew.write(0); + mplew.writeShort(chr.getJob().getId()); + addCharLook(mplew, chr, false); + mplew.writeInt(chr.getInventory(MapleInventoryType.CASH).countById(5110000)); + mplew.writeInt(chr.getItemEffect()); + mplew.writeInt(ItemConstants.getInventoryType(chr.getChair()) == MapleInventoryType.SETUP ? chr.getChair() : 0); + mplew.writePos(chr.getPosition()); + mplew.write(chr.getStance()); + mplew.writeShort(0);//chr.getFh() + mplew.write(0); + MaplePet[] pet = chr.getPets(); + for (int i = 0; i < 3; i++) { + if (pet[i] != null) { + addPetInfo(mplew, pet[i], false); + } + } + mplew.write(0); //end of pets + if (chr.getMount() == null) { + mplew.writeInt(1); // mob level + mplew.writeLong(0); // mob exp + tiredness + } else { + mplew.writeInt(chr.getMount().getLevel()); + mplew.writeInt(chr.getMount().getExp()); + mplew.writeInt(chr.getMount().getTiredness()); + } + if (chr.getPlayerShop() != null && chr.getPlayerShop().isOwner(chr)) { + if (chr.getPlayerShop().hasFreeSlot()) { + addAnnounceBox(mplew, chr.getPlayerShop(), chr.getPlayerShop().getVisitors().length); + } else { + addAnnounceBox(mplew, chr.getPlayerShop(), 1); + } + } else if (chr.getMiniGame() != null && chr.getMiniGame().isOwner(chr)) { + if (chr.getMiniGame().hasFreeSlot()) { + addAnnounceBox(mplew, chr.getMiniGame(), 1, 0, 1, 0); + } else { + addAnnounceBox(mplew, chr.getMiniGame(), 1, 0, 2, 1); + } + } else { + mplew.write(0); + } + if (chr.getChalkboard() != null) { + mplew.write(1); + mplew.writeMapleAsciiString(chr.getChalkboard()); + } else { + mplew.write(0); + } + addRingLook(mplew, chr, true); + addRingLook(mplew, chr, false); + addMarriageRingLook(mplew, chr); + mplew.skip(3); + mplew.write(chr.getTeam());//only needed in specific fields + return mplew.getPacket(); + } + + private static void addRingLook(final MaplePacketLittleEndianWriter mplew, MapleCharacter chr, boolean crush) { + List rings; + if (crush) { + rings = chr.getCrushRings(); + } else { + rings = chr.getFriendshipRings(); + } + boolean yes = false; + for (MapleRing ring : rings) { + if (ring.equipped()) { + if (yes == false) { + yes = true; + mplew.write(1); + } + mplew.writeInt(ring.getRingId()); + mplew.writeInt(0); + mplew.writeInt(ring.getPartnerRingId()); + mplew.writeInt(0); + mplew.writeInt(ring.getItemId()); + } + } + if (yes == false) { + mplew.write(0); + } + } + + private static void addMarriageRingLook(final MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { + if (chr.getMarriageRing() != null && !chr.getMarriageRing().equipped()) { + mplew.write(0); + return; + } + mplew.writeBool(chr.getMarriageRing() != null); + if (chr.getMarriageRing() != null) { + mplew.writeInt(chr.getId()); + mplew.writeInt(chr.getMarriageRing().getPartnerChrId()); + mplew.writeInt(chr.getMarriageRing().getRingId()); + } + } + + /** + * Adds a announcement box to an existing MaplePacketLittleEndianWriter. + * + * @param mplew The MaplePacketLittleEndianWriter to add an announcement box + * to. + * @param shop The shop to announce. + */ + private static void addAnnounceBox(final MaplePacketLittleEndianWriter mplew, MaplePlayerShop shop, int availability) { + mplew.write(4); + mplew.writeInt(shop.getObjectId()); + mplew.writeMapleAsciiString(shop.getDescription()); + mplew.write(0); + mplew.write(0); + mplew.write(1); + mplew.write(availability); + mplew.write(0); + } + + private static void addAnnounceBox(final MaplePacketLittleEndianWriter mplew, MapleMiniGame game, int gametype, int type, int ammount, int joinable) { + mplew.write(gametype); + mplew.writeInt(game.getObjectId()); // gameid/shopid + mplew.writeMapleAsciiString(game.getDescription()); // desc + mplew.write(0); + mplew.write(type); + mplew.write(ammount); + mplew.write(2); + mplew.write(joinable); + } + + public static byte[] facialExpression(MapleCharacter from, int expression) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(10); + mplew.writeShort(SendOpcode.FACIAL_EXPRESSION.getValue()); + mplew.writeInt(from.getId()); + mplew.writeInt(expression); + return mplew.getPacket(); + } + + private static void serializeMovementList(LittleEndianWriter lew, List moves) { + lew.write(moves.size()); + for (LifeMovementFragment move : moves) { + move.serialize(lew); + } + } + + public static byte[] movePlayer(int cid, List moves) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.MOVE_PLAYER.getValue()); + mplew.writeInt(cid); + mplew.writeInt(0); + serializeMovementList(mplew, moves); + return mplew.getPacket(); + } + + public static byte[] moveSummon(int cid, int oid, Point startPos, List moves) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.MOVE_SUMMON.getValue()); + mplew.writeInt(cid); + mplew.writeInt(oid); + mplew.writePos(startPos); + serializeMovementList(mplew, moves); + return mplew.getPacket(); + } + + public static byte[] moveMonster(int useskill, int skill, int skill_1, int skill_2, int skill_3, int skill_4, int oid, Point startPos, List moves) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.MOVE_MONSTER.getValue()); + mplew.writeInt(oid); + mplew.write(0); + mplew.write(useskill); + mplew.write(skill); + mplew.write(skill_1); + mplew.write(skill_2); + mplew.write(skill_3); + mplew.write(skill_4); + mplew.writePos(startPos); + serializeMovementList(mplew, moves); + return mplew.getPacket(); + } + + public static byte[] summonAttack(int cid, int summonSkillId, byte direction, List allDamage) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + //b2 00 29 f7 00 00 9a a3 04 00 c8 04 01 94 a3 04 00 06 ff 2b 00 + mplew.writeShort(SendOpcode.SUMMON_ATTACK.getValue()); + mplew.writeInt(cid); + mplew.writeInt(summonSkillId); + mplew.write(direction); + mplew.write(4); + mplew.write(allDamage.size()); + for (SummonAttackEntry attackEntry : allDamage) { + mplew.writeInt(attackEntry.getMonsterOid()); // oid + mplew.write(6); // who knows + mplew.writeInt(attackEntry.getDamage()); // damage + } + return mplew.getPacket(); + } + + public static byte[] closeRangeAttack(MapleCharacter chr, int skill, int skilllevel, int stance, int numAttackedAndDamage, Map> damage, int speed, int direction, int display) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.CLOSE_RANGE_ATTACK.getValue()); + addAttackBody(mplew, chr, skill, skilllevel, stance, numAttackedAndDamage, 0, damage, speed, direction, display); + return mplew.getPacket(); + } + + public static byte[] rangedAttack(MapleCharacter chr, int skill, int skilllevel, int stance, int numAttackedAndDamage, int projectile, Map> damage, int speed, int direction, int display) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.RANGED_ATTACK.getValue()); + addAttackBody(mplew, chr, skill, skilllevel, stance, numAttackedAndDamage, projectile, damage, speed, direction, display); + mplew.writeInt(0); + return mplew.getPacket(); + } + + public static byte[] magicAttack(MapleCharacter chr, int skill, int skilllevel, int stance, int numAttackedAndDamage, Map> damage, int charge, int speed, int direction, int display) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.MAGIC_ATTACK.getValue()); + addAttackBody(mplew, chr, skill, skilllevel, stance, numAttackedAndDamage, 0, damage, speed, direction, display); + if (charge != -1) { + mplew.writeInt(charge); + } + return mplew.getPacket(); + } + + private static void addAttackBody(LittleEndianWriter lew, MapleCharacter chr, int skill, int skilllevel, int stance, int numAttackedAndDamage, int projectile, Map> damage, int speed, int direction, int display) { + lew.writeInt(chr.getId()); + lew.write(numAttackedAndDamage); + lew.write(0x5B);//? + lew.write(skilllevel); + if (skilllevel > 0) { + lew.writeInt(skill); + } + lew.write(display); + lew.write(direction); + lew.write(stance); + lew.write(speed); + lew.write(0x0A); + lew.writeInt(projectile); + for (Integer oned : damage.keySet()) { + List onedList = damage.get(oned); + if (onedList != null) { + lew.writeInt(oned.intValue()); + lew.write(0xFF); + if (skill == 4211006) { + lew.write(onedList.size()); + } + for (Integer eachd : onedList) { + lew.writeInt(eachd.intValue()); + } + } + } + } + + private static int doubleToShortBits(double d) { + return (int) (Double.doubleToLongBits(d) >> 48); + } + + public static byte[] getNPCShop(MapleClient c, int sid, List items) { + MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance(); + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.OPEN_NPC_SHOP.getValue()); + mplew.writeInt(sid); + mplew.writeShort(items.size()); // item count + for (MapleShopItem item : items) { + mplew.writeInt(item.getItemId()); + mplew.writeInt(item.getPrice()); + mplew.writeInt(item.getPrice() == 0 ? item.getPitch() : 0); //Perfect Pitch + mplew.writeInt(0); //Can be used x minutes after purchase + mplew.writeInt(0); //Hmm + if (!ItemConstants.isRechargable(item.getItemId())) { + mplew.writeShort(1); // stacksize o.o + mplew.writeShort(item.getBuyable()); + } else { + mplew.writeShort(0); + mplew.writeInt(0); + mplew.writeShort(doubleToShortBits(ii.getPrice(item.getItemId()))); + mplew.writeShort(ii.getSlotMax(c, item.getItemId())); + } + } + return mplew.getPacket(); + } + + /* 00 = / + * 01 = You don't have enough in stock + * 02 = You do not have enough mesos + * 03 = Please check if your inventory is full or not + * 05 = You don't have enough in stock + * 06 = Due to an error, the trade did not happen + * 07 = Due to an error, the trade did not happen + * 08 = / + * 0D = You need more items + * 0E = CRASH; LENGTH NEEDS TO BE LONGER :O + */ + public static byte[] shopTransaction(byte code) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(3); + mplew.writeShort(SendOpcode.CONFIRM_SHOP_TRANSACTION.getValue()); + mplew.write(code); + return mplew.getPacket(); + } + + public static byte[] updateInventorySlotLimit(int type, int newLimit) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.INVENTORY_GROW.getValue()); + mplew.write(type); + mplew.write(newLimit); + return mplew.getPacket(); + } + + public static byte[] modifyInventory(boolean updateTick, final List mods) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.INVENTORY_OPERATION.getValue()); + mplew.writeBool(updateTick); + mplew.write(mods.size()); + //mplew.write(0); v104 :) + int addMovement = -1; + for (ModifyInventory mod : mods) { + mplew.write(mod.getMode()); + mplew.write(mod.getInventoryType()); + mplew.writeShort(mod.getMode() == 2 ? mod.getOldPosition() : mod.getPosition()); + switch (mod.getMode()) { + case 0: {//add item + addItemInfo(mplew, mod.getItem(), true); + break; + } + case 1: {//update quantity + mplew.writeShort(mod.getQuantity()); + break; + } + case 2: {//move + mplew.writeShort(mod.getPosition()); + if (mod.getPosition() < 0 || mod.getOldPosition() < 0) { + addMovement = mod.getOldPosition() < 0 ? 1 : 2; + } + break; + } + case 3: {//remove + if (mod.getPosition() < 0) { + addMovement = 2; + } + break; + } + } + mod.clear(); + } + if (addMovement > -1) { + mplew.write(addMovement); + } + return mplew.getPacket(); + } + + public static byte[] getScrollEffect(int chr, ScrollResult scrollSuccess, boolean legendarySpirit) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SHOW_SCROLL_EFFECT.getValue()); + mplew.writeInt(chr); + switch (scrollSuccess) { + case SUCCESS: + mplew.writeShort(1); + mplew.writeShort(legendarySpirit ? 1 : 0); + break; + case FAIL: + mplew.writeShort(0); + mplew.writeShort(legendarySpirit ? 1 : 0); + break; + case CURSE: + mplew.write(0); + mplew.write(1); + mplew.writeShort(legendarySpirit ? 1 : 0); + break; + } + return mplew.getPacket(); + } + + public static byte[] removePlayerFromMap(int cid) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.REMOVE_PLAYER_FROM_MAP.getValue()); + mplew.writeInt(cid); + return mplew.getPacket(); + } + + /** + * animation: 0 - expire
1 - without animation
2 - pickup
4 - + * explode
cid is ignored for 0 and 1 + * + * @param oid + * @param animation + * @param cid + * @return + */ + public static byte[] removeItemFromMap(int oid, int animation, int cid) { + return removeItemFromMap(oid, animation, cid, false, 0); + } + + /** + * animation: 0 - expire
1 - without animation
2 - pickup
4 - + * explode
cid is ignored for 0 and 1.

Flagging pet as true + * will make a pet pick up the item. + * + * @param oid + * @param animation + * @param cid + * @param pet + * @param slot + * @return + */ + public static byte[] removeItemFromMap(int oid, int animation, int cid, boolean pet, int slot) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.REMOVE_ITEM_FROM_MAP.getValue()); + mplew.write(animation); // expire + mplew.writeInt(oid); + if (animation >= 2) { + mplew.writeInt(cid); + if (pet) { + mplew.write(slot); + } + } + return mplew.getPacket(); + } + + public static byte[] updateCharLook(MapleCharacter chr) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.UPDATE_CHAR_LOOK.getValue()); + mplew.writeInt(chr.getId()); + mplew.write(1); + addCharLook(mplew, chr, false); + addRingLook(mplew, chr, true); + addRingLook(mplew, chr, false); + addMarriageRingLook(mplew, chr); + mplew.writeInt(0); + return mplew.getPacket(); + } + + public static byte[] damagePlayer(int skill, int monsteridfrom, int cid, int damage, int fake, int direction, boolean pgmr, int pgmr_1, boolean is_pg, int oid, int pos_x, int pos_y) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.DAMAGE_PLAYER.getValue()); + mplew.writeInt(cid); + mplew.write(skill); + mplew.writeInt(damage); + mplew.writeInt(monsteridfrom); + mplew.write(direction); + if (pgmr) { + mplew.write(pgmr_1); + mplew.write(is_pg ? 1 : 0); + mplew.writeInt(oid); + mplew.write(6); + mplew.writeShort(pos_x); + mplew.writeShort(pos_y); + mplew.write(0); + } else { + mplew.writeShort(0); + } + mplew.writeInt(damage); + if (fake > 0) { + mplew.writeInt(fake); + } + return mplew.getPacket(); + } + + public static byte[] charNameResponse(String charname, boolean nameUsed) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.CHAR_NAME_RESPONSE.getValue()); + mplew.writeMapleAsciiString(charname); + mplew.write(nameUsed ? 1 : 0); + return mplew.getPacket(); + } + + public static byte[] addNewCharEntry(MapleCharacter chr) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.ADD_NEW_CHAR_ENTRY.getValue()); + mplew.write(0); + addCharEntry(mplew, chr, false); + return mplew.getPacket(); + } + + /** + * state 0 = del ok state 12 = invalid bday state 14 = incorrect pic + * + * @param cid + * @param state + * @return + */ + public static byte[] deleteCharResponse(int cid, int state) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.DELETE_CHAR_RESPONSE.getValue()); + mplew.writeInt(cid); + mplew.write(state); + return mplew.getPacket(); + } + + public static byte[] selectWorld(int world) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.LAST_CONNECTED_WORLD.getValue()); + mplew.writeInt(world);//According to GMS, it should be the world that contains the most characters (most active) + return mplew.getPacket(); + } + + public static byte[] sendRecommended(List> worlds) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.RECOMMENDED_WORLD_MESSAGE.getValue()); + mplew.write(worlds.size());//size + for (Iterator> it = worlds.iterator(); it.hasNext();) { + Pair world = it.next(); + mplew.writeInt(world.getLeft()); + mplew.writeMapleAsciiString(world.getRight()); + } + return mplew.getPacket(); + } + + /** + * + * @param chr + * @param isSelf + * @return + */ + public static byte[] charInfo(MapleCharacter chr) { + //3D 00 0A 43 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.CHAR_INFO.getValue()); + mplew.writeInt(chr.getId()); + mplew.write(chr.getLevel()); + mplew.writeShort(chr.getJob().getId()); + mplew.writeShort(chr.getFame()); + mplew.write(chr.getMarriageRing() != null ? 1 : 0); + String guildName = ""; + String allianceName = ""; + MapleGuildSummary gs = chr.getClient().getWorldServer().getGuildSummary(chr.getGuildId(), chr.getWorld()); + if (chr.getGuildId() > 0 && gs != null) { + guildName = gs.getName(); + MapleAlliance alliance = Server.getInstance().getAlliance(gs.getAllianceId()); + if (alliance != null) { + allianceName = alliance.getName(); + } + } + mplew.writeMapleAsciiString(guildName); + mplew.writeMapleAsciiString(allianceName); + mplew.write(0); + MaplePet[] pets = chr.getPets(); + Item inv = chr.getInventory(MapleInventoryType.EQUIPPED).getItem((short) -114); + for (int i = 0; i < 3; i++) { + if (pets[i] != null) { + mplew.write(pets[i].getUniqueId()); + mplew.writeInt(pets[i].getItemId()); // petid + mplew.writeMapleAsciiString(pets[i].getName()); + mplew.write(pets[i].getLevel()); // pet level + mplew.writeShort(pets[i].getCloseness()); // pet closeness + mplew.write(pets[i].getFullness()); // pet fullness + mplew.writeShort(0); + mplew.writeInt(inv != null ? inv.getItemId() : 0); + } + } + mplew.write(0); //end of pets + if (chr.getMount() != null && chr.getInventory(MapleInventoryType.EQUIPPED).getItem((short) -18) != null) { + mplew.write(chr.getMount().getId()); //mount + mplew.writeInt(chr.getMount().getLevel()); //level + mplew.writeInt(chr.getMount().getExp()); //exp + mplew.writeInt(chr.getMount().getTiredness()); //tiredness + } else { + mplew.write(0); + } + mplew.write(chr.getCashShop().getWishList().size()); + for (int sn : chr.getCashShop().getWishList()) { + mplew.writeInt(sn); + } + mplew.writeInt(chr.getMonsterBook().getBookLevel()); + mplew.writeInt(chr.getMonsterBook().getNormalCard()); + mplew.writeInt(chr.getMonsterBook().getSpecialCard()); + mplew.writeInt(chr.getMonsterBook().getTotalCards()); + mplew.writeInt(chr.getMonsterBookCover() > 0 ? MapleItemInformationProvider.getInstance().getCardMobId(chr.getMonsterBookCover()) : 0); + Item medal = chr.getInventory(MapleInventoryType.EQUIPPED).getItem((short) -49); + if (medal != null) { + mplew.writeInt(medal.getItemId()); + } else { + mplew.writeInt(0); + } + ArrayList medalQuests = new ArrayList<>(); + List completed = chr.getCompletedQuests(); + for (MapleQuestStatus q : completed) { + if (q.getQuest().getId() >= 29000) { // && q.getQuest().getId() <= 29923 + medalQuests.add(q.getQuest().getId()); + } + } + + Collections.sort(medalQuests); + mplew.writeShort(medalQuests.size()); + for (Short s : medalQuests) { + mplew.writeShort(s); + } + return mplew.getPacket(); + } + + /** + * It is important that statups is in the correct order (see decleration + * order in MapleBuffStat) since this method doesn't do automagical + * reordering. + * + * @param buffid + * @param bufflength + * @param statups + * @return + */ + //1F 00 00 00 00 00 03 00 00 40 00 00 00 E0 00 00 00 00 00 00 00 00 E0 01 8E AA 4F 00 00 C2 EB 0B E0 01 8E AA 4F 00 00 C2 EB 0B 0C 00 8E AA 4F 00 00 C2 EB 0B 44 02 8E AA 4F 00 00 C2 EB 0B 44 02 8E AA 4F 00 00 C2 EB 0B 00 00 E0 7A 1D 00 8E AA 4F 00 00 00 00 00 00 00 00 03 + public static byte[] giveBuff(int buffid, int bufflength, List> statups) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.GIVE_BUFF.getValue()); + boolean special = false; + writeLongMask(mplew, statups); + for (Pair statup : statups) { + if (statup.getLeft().equals(MapleBuffStat.MONSTER_RIDING) || statup.getLeft().equals(MapleBuffStat.HOMING_BEACON)) { + special = true; + } + mplew.writeShort(statup.getRight().shortValue()); + mplew.writeInt(buffid); + mplew.writeInt(bufflength); + } + mplew.writeInt(0); + mplew.write(0); + mplew.writeInt(statups.get(0).getRight()); //Homing beacon ... + + if (special) { + mplew.skip(3); + } + return mplew.getPacket(); + } + + /** + * + * @param cid + * @param statups + * @param mount + * @return + */ + public static byte[] showMonsterRiding(int cid, MapleMount mount) { //Gtfo with this, this is just giveForeignBuff + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.GIVE_FOREIGN_BUFF.getValue()); + mplew.writeInt(cid); + mplew.writeLong(MapleBuffStat.MONSTER_RIDING.getValue()); //Thanks? + mplew.writeLong(0); + mplew.writeShort(0); + mplew.writeInt(mount.getItemId()); + mplew.writeInt(mount.getSkillId()); + mplew.writeInt(0); //Server Tick value. + mplew.writeShort(0); + mplew.write(0); //Times you have been buffed + return mplew.getPacket(); + } + /* mplew.writeInt(cid); + writeLongMask(mplew, statups); + for (Pair statup : statups) { + if (morph) { + mplew.writeInt(statup.getRight().intValue()); + } else { + mplew.writeShort(statup.getRight().shortValue()); + } + } + mplew.writeShort(0); + mplew.write(0);*/ + + /** + * + * @param c + * @param quest + * @return + */ + public static byte[] forfeitQuest(short quest) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SHOW_STATUS_INFO.getValue()); + mplew.write(1); + mplew.writeShort(quest); + mplew.write(0); + return mplew.getPacket(); + } + + /** + * + * @param c + * @param quest + * @return + */ + public static byte[] completeQuest(short quest, long time) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SHOW_STATUS_INFO.getValue()); + mplew.write(1); + mplew.writeShort(quest); + mplew.write(2); + mplew.writeLong(time); + return mplew.getPacket(); + } + + /** + * + * @param c + * @param quest + * @param npc + * @param progress + * @return + */ + public static byte[] updateQuestInfo(short quest, int npc) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.UPDATE_QUEST_INFO.getValue()); + mplew.write(8); //0x0A in v95 + mplew.writeShort(quest); + mplew.writeInt(npc); + mplew.writeInt(0); + return mplew.getPacket(); + } + + public static byte[] addQuestTimeLimit(final short quest, final int time) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.UPDATE_QUEST_INFO.getValue()); + mplew.write(6); + mplew.writeShort(1);//Size but meh, when will there be 2 at the same time? And it won't even replace the old one :) + mplew.writeShort(quest); + mplew.writeInt(time); + return mplew.getPacket(); + } + + public static byte[] removeQuestTimeLimit(final short quest) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.UPDATE_QUEST_INFO.getValue()); + mplew.write(7); + mplew.writeShort(1);//Position + mplew.writeShort(quest); + return mplew.getPacket(); + } + + public static byte[] updateQuest(MapleQuestStatus q, boolean infoUpdate) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SHOW_STATUS_INFO.getValue()); + mplew.write(1); + mplew.writeShort(infoUpdate ? q.getQuest().getInfoNumber() : q.getQuest().getId()); + if (infoUpdate) { + mplew.write(1); + } else { + mplew.write(q.getStatus().getId()); + } + + mplew.writeMapleAsciiString(q.getQuestData()); + return mplew.getPacket(); + } + + private static void writeLongMaskD(final MaplePacketLittleEndianWriter mplew, List> statups) { + long firstmask = 0; + long secondmask = 0; + for (Pair statup : statups) { + if (statup.getLeft().isFirst()) { + firstmask |= statup.getLeft().getValue(); + } else { + secondmask |= statup.getLeft().getValue(); + } + } + mplew.writeLong(firstmask); + mplew.writeLong(secondmask); + } + + public static byte[] giveDebuff(List> statups, MobSkill skill) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.GIVE_BUFF.getValue()); + writeLongMaskD(mplew, statups); + for (Pair statup : statups) { + mplew.writeShort(statup.getRight().shortValue()); + mplew.writeShort(skill.getSkillId()); + mplew.writeShort(skill.getSkillLevel()); + mplew.writeInt((int) skill.getDuration()); + } + mplew.writeShort(0); // ??? wk charges have 600 here o.o + mplew.writeShort(900);//Delay + mplew.write(1); + return mplew.getPacket(); + } + + public static byte[] giveForeignDebuff(int cid, List> statups, MobSkill skill) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.GIVE_FOREIGN_BUFF.getValue()); + mplew.writeInt(cid); + writeLongMaskD(mplew, statups); + for (int i = 0; i < statups.size(); i++) { + mplew.writeShort(skill.getSkillId()); + mplew.writeShort(skill.getSkillLevel()); + } + mplew.writeShort(0); // same as give_buff + mplew.writeShort(900);//Delay + return mplew.getPacket(); + } + + public static byte[] cancelForeignDebuff(int cid, long mask) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.CANCEL_FOREIGN_BUFF.getValue()); + mplew.writeInt(cid); + mplew.writeLong(0); + mplew.writeLong(mask); + return mplew.getPacket(); + } + + public static byte[] giveForeignBuff(int cid, List> statups) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.GIVE_FOREIGN_BUFF.getValue()); + mplew.writeInt(cid); + writeLongMask(mplew, statups); + for (Pair statup : statups) { + mplew.writeShort(statup.getRight().shortValue()); + } + mplew.writeInt(0); + mplew.writeShort(0); + return mplew.getPacket(); + } + + public static byte[] cancelForeignBuff(int cid, List statups) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.CANCEL_FOREIGN_BUFF.getValue()); + mplew.writeInt(cid); + writeLongMaskFromList(mplew, statups); + return mplew.getPacket(); + } + + public static byte[] cancelBuff(List statups) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.CANCEL_BUFF.getValue()); + writeLongMaskFromList(mplew, statups); + mplew.write(1);//? + return mplew.getPacket(); + } + + private static void writeLongMask(final MaplePacketLittleEndianWriter mplew, List> statups) { + long firstmask = 0; + long secondmask = 0; + for (Pair statup : statups) { + if (statup.getLeft().isFirst()) { + firstmask |= statup.getLeft().getValue(); + } else { + secondmask |= statup.getLeft().getValue(); + } + } + mplew.writeLong(firstmask); + mplew.writeLong(secondmask); + } + + private static void writeLongMaskFromList(final MaplePacketLittleEndianWriter mplew, List statups) { + long firstmask = 0; + long secondmask = 0; + for (MapleBuffStat statup : statups) { + if (statup.isFirst()) { + firstmask |= statup.getValue(); + } else { + secondmask |= statup.getValue(); + } + } + mplew.writeLong(firstmask); + mplew.writeLong(secondmask); + } + + public static byte[] cancelDebuff(long mask) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(19); + mplew.writeShort(SendOpcode.CANCEL_BUFF.getValue()); + mplew.writeLong(0); + mplew.writeLong(mask); + mplew.write(0); + return mplew.getPacket(); + } + + public static byte[] getPlayerShopChat(MapleCharacter c, String chat, boolean owner) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); + mplew.write(PlayerInteractionHandler.Action.CHAT.getCode()); + mplew.write(PlayerInteractionHandler.Action.CHAT_THING.getCode()); + mplew.write(owner ? 0 : 1); + mplew.writeMapleAsciiString(c.getName() + " : " + chat); + return mplew.getPacket(); + } + + public static byte[] getPlayerShopNewVisitor(MapleCharacter c, int slot) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); + mplew.write(PlayerInteractionHandler.Action.VISIT.getCode()); + mplew.write(slot); + addCharLook(mplew, c, false); + mplew.writeMapleAsciiString(c.getName()); + return mplew.getPacket(); + } + + public static byte[] getPlayerShopRemoveVisitor(int slot) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(4); + mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); + mplew.write(PlayerInteractionHandler.Action.EXIT.getCode()); + if (slot > 0) { + mplew.write(slot); + } + return mplew.getPacket(); + } + + public static byte[] getTradePartnerAdd(MapleCharacter c) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); + mplew.write(PlayerInteractionHandler.Action.VISIT.getCode()); + mplew.write(1); + addCharLook(mplew, c, false); + mplew.writeMapleAsciiString(c.getName()); + return mplew.getPacket(); + } + + public static byte[] getTradeInvite(MapleCharacter c) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); + mplew.write(PlayerInteractionHandler.Action.INVITE.getCode()); + mplew.write(3); + mplew.writeMapleAsciiString(c.getName()); + mplew.write(new byte[]{(byte) 0xB7, (byte) 0x50, 0, 0}); + return mplew.getPacket(); + } + + public static byte[] getTradeMesoSet(byte number, int meso) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(8); + mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); + mplew.write(PlayerInteractionHandler.Action.SET_MESO.getCode()); + mplew.write(number); + mplew.writeInt(meso); + return mplew.getPacket(); + } + + public static byte[] getTradeItemAdd(byte number, Item item) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); + mplew.write(PlayerInteractionHandler.Action.SET_ITEMS.getCode()); + mplew.write(number); + mplew.write(item.getPosition()); + addItemInfo(mplew, item, true); + return mplew.getPacket(); + } + + public static byte[] getPlayerShopItemUpdate(MaplePlayerShop shop) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); + mplew.write(PlayerInteractionHandler.Action.UPDATE_MERCHANT.getCode()); + mplew.write(shop.getItems().size()); + for (MaplePlayerShopItem item : shop.getItems()) { + mplew.writeShort(item.getBundles()); + mplew.writeShort(item.getItem().getQuantity()); + mplew.writeInt(item.getPrice()); + addItemInfo(mplew, item.getItem(), true); + } + return mplew.getPacket(); + } + + /** + * + * @param c + * @param shop + * @param owner + * @return + */ + public static byte[] getPlayerShop(MapleClient c, MaplePlayerShop shop, boolean owner) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); + mplew.write(PlayerInteractionHandler.Action.ROOM.getCode()); + mplew.write(4); + mplew.write(4); + mplew.write(owner ? 0 : 1); + mplew.write(0); + addCharLook(mplew, shop.getOwner(), false); + mplew.writeMapleAsciiString(shop.getOwner().getName()); + mplew.write(1); + addCharLook(mplew, shop.getOwner(), false); + mplew.writeMapleAsciiString(shop.getOwner().getName()); + mplew.write(0xFF); + mplew.writeMapleAsciiString(shop.getDescription()); + List items = shop.getItems(); + mplew.write(0x10); + mplew.write(items.size()); + for (MaplePlayerShopItem item : items) { + mplew.writeShort(item.getBundles()); + mplew.writeShort(item.getItem().getQuantity()); + mplew.writeInt(item.getPrice()); + addItemInfo(mplew, item.getItem(), true); + } + return mplew.getPacket(); + } + + public static byte[] getTradeStart(MapleClient c, MapleTrade trade, byte number) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); + mplew.write(PlayerInteractionHandler.Action.ROOM.getCode()); + mplew.write(3); + mplew.write(2); + mplew.write(number); + if (number == 1) { + mplew.write(0); + addCharLook(mplew, trade.getPartner().getChr(), false); + mplew.writeMapleAsciiString(trade.getPartner().getChr().getName()); + } + mplew.write(number); + addCharLook(mplew, c.getPlayer(), false); + mplew.writeMapleAsciiString(c.getPlayer().getName()); + mplew.write(0xFF); + return mplew.getPacket(); + } + + public static byte[] getTradeConfirmation() { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(3); + mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); + mplew.write(PlayerInteractionHandler.Action.CONFIRM.getCode()); + return mplew.getPacket(); + } + + public static byte[] getTradeCompletion(byte number) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(5); + mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); + mplew.write(PlayerInteractionHandler.Action.EXIT.getCode()); + mplew.write(number); + mplew.write(6); + return mplew.getPacket(); + } + + public static byte[] getTradeCancel(byte number) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(5); + mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); + mplew.write(PlayerInteractionHandler.Action.EXIT.getCode()); + mplew.write(number); + mplew.write(2); + return mplew.getPacket(); + } + + public static byte[] addCharBox(MapleCharacter c, int type) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.UPDATE_CHAR_BOX.getValue()); + mplew.writeInt(c.getId()); + addAnnounceBox(mplew, c.getPlayerShop(), type); + return mplew.getPacket(); + } + + public static byte[] removeCharBox(MapleCharacter c) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(7); + mplew.writeShort(SendOpcode.UPDATE_CHAR_BOX.getValue()); + mplew.writeInt(c.getId()); + mplew.write(0); + return mplew.getPacket(); + } + + /** + * Possible values for speaker:
0: Npc talking (left)
+ * 1: Npc talking (right)
2: Player talking (left)
3: Player talking + * (left)
+ * + * @param npc Npcid + * @param msgType + * @param talk + * @param endBytes + * @param speaker + * @return + */ + public static byte[] getNPCTalk(int npc, byte msgType, String talk, String endBytes, byte speaker) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.NPC_TALK.getValue()); + mplew.write(4); // ? + mplew.writeInt(npc); + mplew.write(msgType); + mplew.write(speaker); + mplew.writeMapleAsciiString(talk); + mplew.write(HexTool.getByteArrayFromHexString(endBytes)); + return mplew.getPacket(); + } + + public static byte[] getDimensionalMirror(String talk) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.NPC_TALK.getValue()); + mplew.write(4); // ? + mplew.writeInt(9010022); + mplew.write(0x0E); + mplew.write(0); + mplew.writeInt(0); + mplew.writeMapleAsciiString(talk); + return mplew.getPacket(); + } + + public static byte[] getNPCTalkStyle(int npc, String talk, int styles[]) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.NPC_TALK.getValue()); + mplew.write(4); // ? + mplew.writeInt(npc); + mplew.write(7); + mplew.write(0); //speaker + mplew.writeMapleAsciiString(talk); + mplew.write(styles.length); + for (int i = 0; i < styles.length; i++) { + mplew.writeInt(styles[i]); + } + return mplew.getPacket(); + } + + public static byte[] getNPCTalkNum(int npc, String talk, int def, int min, int max) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.NPC_TALK.getValue()); + mplew.write(4); // ? + mplew.writeInt(npc); + mplew.write(3); + mplew.write(0); //speaker + mplew.writeMapleAsciiString(talk); + mplew.writeInt(def); + mplew.writeInt(min); + mplew.writeInt(max); + mplew.writeInt(0); + return mplew.getPacket(); + } + + public static byte[] getNPCTalkText(int npc, String talk, String def) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.NPC_TALK.getValue()); + mplew.write(4); // Doesn't matter + mplew.writeInt(npc); + mplew.write(2); + mplew.write(0); //speaker + mplew.writeMapleAsciiString(talk); + mplew.writeMapleAsciiString(def);//:D + mplew.writeInt(0); + return mplew.getPacket(); + } + + public static byte[] showBuffeffect(int cid, int skillid, int effectid) { + return showBuffeffect(cid, skillid, effectid, (byte) 3); + } + + public static byte[] showBuffeffect(int cid, int skillid, int effectid, byte direction) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SHOW_FOREIGN_EFFECT.getValue()); + mplew.writeInt(cid); + mplew.write(effectid); //buff level + mplew.writeInt(skillid); + mplew.write(direction); + mplew.write(1); + mplew.writeLong(0); + return mplew.getPacket(); + } + + public static byte[] showOwnBuffEffect(int skillid, int effectid) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SHOW_ITEM_GAIN_INCHAT.getValue()); + mplew.write(effectid); + mplew.writeInt(skillid); + mplew.write(0xA9); + mplew.write(1); + return mplew.getPacket(); + } + + public static byte[] showOwnBerserk(int skilllevel, boolean Berserk) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SHOW_ITEM_GAIN_INCHAT.getValue()); + mplew.write(1); + mplew.writeInt(1320006); + mplew.write(0xA9); + mplew.write(skilllevel); + mplew.write(Berserk ? 1 : 0); + return mplew.getPacket(); + } + + public static byte[] showBerserk(int cid, int skilllevel, boolean Berserk) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SHOW_FOREIGN_EFFECT.getValue()); + mplew.writeInt(cid); + mplew.write(1); + mplew.writeInt(1320006); + mplew.write(0xA9); + mplew.write(skilllevel); + mplew.write(Berserk ? 1 : 0); + return mplew.getPacket(); + } + + public static byte[] updateSkill(int skillid, int level, int masterlevel, long expiration) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.UPDATE_SKILLS.getValue()); + mplew.write(1); + mplew.writeShort(1); + mplew.writeInt(skillid); + mplew.writeInt(level); + mplew.writeInt(masterlevel); + addExpirationTime(mplew, expiration); + mplew.write(4); + return mplew.getPacket(); + } + + public static byte[] getShowQuestCompletion(int id) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.QUEST_CLEAR.getValue()); + mplew.writeShort(id); + return mplew.getPacket(); + } + + public static byte[] getKeymap(Map keybindings) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.KEYMAP.getValue()); + mplew.write(0); + for (int x = 0; x < 90; x++) { + MapleKeyBinding binding = keybindings.get(Integer.valueOf(x)); + if (binding != null) { + mplew.write(binding.getType()); + mplew.writeInt(binding.getAction()); + } else { + mplew.write(0); + mplew.writeInt(0); + } + } + return mplew.getPacket(); + } + + public static byte[] getWhisper(String sender, int channel, String text) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.WHISPER.getValue()); + mplew.write(0x12); + mplew.writeMapleAsciiString(sender); + mplew.writeShort(channel - 1); // I guess this is the channel + mplew.writeMapleAsciiString(text); + return mplew.getPacket(); + } + + /** + * + * @param target name of the target character + * @param reply error code: 0x0 = cannot find char, 0x1 = success + * @return the MaplePacket + */ + public static byte[] getWhisperReply(String target, byte reply) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.WHISPER.getValue()); + mplew.write(0x0A); // whisper? + mplew.writeMapleAsciiString(target); + mplew.write(reply); + return mplew.getPacket(); + } + + public static byte[] getInventoryFull() { + return modifyInventory(true, Collections.emptyList()); + } + + public static byte[] getShowInventoryFull() { + return getShowInventoryStatus(0xff); + } + + public static byte[] showItemUnavailable() { + return getShowInventoryStatus(0xfe); + } + + public static byte[] getShowInventoryStatus(int mode) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SHOW_STATUS_INFO.getValue()); + mplew.write(0); + mplew.write(mode); + mplew.writeInt(0); + mplew.writeInt(0); + return mplew.getPacket(); + } + + public static byte[] getStorage(int npcId, byte slots, Collection items, int meso) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.STORAGE.getValue()); + mplew.write(0x16); + mplew.writeInt(npcId); + mplew.write(slots); + mplew.writeShort(0x7E); + mplew.writeShort(0); + mplew.writeInt(0); + mplew.writeInt(meso); + mplew.writeShort(0); + mplew.write((byte) items.size()); + for (Item item : items) { + addItemInfo(mplew, item, true); + } + mplew.writeShort(0); + mplew.write(0); + return mplew.getPacket(); + } + + /* + * 0x0A = Inv full + * 0x0B = You do not have enough mesos + * 0x0C = One-Of-A-Kind error + */ + public static byte[] getStorageError(byte i) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.STORAGE.getValue()); + mplew.write(i); + return mplew.getPacket(); + } + + public static byte[] mesoStorage(byte slots, int meso) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.STORAGE.getValue()); + mplew.write(0x13); + mplew.write(slots); + mplew.writeShort(2); + mplew.writeShort(0); + mplew.writeInt(0); + mplew.writeInt(meso); + return mplew.getPacket(); + } + + public static byte[] storeStorage(byte slots, MapleInventoryType type, Collection items) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.STORAGE.getValue()); + mplew.write(0xD); + mplew.write(slots); + mplew.writeShort(type.getBitfieldEncoding()); + mplew.writeShort(0); + mplew.writeInt(0); + mplew.write(items.size()); + for (Item item : items) { + addItemInfo(mplew, item, true); + } + return mplew.getPacket(); + } + + public static byte[] takeOutStorage(byte slots, MapleInventoryType type, Collection items) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.STORAGE.getValue()); + mplew.write(0x9); + mplew.write(slots); + mplew.writeShort(type.getBitfieldEncoding()); + mplew.writeShort(0); + mplew.writeInt(0); + mplew.write(items.size()); + for (Item item : items) { + addItemInfo(mplew, item, true); + } + return mplew.getPacket(); + } + + /** + * + * @param oid + * @param remhppercentage + * @return + */ + public static byte[] showMonsterHP(int oid, int remhppercentage) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SHOW_MONSTER_HP.getValue()); + mplew.writeInt(oid); + mplew.write(remhppercentage); + return mplew.getPacket(); + } + + public static byte[] showBossHP(int oid, int currHP, int maxHP, byte tagColor, byte tagBgColor) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.FIELD_EFFECT.getValue()); + mplew.write(5); + mplew.writeInt(oid); + mplew.writeInt(currHP); + mplew.writeInt(maxHP); + mplew.write(tagColor); + mplew.write(tagBgColor); + return mplew.getPacket(); + } + + public static byte[] giveFameResponse(int mode, String charname, int newfame) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.FAME_RESPONSE.getValue()); + mplew.write(0); + mplew.writeMapleAsciiString(charname); + mplew.write(mode); + mplew.writeShort(newfame); + mplew.writeShort(0); + return mplew.getPacket(); + } + + /** + * status can be:
0: ok, use giveFameResponse
1: the username is + * incorrectly entered
2: users under level 15 are unable to toggle with + * fame.
3: can't raise or drop fame anymore today.
4: can't raise + * or drop fame for this character for this month anymore.
5: received + * fame, use receiveFame()
6: level of fame neither has been raised nor + * dropped due to an unexpected error + * + * @param status + * @return + */ + public static byte[] giveFameErrorResponse(int status) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.FAME_RESPONSE.getValue()); + mplew.write(status); + return mplew.getPacket(); + } + + public static byte[] receiveFame(int mode, String charnameFrom) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.FAME_RESPONSE.getValue()); + mplew.write(5); + mplew.writeMapleAsciiString(charnameFrom); + mplew.write(mode); + return mplew.getPacket(); + } + + public static byte[] partyCreated(MaplePartyCharacter partychar) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.PARTY_OPERATION.getValue()); + mplew.write(8); + mplew.writeShort(0x8b); + mplew.writeShort(1); + if (partychar.getDoors().size() > 0) { + for (MapleDoor doors : partychar.getDoors()) { + mplew.writeInt(doors.getTown().getId()); + mplew.writeInt(doors.getTarget().getId()); + mplew.writeInt(doors.getPosition().x); + mplew.writeInt(doors.getPosition().y); + } + } else { + mplew.writeInt(999999999); + mplew.writeInt(999999999); + mplew.writeInt(0); + mplew.writeInt(0); + } + return mplew.getPacket(); + } + + public static byte[] partyInvite(MapleCharacter from) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.PARTY_OPERATION.getValue()); + mplew.write(4); + mplew.writeInt(from.getParty().getId()); + mplew.writeMapleAsciiString(from.getName()); + mplew.write(0); + return mplew.getPacket(); + } + + /** + * 10: A beginner can't create a party. 1/11/14/19: Your request for a party + * didn't work due to an unexpected error. 13: You have yet to join a party. + * 16: Already have joined a party. 17: The party you're trying to join is + * already in full capacity. 19: Unable to find the requested character in + * this channel. + * + * @param message + * @return + */ + public static byte[] partyStatusMessage(int message) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.PARTY_OPERATION.getValue()); + mplew.write(message); + return mplew.getPacket(); + } + + /** + * 23: 'Char' have denied request to the party. + * + * @param message + * @param charname + * @return + */ + public static byte[] partyStatusMessage(int message, String charname) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.PARTY_OPERATION.getValue()); + mplew.write(message); + mplew.writeMapleAsciiString(charname); + return mplew.getPacket(); + } + + private static void addPartyStatus(int forchannel, MapleParty party, LittleEndianWriter lew, boolean leaving) { + List partymembers = new ArrayList<>(party.getMembers()); + while (partymembers.size() < 6) { + partymembers.add(new MaplePartyCharacter()); + } + for (MaplePartyCharacter partychar : partymembers) { + lew.writeInt(partychar.getId()); + } + for (MaplePartyCharacter partychar : partymembers) { + lew.writeAsciiString(getRightPaddedStr(partychar.getName(), '\0', 13)); + } + for (MaplePartyCharacter partychar : partymembers) { + lew.writeInt(partychar.getJobId()); + } + for (MaplePartyCharacter partychar : partymembers) { + lew.writeInt(partychar.getLevel()); + } + for (MaplePartyCharacter partychar : partymembers) { + if (partychar.isOnline()) { + lew.writeInt(partychar.getChannel() - 1); + } else { + lew.writeInt(-2); + } + } + lew.writeInt(party.getLeader().getId()); + for (MaplePartyCharacter partychar : partymembers) { + if (partychar.getChannel() == forchannel) { + lew.writeInt(partychar.getMapId()); + } else { + lew.writeInt(0); + } + } + for (MaplePartyCharacter partychar : partymembers) { + if (partychar.getChannel() == forchannel && !leaving) { + if (partychar.getDoors().size() > 0) { + for (MapleDoor doors : partychar.getDoors()) { + lew.writeInt(doors.getTown().getId()); + lew.writeInt(doors.getTarget().getId()); + lew.writeInt(doors.getPosition().x); + lew.writeInt(doors.getPosition().y); + } + } else { + lew.writeInt(999999999); + lew.writeInt(999999999); + lew.writeInt(0); + lew.writeInt(0); + } + } else { + lew.writeInt(999999999); + lew.writeInt(999999999); + lew.writeInt(0); + lew.writeInt(0); + } + } + } + + public static byte[] updateParty(int forChannel, MapleParty party, PartyOperation op, MaplePartyCharacter target) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.PARTY_OPERATION.getValue()); + switch (op) { + case DISBAND: + case EXPEL: + case LEAVE: + mplew.write(0x0C); + mplew.writeInt(40546); + mplew.writeInt(target.getId()); + if (op == PartyOperation.DISBAND) { + mplew.write(0); + mplew.writeInt(party.getId()); + } else { + mplew.write(1); + if (op == PartyOperation.EXPEL) { + mplew.write(1); + } else { + mplew.write(0); + } + mplew.writeMapleAsciiString(target.getName()); + addPartyStatus(forChannel, party, mplew, false); + } + break; + case JOIN: + mplew.write(0xF); + mplew.writeInt(40546); + mplew.writeMapleAsciiString(target.getName()); + addPartyStatus(forChannel, party, mplew, false); + break; + case SILENT_UPDATE: + case LOG_ONOFF: + mplew.write(0x7); + mplew.writeInt(party.getId()); + addPartyStatus(forChannel, party, mplew, false); + break; + case CHANGE_LEADER: + mplew.write(0x1B); + mplew.writeInt(target.getId()); + mplew.write(0); + break; + } + return mplew.getPacket(); + } + + public static byte[] partyPortal(int townId, int targetId, Point position) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.PARTY_OPERATION.getValue()); + mplew.writeShort(0x23); + mplew.writeInt(townId); + mplew.writeInt(targetId); + mplew.writePos(position); + return mplew.getPacket(); + } + + public static byte[] updatePartyMemberHP(int cid, int curhp, int maxhp) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.UPDATE_PARTYMEMBER_HP.getValue()); + mplew.writeInt(cid); + mplew.writeInt(curhp); + mplew.writeInt(maxhp); + return mplew.getPacket(); + } + + /** + * mode: 0 buddychat; 1 partychat; 2 guildchat + * + * @param name + * @param chattext + * @param mode + * @return + */ + public static byte[] multiChat(String name, String chattext, int mode) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.MULTICHAT.getValue()); + mplew.write(mode); + mplew.writeMapleAsciiString(name); + mplew.writeMapleAsciiString(chattext); + return mplew.getPacket(); + } + + private static void writeIntMask(final MaplePacketLittleEndianWriter mplew, Map stats) { + int firstmask = 0; + int secondmask = 0; + for (MonsterStatus stat : stats.keySet()) { + if (stat.isFirst()) { + firstmask |= stat.getValue(); + } else { + secondmask |= stat.getValue(); + } + } + mplew.writeInt(firstmask); + mplew.writeInt(secondmask); + } + + public static byte[] applyMonsterStatus(final int oid, final MonsterStatusEffect mse, final List reflection) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.APPLY_MONSTER_STATUS.getValue()); + mplew.writeInt(oid); + mplew.writeLong(0); + writeIntMask(mplew, mse.getStati()); + for (Map.Entry stat : mse.getStati().entrySet()) { + mplew.writeShort(stat.getValue()); + if (mse.isMonsterSkill()) { + mplew.writeShort(mse.getMobSkill().getSkillId()); + mplew.writeShort(mse.getMobSkill().getSkillLevel()); + } else { + mplew.writeInt(mse.getSkill().getId()); + } + mplew.writeShort(-1); // might actually be the buffTime but it's not displayed anywhere + } + int size = mse.getStati().size(); // size + if (reflection != null) { + for (Integer ref : reflection) { + mplew.writeInt(ref); + } + if (reflection.size() > 0) { + size /= 2; // This gives 2 buffs per reflection but it's really one buff + } + } + mplew.write(size); // size + mplew.writeInt(0); + return mplew.getPacket(); + } + + public static byte[] cancelMonsterStatus(int oid, Map stats) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.CANCEL_MONSTER_STATUS.getValue()); + mplew.writeInt(oid); + mplew.writeLong(0); + writeIntMask(mplew, stats); + mplew.writeInt(0); + return mplew.getPacket(); + } + + public static byte[] getClock(int time) { // time in seconds + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.CLOCK.getValue()); + mplew.write(2); // clock type. if you send 3 here you have to send another byte (which does not matter at all) before the timestamp + mplew.writeInt(time); + return mplew.getPacket(); + } + + public static byte[] getClockTime(int hour, int min, int sec) { // Current Time + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.CLOCK.getValue()); + mplew.write(1); //Clock-Type + mplew.write(hour); + mplew.write(min); + mplew.write(sec); + return mplew.getPacket(); + } + + public static byte[] removeClock() { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.STOP_CLOCK.getValue()); + mplew.write(0); + return mplew.getPacket(); + } + + public static byte[] spawnMist(int oid, int ownerCid, int skill, int level, MapleMist mist) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SPAWN_MIST.getValue()); + mplew.writeInt(oid); + mplew.writeInt(mist.isMobMist() ? 0 : mist.isPoisonMist() ? 1 : mist.isRecoveryMist() ? 4 : 2); // mob mist = 0, player poison = 1, smokescreen = 2, unknown = 3, recovery = 4 + mplew.writeInt(ownerCid); + mplew.writeInt(skill); + mplew.write(level); + mplew.writeShort(mist.getSkillDelay()); // Skill delay + mplew.writeInt(mist.getBox().x); + mplew.writeInt(mist.getBox().y); + mplew.writeInt(mist.getBox().x + mist.getBox().width); + mplew.writeInt(mist.getBox().y + mist.getBox().height); + mplew.writeInt(0); + return mplew.getPacket(); + } + + public static byte[] removeMist(int oid) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.REMOVE_MIST.getValue()); + mplew.writeInt(oid); + return mplew.getPacket(); + } + + public static byte[] damageSummon(int cid, int summonSkillId, int damage, int unkByte, int monsterIdFrom) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.DAMAGE_SUMMON.getValue()); + mplew.writeInt(cid); + mplew.writeInt(summonSkillId); + mplew.write(unkByte); + mplew.writeInt(damage); + mplew.writeInt(monsterIdFrom); + mplew.write(0); + return mplew.getPacket(); + } + + public static byte[] damageMonster(int oid, int damage) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.DAMAGE_MONSTER.getValue()); + mplew.writeInt(oid); + mplew.write(0); + mplew.writeInt(damage); + mplew.write(0); + mplew.write(0); + mplew.write(0); + return mplew.getPacket(); + } + + public static byte[] healMonster(int oid, int heal) { + return damageMonster(oid, -heal); + } + + public static byte[] updateBuddylist(Collection buddylist) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.BUDDYLIST.getValue()); + mplew.write(7); + mplew.write(buddylist.size()); + for (BuddylistEntry buddy : buddylist) { + if (buddy.isVisible()) { + mplew.writeInt(buddy.getCharacterId()); // cid + mplew.writeAsciiString(getRightPaddedStr(buddy.getName(), '\0', 13)); + mplew.write(0); // opposite status + mplew.writeInt(buddy.getChannel() - 1); + mplew.writeAsciiString(getRightPaddedStr(buddy.getGroup(), '\0', 13)); + mplew.writeInt(0);//mapid? + } + } + for (int x = 0; x < buddylist.size(); x++) { + mplew.writeInt(0);//mapid? + } + return mplew.getPacket(); + } + + public static byte[] buddylistMessage(byte message) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.BUDDYLIST.getValue()); + mplew.write(message); + return mplew.getPacket(); + } + + public static byte[] requestBuddylistAdd(int cidFrom, int cid, String nameFrom) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.BUDDYLIST.getValue()); + mplew.write(9); + mplew.writeInt(cidFrom); + mplew.writeMapleAsciiString(nameFrom); + mplew.writeInt(cidFrom); + mplew.writeAsciiString(getRightPaddedStr(nameFrom, '\0', 11)); + mplew.write(0x09); + mplew.write(0xf0); + mplew.write(0x01); + mplew.writeInt(0x0f); + mplew.writeNullTerminatedAsciiString("Default Group"); + mplew.writeInt(cid); + return mplew.getPacket(); + } + + public static byte[] updateBuddyChannel(int characterid, int channel) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.BUDDYLIST.getValue()); + mplew.write(0x14); + mplew.writeInt(characterid); + mplew.write(0); + mplew.writeInt(channel); + return mplew.getPacket(); + } + + public static byte[] itemEffect(int characterid, int itemid) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SHOW_ITEM_EFFECT.getValue()); + mplew.writeInt(characterid); + mplew.writeInt(itemid); + return mplew.getPacket(); + } + + public static byte[] updateBuddyCapacity(int capacity) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.BUDDYLIST.getValue()); + mplew.write(0x15); + mplew.write(capacity); + return mplew.getPacket(); + } + + public static byte[] showChair(int characterid, int itemid) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SHOW_CHAIR.getValue()); + mplew.writeInt(characterid); + mplew.writeInt(itemid); + return mplew.getPacket(); + } + + public static byte[] cancelChair(int id) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.CANCEL_CHAIR.getValue()); + if (id == -1) { + mplew.write(0); + } else { + mplew.write(1); + mplew.writeShort(id); + } + return mplew.getPacket(); + } + + // is there a way to spawn reactors non-animated? + public static byte[] spawnReactor(MapleReactor reactor) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + Point pos = reactor.getPosition(); + mplew.writeShort(SendOpcode.REACTOR_SPAWN.getValue()); + mplew.writeInt(reactor.getObjectId()); + mplew.writeInt(reactor.getId()); + mplew.write(reactor.getState()); + mplew.writePos(pos); + mplew.writeShort(0); + mplew.write(0); + return mplew.getPacket(); + } + + public static byte[] triggerReactor(MapleReactor reactor, int stance) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + Point pos = reactor.getPosition(); + mplew.writeShort(SendOpcode.REACTOR_HIT.getValue()); + mplew.writeInt(reactor.getObjectId()); + mplew.write(reactor.getState()); + mplew.writePos(pos); + mplew.writeShort(stance); + mplew.write(0); + mplew.write(5); // frame delay, set to 5 since there doesn't appear to be a fixed formula for it + return mplew.getPacket(); + } + + public static byte[] destroyReactor(MapleReactor reactor) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + Point pos = reactor.getPosition(); + mplew.writeShort(SendOpcode.REACTOR_DESTROY.getValue()); + mplew.writeInt(reactor.getObjectId()); + mplew.write(reactor.getState()); + mplew.writePos(pos); + return mplew.getPacket(); + } + + public static byte[] musicChange(String song) { + return environmentChange(song, 6); + } + + public static byte[] showEffect(String effect) { + return environmentChange(effect, 3); + } + + public static byte[] playSound(String sound) { + return environmentChange(sound, 4); + } + + public static byte[] environmentChange(String env, int mode) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.FIELD_EFFECT.getValue()); + mplew.write(mode); + mplew.writeMapleAsciiString(env); + return mplew.getPacket(); + } + + public static byte[] startMapEffect(String msg, int itemid, boolean active) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.BLOW_WEATHER.getValue()); + mplew.write(active ? 0 : 1); + mplew.writeInt(itemid); + if (active) { + mplew.writeMapleAsciiString(msg); + } + return mplew.getPacket(); + } + + public static byte[] removeMapEffect() { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.BLOW_WEATHER.getValue()); + mplew.write(0); + mplew.writeInt(0); + return mplew.getPacket(); + } + + public static byte[] mapEffect(String path) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.FIELD_EFFECT.getValue()); + mplew.write(3); + mplew.writeMapleAsciiString(path); + return mplew.getPacket(); + } + + public static byte[] mapSound(String path) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.FIELD_EFFECT.getValue()); + mplew.write(4); + mplew.writeMapleAsciiString(path); + return mplew.getPacket(); + } + + public static byte[] showGuildInfo(MapleCharacter c) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.GUILD_OPERATION.getValue()); + mplew.write(0x1A); //signature for showing guild info + if (c == null) { //show empty guild (used for leaving, expelled) + mplew.write(0); + return mplew.getPacket(); + } + MapleGuild g = c.getClient().getWorldServer().getGuild(c.getMGC()); + if (g == null) { //failed to read from DB - don't show a guild + mplew.write(0); + return mplew.getPacket(); + } else { + c.setGuildRank(c.getGuildRank()); + } + mplew.write(1); //bInGuild + mplew.writeInt(g.getId()); + mplew.writeMapleAsciiString(g.getName()); + for (int i = 1; i <= 5; i++) { + mplew.writeMapleAsciiString(g.getRankTitle(i)); + } + Collection members = g.getMembers(); + mplew.write(members.size()); //then it is the size of all the members + for (MapleGuildCharacter mgc : members) {//and each of their character ids o_O + mplew.writeInt(mgc.getId()); + } + for (MapleGuildCharacter mgc : members) { + mplew.writeAsciiString(getRightPaddedStr(mgc.getName(), '\0', 13)); + mplew.writeInt(mgc.getJobId()); + mplew.writeInt(mgc.getLevel()); + mplew.writeInt(mgc.getGuildRank()); + mplew.writeInt(mgc.isOnline() ? 1 : 0); + mplew.writeInt(g.getSignature()); + mplew.writeInt(mgc.getAllianceRank()); + } + mplew.writeInt(g.getCapacity()); + mplew.writeShort(g.getLogoBG()); + mplew.write(g.getLogoBGColor()); + mplew.writeShort(g.getLogo()); + mplew.write(g.getLogoColor()); + mplew.writeMapleAsciiString(g.getNotice()); + mplew.writeInt(g.getGP()); + mplew.writeInt(g.getAllianceId()); + return mplew.getPacket(); + } + + public static byte[] guildMemberOnline(int gid, int cid, boolean bOnline) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.GUILD_OPERATION.getValue()); + mplew.write(0x3d); + mplew.writeInt(gid); + mplew.writeInt(cid); + mplew.write(bOnline ? 1 : 0); + return mplew.getPacket(); + } + + public static byte[] guildInvite(int gid, String charName) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.GUILD_OPERATION.getValue()); + mplew.write(0x05); + mplew.writeInt(gid); + mplew.writeMapleAsciiString(charName); + return mplew.getPacket(); + } + + /** + * 'Char' has denied your guild invitation. + * + * @param charname + * @return + */ + public static byte[] denyGuildInvitation(String charname) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.GUILD_OPERATION.getValue()); + mplew.write(0x37); + mplew.writeMapleAsciiString(charname); + return mplew.getPacket(); + } + + public static byte[] genericGuildMessage(byte code) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.GUILD_OPERATION.getValue()); + mplew.write(code); + return mplew.getPacket(); + } + + public static byte[] newGuildMember(MapleGuildCharacter mgc) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.GUILD_OPERATION.getValue()); + mplew.write(0x27); + mplew.writeInt(mgc.getGuildId()); + mplew.writeInt(mgc.getId()); + mplew.writeAsciiString(getRightPaddedStr(mgc.getName(), '\0', 13)); + mplew.writeInt(mgc.getJobId()); + mplew.writeInt(mgc.getLevel()); + mplew.writeInt(mgc.getGuildRank()); //should be always 5 but whatevs + mplew.writeInt(mgc.isOnline() ? 1 : 0); //should always be 1 too + mplew.writeInt(1); //? could be guild signature, but doesn't seem to matter + mplew.writeInt(3); + return mplew.getPacket(); + } + + //someone leaving, mode == 0x2c for leaving, 0x2f for expelled + public static byte[] memberLeft(MapleGuildCharacter mgc, boolean bExpelled) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.GUILD_OPERATION.getValue()); + mplew.write(bExpelled ? 0x2f : 0x2c); + mplew.writeInt(mgc.getGuildId()); + mplew.writeInt(mgc.getId()); + mplew.writeMapleAsciiString(mgc.getName()); + return mplew.getPacket(); + } + + //rank change + public static byte[] changeRank(MapleGuildCharacter mgc) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.GUILD_OPERATION.getValue()); + mplew.write(0x40); + mplew.writeInt(mgc.getGuildId()); + mplew.writeInt(mgc.getId()); + mplew.write(mgc.getGuildRank()); + return mplew.getPacket(); + } + + public static byte[] guildNotice(int gid, String notice) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.GUILD_OPERATION.getValue()); + mplew.write(0x44); + mplew.writeInt(gid); + mplew.writeMapleAsciiString(notice); + return mplew.getPacket(); + } + + public static byte[] guildMemberLevelJobUpdate(MapleGuildCharacter mgc) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.GUILD_OPERATION.getValue()); + mplew.write(0x3C); + mplew.writeInt(mgc.getGuildId()); + mplew.writeInt(mgc.getId()); + mplew.writeInt(mgc.getLevel()); + mplew.writeInt(mgc.getJobId()); + return mplew.getPacket(); + } + + public static byte[] rankTitleChange(int gid, String[] ranks) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.GUILD_OPERATION.getValue()); + mplew.write(0x3E); + mplew.writeInt(gid); + for (int i = 0; i < 5; i++) { + mplew.writeMapleAsciiString(ranks[i]); + } + return mplew.getPacket(); + } + + public static byte[] guildDisband(int gid) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.GUILD_OPERATION.getValue()); + mplew.write(0x32); + mplew.writeInt(gid); + mplew.write(1); + return mplew.getPacket(); + } + + public static byte[] guildQuestWaitingNotice(byte channel, int waitingPos) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.GUILD_OPERATION.getValue()); + mplew.write(0x4C); + mplew.write(channel - 1); + mplew.write(waitingPos); + return mplew.getPacket(); + } + + public static byte[] guildEmblemChange(int gid, short bg, byte bgcolor, short logo, byte logocolor) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.GUILD_OPERATION.getValue()); + mplew.write(0x42); + mplew.writeInt(gid); + mplew.writeShort(bg); + mplew.write(bgcolor); + mplew.writeShort(logo); + mplew.write(logocolor); + return mplew.getPacket(); + } + + public static byte[] guildCapacityChange(int gid, int capacity) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.GUILD_OPERATION.getValue()); + mplew.write(0x3A); + mplew.writeInt(gid); + mplew.write(capacity); + return mplew.getPacket(); + } + + public static void addThread(final MaplePacketLittleEndianWriter mplew, ResultSet rs) throws SQLException { + mplew.writeInt(rs.getInt("localthreadid")); + mplew.writeInt(rs.getInt("postercid")); + mplew.writeMapleAsciiString(rs.getString("name")); + mplew.writeLong(getTime(rs.getLong("timestamp"))); + mplew.writeInt(rs.getInt("icon")); + mplew.writeInt(rs.getInt("replycount")); + } + + public static byte[] BBSThreadList(ResultSet rs, int start) throws SQLException { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.GUILD_BBS_PACKET.getValue()); + mplew.write(0x06); + if (!rs.last()) { + mplew.write(0); + mplew.writeInt(0); + mplew.writeInt(0); + return mplew.getPacket(); + } + int threadCount = rs.getRow(); + if (rs.getInt("localthreadid") == 0) { //has a notice + mplew.write(1); + addThread(mplew, rs); + threadCount--; //one thread didn't count (because it's a notice) + } else { + mplew.write(0); + } + if (!rs.absolute(start + 1)) { //seek to the thread before where we start + rs.first(); //uh, we're trying to start at a place past possible + start = 0; + } + mplew.writeInt(threadCount); + mplew.writeInt(Math.min(10, threadCount - start)); + for (int i = 0; i < Math.min(10, threadCount - start); i++) { + addThread(mplew, rs); + rs.next(); + } + return mplew.getPacket(); + } + + public static byte[] showThread(int localthreadid, ResultSet threadRS, ResultSet repliesRS) throws SQLException, RuntimeException { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.GUILD_BBS_PACKET.getValue()); + mplew.write(0x07); + mplew.writeInt(localthreadid); + mplew.writeInt(threadRS.getInt("postercid")); + mplew.writeLong(getTime(threadRS.getLong("timestamp"))); + mplew.writeMapleAsciiString(threadRS.getString("name")); + mplew.writeMapleAsciiString(threadRS.getString("startpost")); + mplew.writeInt(threadRS.getInt("icon")); + if (repliesRS != null) { + int replyCount = threadRS.getInt("replycount"); + mplew.writeInt(replyCount); + int i; + for (i = 0; i < replyCount && repliesRS.next(); i++) { + mplew.writeInt(repliesRS.getInt("replyid")); + mplew.writeInt(repliesRS.getInt("postercid")); + mplew.writeLong(getTime(repliesRS.getLong("timestamp"))); + mplew.writeMapleAsciiString(repliesRS.getString("content")); + } + if (i != replyCount || repliesRS.next()) { + throw new RuntimeException(String.valueOf(threadRS.getInt("threadid"))); + } + } else { + mplew.writeInt(0); + } + return mplew.getPacket(); + } + + public static byte[] showGuildRanks(int npcid, ResultSet rs) throws SQLException { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.GUILD_OPERATION.getValue()); + mplew.write(0x49); + mplew.writeInt(npcid); + if (!rs.last()) { //no guilds o.o + mplew.writeInt(0); + return mplew.getPacket(); + } + mplew.writeInt(rs.getRow()); //number of entries + rs.beforeFirst(); + while (rs.next()) { + mplew.writeMapleAsciiString(rs.getString("name")); + mplew.writeInt(rs.getInt("GP")); + mplew.writeInt(rs.getInt("logo")); + mplew.writeInt(rs.getInt("logoColor")); + mplew.writeInt(rs.getInt("logoBG")); + mplew.writeInt(rs.getInt("logoBGColor")); + } + return mplew.getPacket(); + } + + public static byte[] showPlayerRanks(int npcid, ResultSet rs) throws SQLException { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.GUILD_OPERATION.getValue()); + mplew.write(0x49); + mplew.writeInt(npcid); + if (!rs.last()) { + mplew.writeInt(0); + return mplew.getPacket(); + } + mplew.writeInt(rs.getRow()); + rs.beforeFirst(); + while (rs.next()) { + mplew.writeMapleAsciiString(rs.getString("name")); + mplew.writeInt(rs.getInt("level")); + mplew.writeInt(0); + mplew.writeInt(0); + mplew.writeInt(0); + mplew.writeInt(0); + } + return mplew.getPacket(); + } + + public static byte[] updateGP(int gid, int GP) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.GUILD_OPERATION.getValue()); + mplew.write(0x48); + mplew.writeInt(gid); + mplew.writeInt(GP); + return mplew.getPacket(); + } + + public static byte[] skillEffect(MapleCharacter from, int skillId, int level, byte flags, int speed, byte direction) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SKILL_EFFECT.getValue()); + mplew.writeInt(from.getId()); + mplew.writeInt(skillId); + mplew.write(level); + mplew.write(flags); + mplew.write(speed); + mplew.write(direction); //Mmmk + return mplew.getPacket(); + } + + public static byte[] skillCancel(MapleCharacter from, int skillId) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.CANCEL_SKILL_EFFECT.getValue()); + mplew.writeInt(from.getId()); + mplew.writeInt(skillId); + return mplew.getPacket(); + } + + public static byte[] showMagnet(int mobid, byte success) { // Monster Magnet + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SHOW_MAGNET.getValue()); + mplew.writeInt(mobid); + mplew.write(success); + mplew.skip(10); //Mmmk + return mplew.getPacket(); + } + + /** + * Sends a player hint. + * + * @param hint The hint it's going to send. + * @param width How tall the box is going to be. + * @param height How long the box is going to be. + * @return The player hint packet. + */ + public static byte[] sendHint(String hint, int width, int height) { + if (width < 1) { + width = hint.length() * 10; + if (width < 40) { + width = 40; + } + } + if (height < 5) { + height = 5; + } + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.PLAYER_HINT.getValue()); + mplew.writeMapleAsciiString(hint); + mplew.writeShort(width); + mplew.writeShort(height); + mplew.write(1); + return mplew.getPacket(); + } + + public static byte[] messengerInvite(String from, int messengerid) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.MESSENGER.getValue()); + mplew.write(0x03); + mplew.writeMapleAsciiString(from); + mplew.write(0); + mplew.writeInt(messengerid); + mplew.write(0); + return mplew.getPacket(); + } + + public static byte[] sendSpouseChat(MapleCharacter wife, String msg) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SPOUSE_CHAT.getValue()); + mplew.writeMapleAsciiString(wife.getName()); + mplew.writeMapleAsciiString(msg); + return mplew.getPacket(); + } + + public static byte[] addMessengerPlayer(String from, MapleCharacter chr, int position, int channel) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.MESSENGER.getValue()); + mplew.write(0x00); + mplew.write(position); + addCharLook(mplew, chr, true); + mplew.writeMapleAsciiString(from); + mplew.write(channel); + mplew.write(0x00); + return mplew.getPacket(); + } + + public static byte[] removeMessengerPlayer(int position) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.MESSENGER.getValue()); + mplew.write(0x02); + mplew.write(position); + return mplew.getPacket(); + } + + public static byte[] updateMessengerPlayer(String from, MapleCharacter chr, int position, int channel) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.MESSENGER.getValue()); + mplew.write(0x07); + mplew.write(position); + addCharLook(mplew, chr, true); + mplew.writeMapleAsciiString(from); + mplew.write(channel); + mplew.write(0x00); + return mplew.getPacket(); + } + + public static byte[] joinMessenger(int position) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.MESSENGER.getValue()); + mplew.write(0x01); + mplew.write(position); + return mplew.getPacket(); + } + + public static byte[] messengerChat(String text) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.MESSENGER.getValue()); + mplew.write(0x06); + mplew.writeMapleAsciiString(text); + return mplew.getPacket(); + } + + public static byte[] messengerNote(String text, int mode, int mode2) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.MESSENGER.getValue()); + mplew.write(mode); + mplew.writeMapleAsciiString(text); + mplew.write(mode2); + return mplew.getPacket(); + } + + public static void addPetInfo(final MaplePacketLittleEndianWriter mplew, MaplePet pet, boolean showpet) { + mplew.write(1); + if (showpet) { + mplew.write(0); + } + + mplew.writeInt(pet.getItemId()); + mplew.writeMapleAsciiString(pet.getName()); + mplew.writeInt(pet.getUniqueId()); + mplew.writeInt(0); + mplew.writePos(pet.getPos()); + mplew.write(pet.getStance()); + mplew.writeInt(pet.getFh()); + } + + public static byte[] showPet(MapleCharacter chr, MaplePet pet, boolean remove, boolean hunger) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SPAWN_PET.getValue()); + mplew.writeInt(chr.getId()); + mplew.write(chr.getPetIndex(pet)); + if (remove) { + mplew.write(0); + mplew.write(hunger ? 1 : 0); + } else { + addPetInfo(mplew, pet, true); + } + return mplew.getPacket(); + } + + public static byte[] movePet(int cid, int pid, byte slot, List moves) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.MOVE_PET.getValue()); + mplew.writeInt(cid); + mplew.write(slot); + mplew.writeInt(pid); + serializeMovementList(mplew, moves); + return mplew.getPacket(); + } + + public static byte[] petChat(int cid, byte index, int act, String text) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.PET_CHAT.getValue()); + mplew.writeInt(cid); + mplew.write(index); + mplew.write(0); + mplew.write(act); + mplew.writeMapleAsciiString(text); + mplew.write(0); + return mplew.getPacket(); + } + + public static byte[] commandResponse(int cid, byte index, int animation, boolean success) { + //AE 00 01 00 00 00 00 01 00 00 + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.PET_COMMAND.getValue()); + mplew.writeInt(cid); + mplew.write(index); + mplew.write((animation == 1 || !success) ? 1 : 0); + mplew.write(animation); + if (animation == 1) { + mplew.write(0); + } else { + mplew.writeShort(success ? 1 : 0); + } + return mplew.getPacket(); + } + + public static byte[] showOwnPetLevelUp(byte index) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SHOW_ITEM_GAIN_INCHAT.getValue()); + mplew.write(4); + mplew.write(0); + mplew.write(index); // Pet Index + return mplew.getPacket(); + } + + public static byte[] showPetLevelUp(MapleCharacter chr, byte index) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SHOW_FOREIGN_EFFECT.getValue()); + mplew.writeInt(chr.getId()); + mplew.write(4); + mplew.write(0); + mplew.write(index); + return mplew.getPacket(); + } + + public static byte[] changePetName(MapleCharacter chr, String newname, int slot) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.PET_NAMECHANGE.getValue()); + mplew.writeInt(chr.getId()); + mplew.write(0); + mplew.writeMapleAsciiString(newname); + mplew.write(0); + return mplew.getPacket(); + } + + public static byte[] petStatUpdate(MapleCharacter chr) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.STAT_CHANGED.getValue()); + int mask = 0; + mask |= MapleStat.PET.getValue(); + mplew.write(0); + mplew.writeInt(mask); + MaplePet[] pets = chr.getPets(); + for (int i = 0; i < 3; i++) { + if (pets[i] != null) { + mplew.writeInt(pets[i].getUniqueId()); + mplew.writeInt(0); + } else { + mplew.writeLong(0); + } + } + mplew.write(0); + return mplew.getPacket(); + } + + public static byte[] showForcedEquip(int team) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.FORCED_MAP_EQUIP.getValue()); + if (team > -1) { + mplew.write(team); // 00 = red, 01 = blue + } + return mplew.getPacket(); + } + + public static byte[] summonSkill(int cid, int summonSkillId, int newStance) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SUMMON_SKILL.getValue()); + mplew.writeInt(cid); + mplew.writeInt(summonSkillId); + mplew.write(newStance); + return mplew.getPacket(); + } + + public static byte[] skillCooldown(int sid, int time) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.COOLDOWN.getValue()); + mplew.writeInt(sid); + mplew.writeShort(time);//Int in v97 + return mplew.getPacket(); + } + + public static byte[] skillBookSuccess(MapleCharacter chr, int skillid, int maxlevel, boolean canuse, boolean success) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SKILL_LEARN_ITEM_RESULT.getValue()); + mplew.writeInt(chr.getId()); + mplew.write(1); + mplew.writeInt(skillid); + mplew.writeInt(maxlevel); + mplew.write(canuse ? 1 : 0); + mplew.write(success ? 1 : 0); + return mplew.getPacket(); + } + + public static byte[] getMacros(SkillMacro[] macros) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.MACRO_SYS_DATA_INIT.getValue()); + int count = 0; + for (int i = 0; i < 5; i++) { + if (macros[i] != null) { + count++; + } + } + mplew.write(count); + for (int i = 0; i < 5; i++) { + SkillMacro macro = macros[i]; + if (macro != null) { + mplew.writeMapleAsciiString(macro.getName()); + mplew.write(macro.getShout()); + mplew.writeInt(macro.getSkill1()); + mplew.writeInt(macro.getSkill2()); + mplew.writeInt(macro.getSkill3()); + } + } + return mplew.getPacket(); + } + + public static byte[] getPlayerNPC(PlayerNPCs npc) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.IMITATED_NPC_DATA.getValue()); + mplew.write(0x01); + mplew.writeInt(npc.getId()); + mplew.writeMapleAsciiString(npc.getName()); + mplew.write(0); // direction + mplew.write(npc.getSkin()); + mplew.writeInt(npc.getFace()); + mplew.write(0); + mplew.writeInt(npc.getHair()); + Map equip = npc.getEquips(); + Map myEquip = new LinkedHashMap<>(); + for (short position : equip.keySet()) { + short pos = (short) (position * -1); + if (pos > 100) { + pos -= 100; + myEquip.put(pos, equip.get(position)); + } else { + if (myEquip.get(pos) == null) { + myEquip.put(pos, equip.get(position)); + } + } + } + for (Entry entry : myEquip.entrySet()) { + mplew.write(entry.getKey()); + mplew.writeInt(entry.getValue()); + } + mplew.writeShort(-1); + Integer cWeapon = equip.get((byte) -111); + if (cWeapon != null) { + mplew.writeInt(cWeapon); + } else { + mplew.writeInt(0); + } + for (int i = 0; i < 12; i++) { + mplew.write(0); + } + return mplew.getPacket(); + } + + public static byte[] updateAriantPQRanking(String name, int score, boolean empty) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.ARIANT_SCORE.getValue()); + mplew.write(empty ? 0 : 1); + if (!empty) { + mplew.writeMapleAsciiString(name); + mplew.writeInt(score); + } + return mplew.getPacket(); + } + + public static byte[] catchMonster(int monsobid, int itemid, byte success) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.CATCH_MONSTER.getValue()); + mplew.writeInt(monsobid); + mplew.writeInt(itemid); + mplew.write(success); + return mplew.getPacket(); + } + + public static byte[] catchMessage(int message) { // not done, I guess + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.BRIDLE_MOB_CATCH_FAIL.getValue()); + mplew.write(message); // 1 = too strong, 2 = Elemental Rock + mplew.writeInt(0);//Maybe itemid? + mplew.writeInt(0); + return mplew.getPacket(); + } + + public static byte[] showAllCharacter(int chars, int unk) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(11); + mplew.writeShort(SendOpcode.VIEW_ALL_CHAR.getValue()); + mplew.write(1); + mplew.writeInt(chars); + mplew.writeInt(unk); + return mplew.getPacket(); + } + + public static byte[] showAllCharacterInfo(int worldid, List chars) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.VIEW_ALL_CHAR.getValue()); + mplew.write(0); + mplew.write(worldid); + mplew.write(chars.size()); + for (MapleCharacter chr : chars) { + addCharEntry(mplew, chr, true); + } + return mplew.getPacket(); + } + + public static byte[] updateMount(int charid, MapleMount mount, boolean levelup) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SET_TAMING_MOB_INFO.getValue()); + mplew.writeInt(charid); + mplew.writeInt(mount.getLevel()); + mplew.writeInt(mount.getExp()); + mplew.writeInt(mount.getTiredness()); + mplew.write(levelup ? (byte) 1 : (byte) 0); + return mplew.getPacket(); + } + + + public static byte[] boatPacket(boolean type) {//don't think this is correct.. + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.CONTI_STATE.getValue()); + mplew.write(type ? 1 : 2); + mplew.write(0); + return mplew.getPacket(); + } + + public static byte[] getMiniGame(MapleClient c, MapleMiniGame minigame, boolean owner, int piece) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); + mplew.write(PlayerInteractionHandler.Action.ROOM.getCode()); + mplew.write(1); + mplew.write(0); + mplew.write(owner ? 0 : 1); + mplew.write(0); + addCharLook(mplew, minigame.getOwner(), false); + mplew.writeMapleAsciiString(minigame.getOwner().getName()); + if (minigame.getVisitor() != null) { + MapleCharacter visitor = minigame.getVisitor(); + mplew.write(1); + addCharLook(mplew, visitor, false); + mplew.writeMapleAsciiString(visitor.getName()); + } + mplew.write(0xFF); + mplew.write(0); + mplew.writeInt(1); + mplew.writeInt(minigame.getOwner().getMiniGamePoints("wins", true)); + mplew.writeInt(minigame.getOwner().getMiniGamePoints("ties", true)); + mplew.writeInt(minigame.getOwner().getMiniGamePoints("losses", true)); + mplew.writeInt(2000); + if (minigame.getVisitor() != null) { + MapleCharacter visitor = minigame.getVisitor(); + mplew.write(1); + mplew.writeInt(1); + mplew.writeInt(visitor.getMiniGamePoints("wins", true)); + mplew.writeInt(visitor.getMiniGamePoints("ties", true)); + mplew.writeInt(visitor.getMiniGamePoints("losses", true)); + mplew.writeInt(2000); + } + mplew.write(0xFF); + mplew.writeMapleAsciiString(minigame.getDescription()); + mplew.write(piece); + mplew.write(0); + return mplew.getPacket(); + } + + public static byte[] getMiniGameReady(MapleMiniGame game) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(3); + mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); + mplew.write(PlayerInteractionHandler.Action.READY.getCode()); + return mplew.getPacket(); + } + + public static byte[] getMiniGameUnReady(MapleMiniGame game) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(3); + mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); + mplew.write(PlayerInteractionHandler.Action.UN_READY.getCode()); + return mplew.getPacket(); + } + + public static byte[] getMiniGameStart(MapleMiniGame game, int loser) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(4); + mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); + mplew.write(PlayerInteractionHandler.Action.START.getCode()); + mplew.write(loser); + return mplew.getPacket(); + } + + public static byte[] getMiniGameSkipOwner(MapleMiniGame game) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(4); + mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); + mplew.write(PlayerInteractionHandler.Action.SKIP.getCode()); + mplew.write(0x01); + return mplew.getPacket(); + } + + public static byte[] getMiniGameRequestTie(MapleMiniGame game) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(3); + mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); + mplew.write(PlayerInteractionHandler.Action.REQUEST_TIE.getCode()); + return mplew.getPacket(); + } + + public static byte[] getMiniGameDenyTie(MapleMiniGame game) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(3); + mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); + mplew.write(PlayerInteractionHandler.Action.ANSWER_TIE.getCode()); + return mplew.getPacket(); + } + + public static byte[] getMiniGameFull() { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(5); + mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); + mplew.write(PlayerInteractionHandler.Action.ROOM.getCode()); + mplew.write(0); + mplew.write(2); + return mplew.getPacket(); + } + + public static byte[] getMiniGameSkipVisitor(MapleMiniGame game) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(4); + mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); + mplew.writeShort(PlayerInteractionHandler.Action.SKIP.getCode()); + return mplew.getPacket(); + } + + public static byte[] getMiniGameMoveOmok(MapleMiniGame game, int move1, int move2, int move3) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(12); + mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); + mplew.write(PlayerInteractionHandler.Action.MOVE_OMOK.getCode()); + mplew.writeInt(move1); + mplew.writeInt(move2); + mplew.write(move3); + return mplew.getPacket(); + } + + public static byte[] getMiniGameNewVisitor(MapleCharacter c, int slot) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); + mplew.write(PlayerInteractionHandler.Action.VISIT.getCode()); + mplew.write(slot); + addCharLook(mplew, c, false); + mplew.writeMapleAsciiString(c.getName()); + mplew.writeInt(1); + mplew.writeInt(c.getMiniGamePoints("wins", true)); + mplew.writeInt(c.getMiniGamePoints("ties", true)); + mplew.writeInt(c.getMiniGamePoints("losses", true)); + mplew.writeInt(2000); + return mplew.getPacket(); + } + + public static byte[] getMiniGameRemoveVisitor() { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(3); + mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); + mplew.write(PlayerInteractionHandler.Action.EXIT.getCode()); + mplew.write(1); + return mplew.getPacket(); + } + + private static byte[] getMiniGameResult(MapleMiniGame game, int win, int lose, int tie, int result, int forfeit, boolean omok) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); + mplew.write(PlayerInteractionHandler.Action.GET_RESULT.getCode()); + if (tie == 0 && forfeit != 1) { + mplew.write(0); + } else if (tie == 1) { + mplew.write(1); + } else if (forfeit == 1) { + mplew.write(2); + } + mplew.write(0); // owner + mplew.writeInt(1); // unknown + mplew.writeInt(game.getOwner().getMiniGamePoints("wins", omok) + win); // wins + mplew.writeInt(game.getOwner().getMiniGamePoints("ties", omok) + tie); // ties + mplew.writeInt(game.getOwner().getMiniGamePoints("losses", omok) + lose); // losses + mplew.writeInt(2000); // points + mplew.writeInt(1); // start of visitor; unknown + mplew.writeInt(game.getVisitor().getMiniGamePoints("wins", omok) + lose); // wins + mplew.writeInt(game.getVisitor().getMiniGamePoints("ties", omok) + tie); // ties + mplew.writeInt(game.getVisitor().getMiniGamePoints("losses", omok) + win); // losses + mplew.writeInt(2000); // points + game.getOwner().setMiniGamePoints(game.getVisitor(), result, omok); + return mplew.getPacket(); + } + + public static byte[] getMiniGameOwnerWin(MapleMiniGame game) { + return getMiniGameResult(game, 0, 1, 0, 1, 0, true); + } + + public static byte[] getMiniGameVisitorWin(MapleMiniGame game) { + return getMiniGameResult(game, 1, 0, 0, 2, 0, true); + } + + public static byte[] getMiniGameTie(MapleMiniGame game) { + return getMiniGameResult(game, 0, 0, 1, 3, 0, true); + } + + public static byte[] getMiniGameOwnerForfeit(MapleMiniGame game) { + return getMiniGameResult(game, 0, 1, 0, 2, 1, true); + } + + public static byte[] getMiniGameVisitorForfeit(MapleMiniGame game) { + return getMiniGameResult(game, 1, 0, 0, 1, 1, true); + } + + public static byte[] getMiniGameClose() { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(5); + mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); + mplew.write(PlayerInteractionHandler.Action.EXIT.getCode()); + mplew.write(1); + mplew.write(3); + return mplew.getPacket(); + } + + public static byte[] getMatchCard(MapleClient c, MapleMiniGame minigame, boolean owner, int piece) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); + mplew.write(PlayerInteractionHandler.Action.ROOM.getCode()); + mplew.write(2); + mplew.write(2); + mplew.write(owner ? 0 : 1); + mplew.write(0); + addCharLook(mplew, minigame.getOwner(), false); + mplew.writeMapleAsciiString(minigame.getOwner().getName()); + if (minigame.getVisitor() != null) { + MapleCharacter visitor = minigame.getVisitor(); + mplew.write(1); + addCharLook(mplew, visitor, false); + mplew.writeMapleAsciiString(visitor.getName()); + } + mplew.write(0xFF); + mplew.write(0); + mplew.writeInt(2); + mplew.writeInt(minigame.getOwner().getMiniGamePoints("wins", false)); + mplew.writeInt(minigame.getOwner().getMiniGamePoints("ties", false)); + mplew.writeInt(minigame.getOwner().getMiniGamePoints("losses", false)); + mplew.writeInt(2000); + if (minigame.getVisitor() != null) { + MapleCharacter visitor = minigame.getVisitor(); + mplew.write(1); + mplew.writeInt(2); + mplew.writeInt(visitor.getMiniGamePoints("wins", false)); + mplew.writeInt(visitor.getMiniGamePoints("ties", false)); + mplew.writeInt(visitor.getMiniGamePoints("losses", false)); + mplew.writeInt(2000); + } + mplew.write(0xFF); + mplew.writeMapleAsciiString(minigame.getDescription()); + mplew.write(piece); + mplew.write(0); + return mplew.getPacket(); + } + + public static byte[] getMatchCardStart(MapleMiniGame game, int loser) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); + mplew.write(PlayerInteractionHandler.Action.START.getCode()); + mplew.write(loser); + mplew.write(0x0C); + int last = 13; + if (game.getMatchesToWin() > 10) { + last = 31; + } else if (game.getMatchesToWin() > 6) { + last = 21; + } + for (int i = 1; i < last; i++) { + mplew.writeInt(game.getCardId(i)); + } + return mplew.getPacket(); + } + + public static byte[] getMatchCardNewVisitor(MapleCharacter c, int slot) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); + mplew.write(PlayerInteractionHandler.Action.VISIT.getCode()); + mplew.write(slot); + addCharLook(mplew, c, false); + mplew.writeMapleAsciiString(c.getName()); + mplew.writeInt(1); + mplew.writeInt(c.getMiniGamePoints("wins", false)); + mplew.writeInt(c.getMiniGamePoints("ties", false)); + mplew.writeInt(c.getMiniGamePoints("losses", false)); + mplew.writeInt(2000); + return mplew.getPacket(); + } + + public static byte[] getMatchCardSelect(MapleMiniGame game, int turn, int slot, int firstslot, int type) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(6); + mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); + mplew.write(PlayerInteractionHandler.Action.SELECT_CARD.getCode()); + mplew.write(turn); + if (turn == 1) { + mplew.write(slot); + } else if (turn == 0) { + mplew.write(slot); + mplew.write(firstslot); + mplew.write(type); + } + return mplew.getPacket(); + } + + public static byte[] getMatchCardOwnerWin(MapleMiniGame game) { + return getMiniGameResult(game, 1, 0, 0, 1, 0, false); + } + + public static byte[] getMatchCardVisitorWin(MapleMiniGame game) { + return getMiniGameResult(game, 0, 1, 0, 2, 0, false); + } + + public static byte[] getMatchCardTie(MapleMiniGame game) { + return getMiniGameResult(game, 0, 0, 1, 3, 0, false); + } + + public static byte[] fredrickMessage(byte operation) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.FREDRICK_MESSAGE.getValue()); + mplew.write(operation); + return mplew.getPacket(); + } + + public static byte[] getFredrick(byte op) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.FREDRICK.getValue()); + mplew.write(op); + + switch (op) { + case 0x24: + mplew.skip(8); + break; + default: + mplew.write(0); + break; + } + + return mplew.getPacket(); + } + + public static byte[] getFredrick(MapleCharacter chr) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.FREDRICK.getValue()); + mplew.write(0x23); + mplew.writeInt(9030000); // Fredrick + mplew.writeInt(32272); //id + mplew.skip(5); + mplew.writeInt(chr.getMerchantMeso()); + mplew.write(0); + try { + List> items = ItemFactory.MERCHANT.loadItems(chr.getId(), false); + mplew.write(items.size()); + + for (int i = 0; i < items.size(); i++) { + addItemInfo(mplew, items.get(i).getLeft(), true); + } + } catch (SQLException e) { + e.printStackTrace(); + } + mplew.skip(3); + return mplew.getPacket(); + } + + public static byte[] addOmokBox(MapleCharacter c, int ammount, int type) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.UPDATE_CHAR_BOX.getValue()); + mplew.writeInt(c.getId()); + addAnnounceBox(mplew, c.getMiniGame(), 1, 0, ammount, type); + return mplew.getPacket(); + } + + public static byte[] removeOmokBox(MapleCharacter c) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(7); + mplew.writeShort(SendOpcode.UPDATE_CHAR_BOX.getValue()); + mplew.writeInt(c.getId()); + mplew.write(0); + return mplew.getPacket(); + } + + public static byte[] addMatchCardBox(MapleCharacter c, int ammount, int type) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.UPDATE_CHAR_BOX.getValue()); + mplew.writeInt(c.getId()); + addAnnounceBox(mplew, c.getMiniGame(), 2, 0, ammount, type); + return mplew.getPacket(); + } + + public static byte[] removeMatchcardBox(MapleCharacter c) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.UPDATE_CHAR_BOX.getValue()); + mplew.writeInt(c.getId()); + mplew.write(0); + return mplew.getPacket(); + } + + public static byte[] getPlayerShopChat(MapleCharacter c, String chat, byte slot) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); + mplew.write(PlayerInteractionHandler.Action.CHAT.getCode()); + mplew.write(PlayerInteractionHandler.Action.CHAT_THING.getCode()); + mplew.write(slot); + mplew.writeMapleAsciiString(c.getName() + " : " + chat); + return mplew.getPacket(); + } + + public static byte[] getTradeChat(MapleCharacter c, String chat, boolean owner) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); + mplew.write(PlayerInteractionHandler.Action.CHAT.getCode()); + mplew.write(PlayerInteractionHandler.Action.CHAT_THING.getCode()); + mplew.write(owner ? 0 : 1); + mplew.writeMapleAsciiString(c.getName() + " : " + chat); + return mplew.getPacket(); + } + + public static byte[] hiredMerchantBox() { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.ENTRUSTED_SHOP_CHECK_RESULT.getValue()); // header. + mplew.write(0x07); + return mplew.getPacket(); + } + + public static byte[] owlOfMinerva(MapleClient c, int itemid, List hms, List items) { //Thanks moongra, you save me some time :) + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SHOP_SCANNER_RESULT.getValue()); // header. + mplew.write(6); + mplew.writeInt(0); + mplew.writeInt(itemid); + mplew.writeInt(hms.size()); + for (HiredMerchant hm : hms) { + for (MaplePlayerShopItem item : items) { + mplew.writeMapleAsciiString(hm.getOwner()); + mplew.writeInt(hm.getMapId()); + mplew.writeMapleAsciiString(hm.getDescription()); + mplew.writeInt(item.getItem().getQuantity()); + mplew.writeInt(item.getBundles()); + mplew.writeInt(item.getPrice()); + mplew.writeInt(hm.getOwnerId()); + mplew.write(hm.getFreeSlot() == -1 ? 1 : 0); + MapleCharacter chr = c.getChannelServer().getPlayerStorage().getCharacterById(hm.getOwnerId()); + if ((chr != null) && (c.getChannel() == hm.getChannel())) { + mplew.write(1); + } else { + mplew.write(2); + } + + if (item.getItem().getItemId() / 1000000 == 1) { + addItemInfo(mplew, item.getItem(), true); + } + } + } + return mplew.getPacket(); + } + + public static byte[] retrieveFirstMessage() { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.ENTRUSTED_SHOP_CHECK_RESULT.getValue()); // header. + mplew.write(0x09); + return mplew.getPacket(); + } + + public static byte[] remoteChannelChange(byte ch) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.ENTRUSTED_SHOP_CHECK_RESULT.getValue()); // header. + mplew.write(0x10); + mplew.writeInt(0);//No idea yet + mplew.write(ch); + return mplew.getPacket(); + } + /* + * Possible things for ENTRUSTED_SHOP_CHECK_RESULT + * 0x0E = 00 = Renaming Failed - Can't find the merchant, 01 = Renaming succesful + * 0x10 = Changes channel to the store (Store is open at Channel 1, do you want to change channels?) + * 0x11 = You cannot sell any items when managing.. blabla + * 0x12 = FKING POPUP LOL + */ + + public static byte[] getHiredMerchant(MapleCharacter chr, HiredMerchant hm, boolean firstTime) {//Thanks Dustin + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); + mplew.write(PlayerInteractionHandler.Action.ROOM.getCode()); + mplew.write(0x05); + mplew.write(0x04); + mplew.writeShort(hm.getVisitorSlot(chr) + 1); + mplew.writeInt(hm.getItemId()); + mplew.writeMapleAsciiString("Hired Merchant"); + for (int i = 0; i < 3; i++) { + if (hm.getVisitors()[i] != null) { + mplew.write(i + 1); + addCharLook(mplew, hm.getVisitors()[i], false); + mplew.writeMapleAsciiString(hm.getVisitors()[i].getName()); + } + } + mplew.write(-1); + if (hm.isOwner(chr)) { + mplew.writeShort(hm.getMessages().size()); + for (int i = 0; i < hm.getMessages().size(); i++) { + mplew.writeMapleAsciiString(hm.getMessages().get(i).getLeft()); + mplew.write(hm.getMessages().get(i).getRight()); + } + } else { + mplew.writeShort(0); + } + mplew.writeMapleAsciiString(hm.getOwner()); + if (hm.isOwner(chr)) { + mplew.writeInt(hm.getTimeLeft()); + mplew.write(firstTime ? 1 : 0); + //List sold = hm.getSold(); + mplew.write(0);//sold.size() + /*for (SoldItem s : sold) { fix this + mplew.writeInt(s.getItemId()); + mplew.writeShort(s.getQuantity()); + mplew.writeInt(s.getMesos()); + mplew.writeMapleAsciiString(s.getBuyer()); + }*/ + mplew.writeInt(chr.getMerchantMeso());//:D? + } + mplew.writeMapleAsciiString(hm.getDescription()); + mplew.write(0x10); //TODO SLOTS, which is 16 for most stores...slotMax + mplew.writeInt(chr.getMeso()); + mplew.write(hm.getItems().size()); + if (hm.getItems().isEmpty()) { + mplew.write(0);//Hmm?? + } else { + for (MaplePlayerShopItem item : hm.getItems()) { + mplew.writeShort(item.getBundles()); + mplew.writeShort(item.getItem().getQuantity()); + mplew.writeInt(item.getPrice()); + addItemInfo(mplew, item.getItem(), true); + } + } + return mplew.getPacket(); + } + + public static byte[] updateHiredMerchant(HiredMerchant hm, MapleCharacter chr) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); + mplew.write(PlayerInteractionHandler.Action.UPDATE_MERCHANT.getCode()); + mplew.writeInt(chr.getMeso()); + mplew.write(hm.getItems().size()); + for (MaplePlayerShopItem item : hm.getItems()) { + mplew.writeShort(item.getBundles()); + mplew.writeShort(item.getItem().getQuantity()); + mplew.writeInt(item.getPrice()); + addItemInfo(mplew, item.getItem(), true); + } + return mplew.getPacket(); + } + + public static byte[] hiredMerchantChat(String message, byte slot) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); + mplew.write(PlayerInteractionHandler.Action.CHAT.getCode()); + mplew.write(PlayerInteractionHandler.Action.CHAT_THING.getCode()); + mplew.write(slot); + mplew.writeMapleAsciiString(message); + return mplew.getPacket(); + } + + public static byte[] hiredMerchantVisitorLeave(int slot) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); + mplew.write(PlayerInteractionHandler.Action.EXIT.getCode()); + if (slot != 0) { + mplew.write(slot); + } + return mplew.getPacket(); + } + + public static byte[] hiredMerchantOwnerLeave() { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); + mplew.write(PlayerInteractionHandler.Action.REAL_CLOSE_MERCHANT.getCode()); + mplew.write(0); + return mplew.getPacket(); + } + + public static byte[] leaveHiredMerchant(int slot, int status2) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); + mplew.write(PlayerInteractionHandler.Action.EXIT.getCode()); + mplew.write(slot); + mplew.write(status2); + return mplew.getPacket(); + } + + public static byte[] hiredMerchantVisitorAdd(MapleCharacter chr, int slot) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); + mplew.write(PlayerInteractionHandler.Action.VISIT.getCode()); + mplew.write(slot); + addCharLook(mplew, chr, false); + mplew.writeMapleAsciiString(chr.getName()); + return mplew.getPacket(); + } + + public static byte[] spawnHiredMerchant(HiredMerchant hm) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SPAWN_HIRED_MERCHANT.getValue()); + mplew.writeInt(hm.getOwnerId()); + mplew.writeInt(hm.getItemId()); + mplew.writeShort((short) hm.getPosition().getX()); + mplew.writeShort((short) hm.getPosition().getY()); + mplew.writeShort(0); + mplew.writeMapleAsciiString(hm.getOwner()); + mplew.write(0x05); + mplew.writeInt(hm.getObjectId()); + mplew.writeMapleAsciiString(hm.getDescription()); + mplew.write(hm.getItemId() % 10); + mplew.write(new byte[]{1, 4}); + return mplew.getPacket(); + } + + public static byte[] destroyHiredMerchant(int id) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.DESTROY_HIRED_MERCHANT.getValue()); + mplew.writeInt(id); + return mplew.getPacket(); + } + + public static byte[] spawnPlayerNPC(PlayerNPCs npc) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SPAWN_NPC_REQUEST_CONTROLLER.getValue()); + mplew.write(1); + mplew.writeInt(npc.getObjectId()); + mplew.writeInt(npc.getId()); + mplew.writeShort(npc.getPosition().x); + mplew.writeShort(npc.getCY()); + mplew.write(1); + mplew.writeShort(npc.getFH()); + mplew.writeShort(npc.getRX0()); + mplew.writeShort(npc.getRX1()); + mplew.write(1); + return mplew.getPacket(); + } + + public static byte[] sendYellowTip(String tip) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SET_WEEK_EVENT_MESSAGE.getValue()); + mplew.write(0xFF); + mplew.writeMapleAsciiString(tip); + mplew.writeShort(0); + return mplew.getPacket(); + } + + public static byte[] givePirateBuff(List> statups, int buffid, int duration) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + boolean infusion = buffid == Buccaneer.SPEED_INFUSION || buffid == ThunderBreaker.SPEED_INFUSION || buffid == Corsair.SPEED_INFUSION; + mplew.writeShort(SendOpcode.GIVE_BUFF.getValue()); + writeLongMask(mplew, statups); + mplew.writeShort(0); + for (Pair stat : statups) { + mplew.writeInt(stat.getRight().shortValue()); + mplew.writeInt(buffid); + mplew.skip(infusion ? 10 : 5); + mplew.writeShort(duration); + } + mplew.skip(3); + return mplew.getPacket(); + } + + public static byte[] giveForgeinPirateBuff(int cid, int buffid, int time, List> statups) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + boolean infusion = buffid == Buccaneer.SPEED_INFUSION || buffid == ThunderBreaker.SPEED_INFUSION || buffid == Corsair.SPEED_INFUSION; + mplew.writeShort(SendOpcode.GIVE_FOREIGN_BUFF.getValue()); + mplew.writeInt(cid); + writeLongMask(mplew, statups); + mplew.writeShort(0); + for (Pair statup : statups) { + mplew.writeInt(statup.getRight().shortValue()); + mplew.writeInt(buffid); + mplew.skip(infusion ? 10 : 5); + mplew.writeShort(time); + } + mplew.writeShort(0); + mplew.write(2); + return mplew.getPacket(); + } + + public static byte[] sendMTS(List items, int tab, int type, int page, int pages) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.MTS_OPERATION.getValue()); + mplew.write(0x15); //operation + mplew.writeInt(pages * 16); //testing, change to 10 if fails + mplew.writeInt(items.size()); //number of items + mplew.writeInt(tab); + mplew.writeInt(type); + mplew.writeInt(page); + mplew.write(1); + mplew.write(1); + for (int i = 0; i < items.size(); i++) { + MTSItemInfo item = items.get(i); + addItemInfo(mplew, item.getItem(), true); + mplew.writeInt(item.getID()); //id + mplew.writeInt(item.getTaxes()); //this + below = price + mplew.writeInt(item.getPrice()); //price + mplew.writeInt(0); + mplew.writeLong(getTime(item.getEndingDate())); + mplew.writeMapleAsciiString(item.getSeller()); //account name (what was nexon thinking?) + mplew.writeMapleAsciiString(item.getSeller()); //char name + for (int j = 0; j < 28; j++) { + mplew.write(0); + } + } + mplew.write(1); + return mplew.getPacket(); + } + + public static byte[] noteSendMsg() { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(3); + mplew.writeShort(SendOpcode.MEMO_RESULT.getValue()); + mplew.write(4); + return mplew.getPacket(); + } + + /* + * 0 = Player online, use whisper + * 1 = Check player's name + * 2 = Receiver inbox full + */ + public static byte[] noteError(byte error) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(4); + mplew.writeShort(SendOpcode.MEMO_RESULT.getValue()); + mplew.write(5); + mplew.write(error); + return mplew.getPacket(); + } + + public static byte[] showNotes(ResultSet notes, int count) throws SQLException { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.MEMO_RESULT.getValue()); + mplew.write(3); + mplew.write(count); + for (int i = 0; i < count; i++) { + mplew.writeInt(notes.getInt("id")); + mplew.writeMapleAsciiString(notes.getString("from") + " ");//Stupid nexon forgot space lol + mplew.writeMapleAsciiString(notes.getString("message")); + mplew.writeLong(getTime(notes.getLong("timestamp"))); + mplew.write(notes.getByte("fame"));//FAME :D + notes.next(); + } + return mplew.getPacket(); + } + + public static byte[] useChalkboard(MapleCharacter chr, boolean close) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.CHALKBOARD.getValue()); + mplew.writeInt(chr.getId()); + if (close) { + mplew.write(0); + } else { + mplew.write(1); + mplew.writeMapleAsciiString(chr.getChalkboard()); + } + return mplew.getPacket(); + } + + public static byte[] trockRefreshMapList(MapleCharacter chr, boolean delete, boolean vip) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.MAP_TRANSFER_RESULT.getValue()); + mplew.write(delete ? 2 : 3); + if (vip) { + mplew.write(1); + List map = chr.getVipTrockMaps(); + for (int i = 0; i < 10; i++) { + mplew.writeInt(map.get(i)); + } + } else { + mplew.write(0); + List map = chr.getTrockMaps(); + for (int i = 0; i < 5; i++) { + mplew.writeInt(map.get(i)); + } + } + return mplew.getPacket(); + } + + public static byte[] showMTSCash(MapleCharacter p) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.MTS_OPERATION2.getValue()); + mplew.writeInt(p.getCashShop().getCash(4)); + mplew.writeInt(p.getCashShop().getCash(2)); + return mplew.getPacket(); + } + + public static byte[] MTSWantedListingOver(int nx, int items) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.MTS_OPERATION.getValue()); + mplew.write(0x3D); + mplew.writeInt(nx); + mplew.writeInt(items); + return mplew.getPacket(); + } + + public static byte[] MTSConfirmSell() { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.MTS_OPERATION.getValue()); + mplew.write(0x1D); + return mplew.getPacket(); + } + + public static byte[] MTSConfirmBuy() { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.MTS_OPERATION.getValue()); + mplew.write(0x33); + return mplew.getPacket(); + } + + public static byte[] MTSFailBuy() { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.MTS_OPERATION.getValue()); + mplew.write(0x34); + mplew.write(0x42); + return mplew.getPacket(); + } + + public static byte[] MTSConfirmTransfer(int quantity, int pos) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.MTS_OPERATION.getValue()); + mplew.write(0x27); + mplew.writeInt(quantity); + mplew.writeInt(pos); + return mplew.getPacket(); + } + + public static byte[] notYetSoldInv(List items) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.MTS_OPERATION.getValue()); + mplew.write(0x23); + mplew.writeInt(items.size()); + if (!items.isEmpty()) { + for (MTSItemInfo item : items) { + addItemInfo(mplew, item.getItem(), true); + mplew.writeInt(item.getID()); //id + mplew.writeInt(item.getTaxes()); //this + below = price + mplew.writeInt(item.getPrice()); //price + mplew.writeInt(0); + mplew.writeLong(getTime(item.getEndingDate())); + mplew.writeMapleAsciiString(item.getSeller()); //account name (what was nexon thinking?) + mplew.writeMapleAsciiString(item.getSeller()); //char name + for (int i = 0; i < 28; i++) { + mplew.write(0); + } + } + } else { + mplew.writeInt(0); + } + return mplew.getPacket(); + } + + public static byte[] transferInventory(List items) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.MTS_OPERATION.getValue()); + mplew.write(0x21); + mplew.writeInt(items.size()); + if (!items.isEmpty()) { + for (MTSItemInfo item : items) { + addItemInfo(mplew, item.getItem(), true); + mplew.writeInt(item.getID()); //id + mplew.writeInt(item.getTaxes()); //taxes + mplew.writeInt(item.getPrice()); //price + mplew.writeInt(0); + mplew.writeLong(getTime(item.getEndingDate())); + mplew.writeMapleAsciiString(item.getSeller()); //account name (what was nexon thinking?) + mplew.writeMapleAsciiString(item.getSeller()); //char name + for (int i = 0; i < 28; i++) { + mplew.write(0); + } + } + } + mplew.write(0xD0 + items.size()); + mplew.write(new byte[]{-1, -1, -1, 0}); + return mplew.getPacket(); + } + + public static byte[] showCouponRedeemedItem(int itemid) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.CASHSHOP_OPERATION.getValue()); + mplew.writeShort(0x49); //v72 + mplew.writeInt(0); + mplew.writeInt(1); + mplew.writeShort(1); + mplew.writeShort(0x1A); + mplew.writeInt(itemid); + mplew.writeInt(0); + return mplew.getPacket(); + } + + public static byte[] showCash(MapleCharacter mc) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.QUERY_CASH_RESULT.getValue()); + + mplew.writeInt(mc.getCashShop().getCash(1)); + mplew.writeInt(mc.getCashShop().getCash(2)); + mplew.writeInt(mc.getCashShop().getCash(4)); + + return mplew.getPacket(); + } + + public static byte[] enableCSUse() { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.write(0x12); + mplew.skip(6); + return mplew.getPacket(); + } + + /** + * + * @param target + * @param mapid + * @param MTSmapCSchannel 0: MTS 1: Map 2: CS 3: Different Channel + * @return + */ + public static byte[] getFindReply(String target, int mapid, int MTSmapCSchannel) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.WHISPER.getValue()); + mplew.write(9); + mplew.writeMapleAsciiString(target); + mplew.write(MTSmapCSchannel); // 0: mts 1: map 2: cs + mplew.writeInt(mapid); // -1 if mts, cs + if (MTSmapCSchannel == 1) { + mplew.write(new byte[8]); + } + return mplew.getPacket(); + } + + public static byte[] sendAutoHpPot(int itemId) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.AUTO_HP_POT.getValue()); + mplew.writeInt(itemId); + return mplew.getPacket(); + } + + public static byte[] sendAutoMpPot(int itemId) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(6); + mplew.writeShort(SendOpcode.AUTO_MP_POT.getValue()); + mplew.writeInt(itemId); + return mplew.getPacket(); + } + + public static byte[] showOXQuiz(int questionSet, int questionId, boolean askQuestion) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(6); + mplew.writeShort(SendOpcode.OX_QUIZ.getValue()); + mplew.write(askQuestion ? 1 : 0); + mplew.write(questionSet); + mplew.writeShort(questionId); + return mplew.getPacket(); + } + + public static byte[] updateGender(MapleCharacter chr) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(3); + mplew.writeShort(SendOpcode.SET_GENDER.getValue()); + mplew.write(chr.getGender()); + return mplew.getPacket(); + } + + public static byte[] enableReport() { // by snow + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(3); + mplew.writeShort(SendOpcode.CLAIM_STATUS_CHANGED.getValue()); + mplew.write(1); + return mplew.getPacket(); + } + + public static byte[] giveFinalAttack(int skillid, int time) {//packets found by lailainoob + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.GIVE_BUFF.getValue()); + mplew.writeLong(0); + mplew.writeShort(0); + mplew.write(0);//some 80 and 0 bs DIRECTION + mplew.write(0x80);//let's just do 80, then 0 + mplew.writeInt(0); + mplew.writeShort(1); + mplew.writeInt(skillid); + mplew.writeInt(time); + mplew.writeInt(0); + return mplew.getPacket(); + } + + public static byte[] loadFamily(MapleCharacter player) { + String[] title = {"Family Reunion", "Summon Family", "My Drop Rate 1.5x (15 min)", "My EXP 1.5x (15 min)", "Family Bonding (30 min)", "My Drop Rate 2x (15 min)", "My EXP 2x (15 min)", "My Drop Rate 2x (30 min)", "My EXP 2x (30 min)", "My Party Drop Rate 2x (30 min)", "My Party EXP 2x (30 min)"}; + String[] description = {"[Target] Me\n[Effect] Teleport directly to the Family member of your choice.", "[Target] 1 Family member\n[Effect] Summon a Family member of choice to the map you're in.", "[Target] Me\n[Time] 15 min.\n[Effect] Monster drop rate will be increased #c1.5x#.\n* If the Drop Rate event is in progress, this will be nullified.", "[Target] Me\n[Time] 15 min.\n[Effect] EXP earned from hunting will be increased #c1.5x#.\n* If the EXP event is in progress, this will be nullified.", "[Target] At least 6 Family members online that are below me in the Pedigree\n[Time] 30 min.\n[Effect] Monster drop rate and EXP earned will be increased #c2x#. \n* If the EXP event is in progress, this will be nullified.", "[Target] Me\n[Time] 15 min.\n[Effect] Monster drop rate will be increased #c2x#.\n* If the Drop Rate event is in progress, this will be nullified.", "[Target] Me\n[Time] 15 min.\n[Effect] EXP earned from hunting will be increased #c2x#.\n* If the EXP event is in progress, this will be nullified.", "[Target] Me\n[Time] 30 min.\n[Effect] Monster drop rate will be increased #c2x#.\n* If the Drop Rate event is in progress, this will be nullified.", "[Target] Me\n[Time] 30 min.\n[Effect] EXP earned from hunting will be increased #c2x#. \n* If the EXP event is in progress, this will be nullified.", "[Target] My party\n[Time] 30 min.\n[Effect] Monster drop rate will be increased #c2x#.\n* If the Drop Rate event is in progress, this will be nullified.", "[Target] My party\n[Time] 30 min.\n[Effect] EXP earned from hunting will be increased #c2x#.\n* If the EXP event is in progress, this will be nullified."}; + int[] repCost = {3, 5, 7, 8, 10, 12, 15, 20, 25, 40, 50}; + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.FAMILY_PRIVILEGE_LIST.getValue()); + mplew.writeInt(11); + for (int i = 0; i < 11; i++) { + mplew.write(i > 4 ? (i % 2) + 1 : i); + mplew.writeInt(repCost[i] * 100); + mplew.writeInt(1); + mplew.writeMapleAsciiString(title[i]); + mplew.writeMapleAsciiString(description[i]); + } + return mplew.getPacket(); + } + + /** + * Family Result Message + * + * Possible values for type:
+ * 67: You do not belong to the same family.
+ * 69: The character you wish to add as\r\na Junior must be in the same + * map.
+ * 70: This character is already a Junior of another character.
+ * 71: The Junior you wish to add\r\nmust be at a lower rank.
+ * 72: The gap between you and your\r\njunior must be within 20 levels.
+ * 73: Another character has requested to add this character.\r\nPlease try + * again later.
+ * 74: Another character has requested a summon.\r\nPlease try again + * later.
+ * 75: The summons has failed. Your current location or state does not allow + * a summons.
+ * 76: The family cannot extend more than 1000 generations from above and + * below.
+ * 77: The Junior you wish to add\r\nmust be over Level 10.
+ * 78: You cannot add a Junior \r\nthat has requested to change worlds.
+ * 79: You cannot add a Junior \r\nsince you've requested to change + * worlds.
+ * 80: Separation is not possible due to insufficient Mesos.\r\nYou will + * need %d Mesos to\r\nseparate with a Senior.
+ * 81: Separation is not possible due to insufficient Mesos.\r\nYou will + * need %d Mesos to\r\nseparate with a Junior.
+ * 82: The Entitlement does not apply because your level does not match the + * corresponding area.
+ * + * @param type The type + * @return Family Result packet + */ + public static byte[] sendFamilyMessage(int type, int mesos) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(6); + mplew.writeShort(SendOpcode.FAMILY_RESULT.getValue()); + mplew.writeInt(type); + mplew.writeInt(mesos); + return mplew.getPacket(); + } + + public static byte[] getFamilyInfo(MapleFamilyEntry f) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.FAMILY_INFO_RESULT.getValue()); + mplew.writeInt(f.getReputation()); // cur rep left + mplew.writeInt(f.getTotalReputation()); // tot rep left + mplew.writeInt(f.getTodaysRep()); // todays rep + mplew.writeShort(f.getJuniors()); // juniors added + mplew.writeShort(f.getTotalJuniors()); // juniors allowed + mplew.writeShort(0); //Unknown + mplew.writeInt(f.getId()); // id? + mplew.writeMapleAsciiString(f.getFamilyName()); + mplew.writeInt(0); + mplew.writeShort(0); + return mplew.getPacket(); + } + + public static byte[] showPedigree(int chrid, Map members) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.FAMILY_CHART_RESULT.getValue()); + //Hmmm xD + return mplew.getPacket(); + } + + public static byte[] updateAreaInfo(int area, String info) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SHOW_STATUS_INFO.getValue()); + mplew.write(0x0A); //0x0B in v95 + mplew.writeShort(area);//infoNumber + mplew.writeMapleAsciiString(info); + return mplew.getPacket(); + } + + public static byte[] getGPMessage(int gpChange) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(7); + mplew.writeShort(SendOpcode.SHOW_STATUS_INFO.getValue()); + mplew.write(6); + mplew.writeInt(gpChange); + return mplew.getPacket(); + } + + public static byte[] getItemMessage(int itemid) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(7); + mplew.writeShort(SendOpcode.SHOW_STATUS_INFO.getValue()); + mplew.write(7); + mplew.writeInt(itemid); + return mplew.getPacket(); + } + + public static byte[] addCard(boolean full, int cardid, int level) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(11); + mplew.writeShort(SendOpcode.MONSTER_BOOK_SET_CARD.getValue()); + mplew.write(full ? 0 : 1); + mplew.writeInt(cardid); + mplew.writeInt(level); + return mplew.getPacket(); + } + + public static byte[] showGainCard() { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(3); + mplew.writeShort(SendOpcode.SHOW_ITEM_GAIN_INCHAT.getValue()); + mplew.write(0x0D); + return mplew.getPacket(); + } + + public static byte[] showForeginCardEffect(int id) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(7); + mplew.writeShort(SendOpcode.SHOW_FOREIGN_EFFECT.getValue()); + mplew.writeInt(id); + mplew.write(0x0D); + return mplew.getPacket(); + } + + public static byte[] changeCover(int cardid) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(6); + mplew.writeShort(SendOpcode.MONSTER_BOOK_SET_COVER.getValue()); + mplew.writeInt(cardid); + return mplew.getPacket(); + } + + public static byte[] aranGodlyStats() { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.FORCED_STAT_SET.getValue()); + mplew.write(new byte[]{(byte) 0x1F, (byte) 0x0F, 0, 0, (byte) 0xE7, 3, (byte) 0xE7, 3, (byte) 0xE7, 3, (byte) 0xE7, 3, (byte) 0xFF, 0, (byte) 0xE7, 3, (byte) 0xE7, 3, (byte) 0x78, (byte) 0x8C}); + return mplew.getPacket(); + } + + public static byte[] showIntro(String path) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SHOW_ITEM_GAIN_INCHAT.getValue()); + mplew.write(0x12); + mplew.writeMapleAsciiString(path); + return mplew.getPacket(); + } + + public static byte[] showInfo(String path) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SHOW_ITEM_GAIN_INCHAT.getValue()); + mplew.write(0x17); + mplew.writeMapleAsciiString(path); + mplew.writeInt(1); + return mplew.getPacket(); + } + + /** + * Sends a UI utility. 0x01 - Equipment Inventory. 0x02 - Stat Window. 0x03 + * - Skill Window. 0x05 - Keyboard Settings. 0x06 - Quest window. 0x09 - + * Monsterbook Window. 0x0A - Char Info 0x0B - Guild BBS 0x12 - Monster + * Carnival Window 0x16 - Party Search. 0x17 - Item Creation Window. 0x1A - + * My Ranking O.O 0x1B - Family Window 0x1C - Family Pedigree 0x1D - GM + * Story Board /funny shet 0x1E - Envelop saying you got mail from an admin. + * lmfao 0x1F - Medal Window 0x20 - Maple Event (???) 0x21 - Invalid Pointer + * Crash + * + * @param ui + * @return + */ + public static byte[] openUI(byte ui) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(3); + mplew.writeShort(SendOpcode.OPEN_UI.getValue()); + mplew.write(ui); + return mplew.getPacket(); + } + + public static byte[] lockUI(boolean enable) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(3); + mplew.writeShort(SendOpcode.LOCK_UI.getValue()); + mplew.write(enable ? 1 : 0); + return mplew.getPacket(); + } + + public static byte[] disableUI(boolean enable) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.DISABLE_UI.getValue()); + mplew.write(enable ? 1 : 0); + return mplew.getPacket(); + } + + public static byte[] itemMegaphone(String msg, boolean whisper, int channel, Item item) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SERVERMESSAGE.getValue()); + mplew.write(8); + mplew.writeMapleAsciiString(msg); + mplew.write(channel - 1); + mplew.write(whisper ? 1 : 0); + if (item == null) { + mplew.write(0); + } else { + mplew.write(item.getPosition()); + addItemInfo(mplew, item, true); + } + return mplew.getPacket(); + } + + public static byte[] removeNPC(int oid) { //Make npc's invisible + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SPAWN_NPC_REQUEST_CONTROLLER.getValue()); + mplew.write(0); + mplew.writeInt(oid); + return mplew.getPacket(); + } + + /** + * Sends a report response + * + * Possible values for mode:
0: You have succesfully + * reported the user.
1: Unable to locate the user.
2: You may only + * report users 10 times a day.
3: You have been reported to the GM's by + * a user.
4: Your request did not go through for unknown reasons. + * Please try again later.
+ * + * @param mode The mode + * @return Report Reponse packet + */ + public static byte[] reportResponse(byte mode) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SUE_CHARACTER_RESULT.getValue()); + mplew.write(mode); + return mplew.getPacket(); + } + + public static byte[] sendHammerData(int hammerUsed) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.VICIOUS_HAMMER.getValue()); + mplew.write(0x39); + mplew.writeInt(0); + mplew.writeInt(hammerUsed); + return mplew.getPacket(); + } + + public static byte[] sendHammerMessage() { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.VICIOUS_HAMMER.getValue()); + mplew.write(0x3D); + mplew.writeInt(0); + return mplew.getPacket(); + } + + public static byte[] playPortalSound() { + return showSpecialEffect(7); + } + + public static byte[] showMonsterBookPickup() { + return showSpecialEffect(14); + } + + public static byte[] showEquipmentLevelUp() { + return showSpecialEffect(15); + } + + public static byte[] showItemLevelup() { + return showSpecialEffect(15); + } + + /** + * 6 = Exp did not drop (Safety Charms) 7 = Enter portal sound 8 = Job + * change 9 = Quest complete 10 = Recovery 14 = Monster book pickup 15 = + * Equipment levelup 16 = Maker Skill Success 19 = Exp card [500, 200, 50] + * + * @param effect + * @return + */ + public static byte[] showSpecialEffect(int effect) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SHOW_ITEM_GAIN_INCHAT.getValue()); + mplew.write(effect); + return mplew.getPacket(); + } + + public static byte[] showForeignEffect(int effect) { + return showForeignEffect(-1, effect); + } + + public static byte[] showForeignEffect(int cid, int effect) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SHOW_FOREIGN_EFFECT.getValue()); + mplew.writeInt(cid); + mplew.write(effect); + return mplew.getPacket(); + } + + public static byte[] showOwnRecovery(byte heal) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SHOW_ITEM_GAIN_INCHAT.getValue()); + mplew.write(0x0A); + mplew.write(heal); + return mplew.getPacket(); + } + + public static byte[] showRecovery(int cid, byte amount) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SHOW_FOREIGN_EFFECT.getValue()); + mplew.writeInt(cid); + mplew.write(0x0A); + mplew.write(amount); + return mplew.getPacket(); + } + + public static byte[] showWheelsLeft(int left) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SHOW_ITEM_GAIN_INCHAT.getValue()); + mplew.write(0x15); + mplew.write(left); + return mplew.getPacket(); + } + + public static byte[] updateQuestFinish(short quest, int npc, short nextquest) { //Check + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.UPDATE_QUEST_INFO.getValue()); //0xF2 in v95 + mplew.write(8);//0x0A in v95 + mplew.writeShort(quest); + mplew.writeInt(npc); + mplew.writeShort(nextquest); + return mplew.getPacket(); + } + + public static byte[] showInfoText(String text) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SHOW_STATUS_INFO.getValue()); + mplew.write(9); + mplew.writeMapleAsciiString(text); + return mplew.getPacket(); + } + + public static byte[] questError(short quest) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.UPDATE_QUEST_INFO.getValue()); + mplew.write(0x0A); + mplew.writeShort(quest); + return mplew.getPacket(); + } + + public static byte[] questFailure(byte type) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.UPDATE_QUEST_INFO.getValue()); + mplew.write(type);//0x0B = No meso, 0x0D = Worn by character, 0x0E = Not having the item ? + return mplew.getPacket(); + } + + public static byte[] questExpire(short quest) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.UPDATE_QUEST_INFO.getValue()); + mplew.write(0x0F); + mplew.writeShort(quest); + return mplew.getPacket(); + } + + public static byte[] getMultiMegaphone(String[] messages, int channel, boolean showEar) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SERVERMESSAGE.getValue()); + mplew.write(0x0A); + if (messages[0] != null) { + mplew.writeMapleAsciiString(messages[0]); + } + mplew.write(messages.length); + for (int i = 1; i < messages.length; i++) { + if (messages[i] != null) { + mplew.writeMapleAsciiString(messages[i]); + } + } + for (int i = 0; i < 10; i++) { + mplew.write(channel - 1); + } + mplew.write(showEar ? 1 : 0); + mplew.write(1); + return mplew.getPacket(); + } + + /** + * Gets a gm effect packet (ie. hide, banned, etc.) + * + * Possible values for type:
0x04: You have successfully + * blocked access.
+ * 0x05: The unblocking has been successful.
0x06 with Mode 0: You have + * successfully removed the name from the ranks.
0x06 with Mode 1: You + * have entered an invalid character name.
0x10: GM Hide, mode + * determines whether or not it is on.
0x1E: Mode 0: Failed to send + * warning Mode 1: Sent warning
0x13 with Mode 0: + mapid 0x13 with Mode + * 1: + ch (FF = Unable to find merchant) + * + * @param type The type + * @param mode The mode + * @return The gm effect packet + */ + public static byte[] getGMEffect(int type, byte mode) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.ADMIN_RESULT.getValue()); + mplew.write(type); + mplew.write(mode); + return mplew.getPacket(); + } + + public static byte[] findMerchantResponse(boolean map, int extra) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.ADMIN_RESULT.getValue()); + mplew.write(0x13); + mplew.write(map ? 0 : 1); //00 = mapid, 01 = ch + if (map) { + mplew.writeInt(extra); + } else { + mplew.write(extra); //-1 = unable to find + } + mplew.write(0); + return mplew.getPacket(); + } + + public static byte[] disableMinimap() { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.ADMIN_RESULT.getValue()); + mplew.writeShort(0x1C); + return mplew.getPacket(); + } + + public static byte[] sendFamilyInvite(int playerId, String inviter) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.FAMILY_JOIN_REQUEST.getValue()); + mplew.writeInt(playerId); + mplew.writeMapleAsciiString(inviter); + return mplew.getPacket(); + } + + public static byte[] showBoughtCashPackage(List cashPackage, int accountId) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.CASHSHOP_OPERATION.getValue()); + + mplew.write(0x89); + mplew.write(cashPackage.size()); + + for (Item item : cashPackage) { + addCashItemInformation(mplew, item, accountId); + } + + mplew.writeShort(0); + + return mplew.getPacket(); + } + + public static byte[] showBoughtQuestItem(int itemId) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.CASHSHOP_OPERATION.getValue()); + + mplew.write(0x8D); + mplew.writeInt(1); + mplew.writeShort(1); + mplew.write(0x0B); + mplew.write(0); + mplew.writeInt(itemId); + + return mplew.getPacket(); + } + + private static void getGuildInfo(final MaplePacketLittleEndianWriter mplew, MapleGuild guild) { + mplew.writeInt(guild.getId()); + mplew.writeMapleAsciiString(guild.getName()); + for (int i = 1; i <= 5; i++) { + mplew.writeMapleAsciiString(guild.getRankTitle(i)); + } + Collection members = guild.getMembers(); + mplew.write(members.size()); + for (MapleGuildCharacter mgc : members) { + mplew.writeInt(mgc.getId()); + } + for (MapleGuildCharacter mgc : members) { + mplew.writeAsciiString(getRightPaddedStr(mgc.getName(), '\0', 13)); + mplew.writeInt(mgc.getJobId()); + mplew.writeInt(mgc.getLevel()); + mplew.writeInt(mgc.getGuildRank()); + mplew.writeInt(mgc.isOnline() ? 1 : 0); + mplew.writeInt(guild.getSignature()); + mplew.writeInt(mgc.getAllianceRank()); + } + mplew.writeInt(guild.getCapacity()); + mplew.writeShort(guild.getLogoBG()); + mplew.write(guild.getLogoBGColor()); + mplew.writeShort(guild.getLogo()); + mplew.write(guild.getLogoColor()); + mplew.writeMapleAsciiString(guild.getNotice()); + mplew.writeInt(guild.getGP()); + mplew.writeInt(guild.getAllianceId()); + } + + public static byte[] getAllianceInfo(MapleAlliance alliance) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.ALLIANCE_OPERATION.getValue()); + mplew.write(0x0C); + mplew.write(1); + mplew.writeInt(alliance.getId()); + mplew.writeMapleAsciiString(alliance.getName()); + for (int i = 1; i <= 5; i++) { + mplew.writeMapleAsciiString(alliance.getRankTitle(i)); + } + mplew.write(alliance.getGuilds().size()); + mplew.writeInt(2); // probably capacity + for (Integer guild : alliance.getGuilds()) { + mplew.writeInt(guild); + } + mplew.writeMapleAsciiString(alliance.getNotice()); + return mplew.getPacket(); + } + + public static byte[] makeNewAlliance(MapleAlliance alliance, MapleClient c) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.ALLIANCE_OPERATION.getValue()); + mplew.write(0x0F); + mplew.writeInt(alliance.getId()); + mplew.writeMapleAsciiString(alliance.getName()); + for (int i = 1; i <= 5; i++) { + mplew.writeMapleAsciiString(alliance.getRankTitle(i)); + } + mplew.write(alliance.getGuilds().size()); + for (Integer guild : alliance.getGuilds()) { + mplew.writeInt(guild); + } + mplew.writeInt(2); // probably capacity + mplew.writeShort(0); + for (Integer guildd : alliance.getGuilds()) { + getGuildInfo(mplew, Server.getInstance().getGuild(guildd, c.getWorld(), c.getPlayer().getMGC())); + } + return mplew.getPacket(); + } + + public static byte[] getGuildAlliances(MapleAlliance alliance, MapleClient c) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.ALLIANCE_OPERATION.getValue()); + mplew.write(0x0D); + mplew.writeInt(alliance.getGuilds().size()); + for (Integer guild : alliance.getGuilds()) { + getGuildInfo(mplew, Server.getInstance().getGuild(guild, c.getWorld(), null)); + } + return mplew.getPacket(); + } + + public static byte[] addGuildToAlliance(MapleAlliance alliance, int newGuild, MapleClient c) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.ALLIANCE_OPERATION.getValue()); + mplew.write(0x12); + mplew.writeInt(alliance.getId()); + mplew.writeMapleAsciiString(alliance.getName()); + for (int i = 1; i <= 5; i++) { + mplew.writeMapleAsciiString(alliance.getRankTitle(i)); + } + mplew.write(alliance.getGuilds().size()); + for (Integer guild : alliance.getGuilds()) { + mplew.writeInt(guild); + } + mplew.writeInt(2); + mplew.writeMapleAsciiString(alliance.getNotice()); + mplew.writeInt(newGuild); + getGuildInfo(mplew, Server.getInstance().getGuild(newGuild, c.getWorld(), null)); + return mplew.getPacket(); + } + + public static byte[] allianceMemberOnline(MapleCharacter mc, boolean online) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.ALLIANCE_OPERATION.getValue()); + mplew.write(0x0E); + mplew.writeInt(mc.getGuild().getAllianceId()); + mplew.writeInt(mc.getGuildId()); + mplew.writeInt(mc.getId()); + mplew.write(online ? 1 : 0); + return mplew.getPacket(); + } + + public static byte[] allianceNotice(int id, String notice) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.ALLIANCE_OPERATION.getValue()); + mplew.write(0x1C); + mplew.writeInt(id); + mplew.writeMapleAsciiString(notice); + return mplew.getPacket(); + } + + public static byte[] changeAllianceRankTitle(int alliance, String[] ranks) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.ALLIANCE_OPERATION.getValue()); + mplew.write(0x1A); + mplew.writeInt(alliance); + for (int i = 0; i < 5; i++) { + mplew.writeMapleAsciiString(ranks[i]); + } + return mplew.getPacket(); + } + + public static byte[] updateAllianceJobLevel(MapleCharacter mc) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.ALLIANCE_OPERATION.getValue()); + mplew.write(0x18); + mplew.writeInt(mc.getGuild().getAllianceId()); + mplew.writeInt(mc.getGuildId()); + mplew.writeInt(mc.getId()); + mplew.writeInt(mc.getLevel()); + mplew.writeInt(mc.getJob().getId()); + return mplew.getPacket(); + } + + public static byte[] removeGuildFromAlliance(MapleAlliance alliance, int expelledGuild, MapleClient c) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.ALLIANCE_OPERATION.getValue()); + mplew.write(0x10); + mplew.writeInt(alliance.getId()); + mplew.writeMapleAsciiString(alliance.getName()); + for (int i = 1; i <= 5; i++) { + mplew.writeMapleAsciiString(alliance.getRankTitle(i)); + } + mplew.write(alliance.getGuilds().size()); + for (Integer guild : alliance.getGuilds()) { + mplew.writeInt(guild); + } + mplew.writeInt(2); + mplew.writeMapleAsciiString(alliance.getNotice()); + mplew.writeInt(expelledGuild); + getGuildInfo(mplew, Server.getInstance().getGuild(expelledGuild, c.getWorld(), null)); + mplew.write(0x01); + return mplew.getPacket(); + } + + public static byte[] disbandAlliance(int alliance) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.ALLIANCE_OPERATION.getValue()); + mplew.write(0x1D); + mplew.writeInt(alliance); + return mplew.getPacket(); + } + + public static byte[] sendMesoLimit() { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.TRADE_MONEY_LIMIT.getValue()); //Players under level 15 can only trade 1m per day + return mplew.getPacket(); + } + + public static byte[] sendEngagementRequest(String name) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.MARRIAGE_REQUEST.getValue()); // has requested engagement. Will you accept this proposal? + mplew.write(0); + mplew.writeMapleAsciiString(name); // name + mplew.writeInt(10); // playerid + return mplew.getPacket(); + } + + public static byte[] sendGroomWishlist() { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.MARRIAGE_REQUEST.getValue()); // has requested engagement. Will you accept this proposal? + mplew.write(9); + return mplew.getPacket(); + } + + public static byte[] sendBrideWishList(List items) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.WEDDING_GIFT_RESULT.getValue()); + mplew.write(0x0A); + mplew.writeLong(-1); // ? + mplew.writeInt(0); // ? + mplew.write(items.size()); + for (Item item : items) { + addItemInfo(mplew, item, true); + } + return mplew.getPacket(); + } + + public static byte[] addItemToWeddingRegistry(MapleCharacter chr, Item item) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.WEDDING_GIFT_RESULT.getValue()); + mplew.write(0x0B); + mplew.writeInt(0); + for (int i = 0; i < 0; i++) // f4 + { + mplew.write(0); + } + + addItemInfo(mplew, item, true); + return mplew.getPacket(); + } + + public static byte[] sendFamilyJoinResponse(boolean accepted, String added) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.FAMILY_JOIN_REQUEST_RESULT.getValue()); + mplew.write(accepted ? 1 : 0); + mplew.writeMapleAsciiString(added); + return mplew.getPacket(); + } + + public static byte[] getSeniorMessage(String name) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.FAMILY_JOIN_ACCEPTED.getValue()); + mplew.writeMapleAsciiString(name); + mplew.writeInt(0); + return mplew.getPacket(); + } + + public static byte[] sendGainRep(int gain, int mode) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.FAMILY_FAMOUS_POINT_INC_RESULT.getValue()); + mplew.writeInt(gain); + mplew.writeShort(0); + return mplew.getPacket(); + } + + public static byte[] removeItemFromDuey(boolean remove, int Package) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.PARCEL.getValue()); + mplew.write(0x17); + mplew.writeInt(Package); + mplew.write(remove ? 3 : 4); + return mplew.getPacket(); + } + + public static byte[] sendDueyMSG(byte operation) { + return sendDuey(operation, null); + } + + public static byte[] sendDuey(byte operation, List packages) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.PARCEL.getValue()); + mplew.write(operation); + if (operation == 8) { + mplew.write(0); + mplew.write(packages.size()); + for (DueyPackages dp : packages) { + mplew.writeInt(dp.getPackageId()); + mplew.writeAsciiString(dp.getSender()); + for (int i = dp.getSender().length(); i < 13; i++) { + mplew.write(0); + } + mplew.writeInt(dp.getMesos()); + mplew.writeLong(getTime(dp.sentTimeInMilliseconds())); + mplew.writeLong(0); // Contains message o____o. + for (int i = 0; i < 48; i++) { + mplew.writeInt(Randomizer.nextInt(Integer.MAX_VALUE)); + } + mplew.writeInt(0); + mplew.write(0); + if (dp.getItem() != null) { + mplew.write(1); + addItemInfo(mplew, dp.getItem(), true); + } else { + mplew.write(0); + } + } + mplew.write(0); + } + + return mplew.getPacket(); + } + + public static byte[] sendDojoAnimation(byte firstByte, String animation) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.FIELD_EFFECT.getValue()); + mplew.write(firstByte); + mplew.writeMapleAsciiString(animation); + return mplew.getPacket(); + } + + public static byte[] getDojoInfo(String info) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SHOW_STATUS_INFO.getValue()); + mplew.write(10); + mplew.write(new byte[]{(byte) 0xB7, 4});//QUEST ID f5 + mplew.writeMapleAsciiString(info); + return mplew.getPacket(); + } + + public static byte[] getDojoInfoMessage(String message) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SHOW_STATUS_INFO.getValue()); + mplew.write(9); + mplew.writeMapleAsciiString(message); + return mplew.getPacket(); + } + + /** + * Gets a "block" packet (ie. the cash shop is unavailable, etc) + * + * Possible values for type:
1: The portal is closed for + * now.
2: You cannot go to that place.
3: Unable to approach due to + * the force of the ground.
4: You cannot teleport to or on this + * map.
5: Unable to approach due to the force of the ground.
6: + * This map can only be entered by party members.
7: The Cash Shop is + * currently not available. Stay tuned...
+ * + * @param type The type + * @return The "block" packet. + */ + public static byte[] blockedMessage(int type) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.BLOCKED_MAP.getValue()); + mplew.write(type); + return mplew.getPacket(); + } + + /** + * Gets a "block" packet (ie. the cash shop is unavailable, etc) + * + * Possible values for type:
1: You cannot move that + * channel. Please try again later.
2: You cannot go into the cash shop. + * Please try again later.
3: The Item-Trading Shop is currently + * unavailable. Please try again later.
4: You cannot go into the trade + * shop, due to limitation of user count.
5: You do not meet the minimum + * level requirement to access the Trade Shop.
+ * + * @param type The type + * @return The "block" packet. + */ + public static byte[] blockedMessage2(int type) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.BLOCKED_SERVER.getValue()); + mplew.write(type); + return mplew.getPacket(); + } + + public static byte[] updateDojoStats(MapleCharacter chr, int belt) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SHOW_STATUS_INFO.getValue()); + mplew.write(10); + mplew.write(new byte[]{(byte) 0xB7, 4}); //? + mplew.writeMapleAsciiString("pt=" + chr.getDojoPoints() + ";belt=" + belt + ";tuto=" + (chr.getFinishedDojoTutorial() ? "1" : "0")); + return mplew.getPacket(); + } + + /** + * Sends a "levelup" packet to the guild or family. + * + * Possible values for type:
0: ? has reached Lv. + * ?.
- The Reps you have received from ? will be reduced in half. 1: + * ? has reached Lv. ?.
2: ? has reached Lv. ?.
+ * + * @param type The type + * @return The "levelup" packet. + */ + public static byte[] levelUpMessage(int type, int level, String charname) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.NOTIFY_LEVELUP.getValue()); + mplew.write(type); + mplew.writeInt(level); + mplew.writeMapleAsciiString(charname); + + return mplew.getPacket(); + } + + /** + * Sends a "married" packet to the guild or family. + * + * Possible values for type:
0: 1: + * + * @param type The type + * @return The "married" packet. + */ + public static byte[] marriageMessage(int type, String charname) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.NOTIFY_MARRIAGE.getValue()); + mplew.write(type); + mplew.writeMapleAsciiString("> " + charname); //To fix the stupid packet lol + + return mplew.getPacket(); + } + + /** + * Sends a "job advance" packet to the guild or family. + * + * Possible values for type:
0: 1: + * + * @param type The type + * @return The "job advance" packet. + */ + public static byte[] jobMessage(int type, int job, String charname) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.NOTIFY_JOB_CHANGE.getValue()); + mplew.write(type); + mplew.writeInt(job); //Why fking int? + mplew.writeMapleAsciiString("> " + charname); //To fix the stupid packet lol + + return mplew.getPacket(); + } + + /** + * + * @param type - (0:Light&Long 1:Heavy&Short) + * @param delay - seconds + * @return + */ + public static byte[] trembleEffect(int type, int delay) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.FIELD_EFFECT.getValue()); + mplew.write(1); + mplew.write(type); + mplew.writeInt(delay); + return mplew.getPacket(); + } + + public static byte[] getEnergy(String info, int amount) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SESSION_VALUE.getValue()); + mplew.writeMapleAsciiString(info); + mplew.writeMapleAsciiString(Integer.toString(amount)); + return mplew.getPacket(); + } + + public static byte[] dojoWarpUp() { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.DOJO_WARP_UP.getValue()); + mplew.write(0); + mplew.write(6); + return mplew.getPacket(); + } + + public static byte[] itemExpired(int itemid) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SHOW_STATUS_INFO.getValue()); + mplew.write(2); + mplew.writeInt(itemid); + return mplew.getPacket(); + } + + private static String getRightPaddedStr(String in, char padchar, int length) { + StringBuilder builder = new StringBuilder(in); + for (int x = in.length(); x < length; x++) { + builder.append(padchar); + } + return builder.toString(); + } + + public static byte[] MobDamageMobFriendly(MapleMonster mob, int damage) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.DAMAGE_MONSTER.getValue()); + mplew.writeInt(mob.getObjectId()); + mplew.write(1); // direction ? + mplew.writeInt(damage); + int remainingHp = mob.getHp() - damage; + if (remainingHp <= 1) { + remainingHp = 0; + mob.getMap().removeMapObject(mob); + } + mob.setHp(remainingHp); + mplew.writeInt(remainingHp); + mplew.writeInt(mob.getMaxHp()); + return mplew.getPacket(); + } + + public static byte[] shopErrorMessage(int error, int type) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue()); + mplew.write(0x0A); + mplew.write(type); + mplew.write(error); + return mplew.getPacket(); + } + + private static void addRingInfo(final MaplePacketLittleEndianWriter mplew, MapleCharacter chr) { + mplew.writeShort(chr.getCrushRings().size()); + for (MapleRing ring : chr.getCrushRings()) { + mplew.writeInt(ring.getPartnerChrId()); + mplew.writeAsciiString(getRightPaddedStr(ring.getPartnerName(), '\0', 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(), '\0', 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(StringUtil.getRightPaddedStr(chr.getGender() == 0 ? chr.getName() : chr.getMarriageRing().getPartnerName(), '\0', 13)); + mplew.writeAsciiString(StringUtil.getRightPaddedStr(chr.getGender() == 0 ? chr.getMarriageRing().getPartnerName() : chr.getName(), '\0', 13)); + } + } + + public static byte[] finishedSort(int inv) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(4); + mplew.writeShort(SendOpcode.GATHER_ITEM_RESULT.getValue()); + mplew.write(0); + mplew.write(inv); + return mplew.getPacket(); + } + + public static byte[] finishedSort2(int inv) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(4); + mplew.writeShort(SendOpcode.SORT_ITEM_RESULT.getValue()); + mplew.write(0); + mplew.write(inv); + return mplew.getPacket(); + } + + public static byte[] bunnyPacket() { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SHOW_STATUS_INFO.getValue()); + mplew.write(9); + mplew.writeAsciiString("Protect the Moon Bunny!!!"); + return mplew.getPacket(); + } + + public static byte[] hpqMessage(String text) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.BLOW_WEATHER.getValue()); // not 100% sure + mplew.write(0); + mplew.writeInt(5120016); + mplew.writeAsciiString(text); + return mplew.getPacket(); + } + + public static byte[] showEventInstructions() { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.GMEVENT_INSTRUCTIONS.getValue()); + mplew.write(0); + return mplew.getPacket(); + } + + public static byte[] leftKnockBack() { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(2); + mplew.writeShort(SendOpcode.LEFT_KNOCK_BACK.getValue()); + return mplew.getPacket(); + } + + public static byte[] rollSnowBall(boolean entermap, int state, MapleSnowball ball0, MapleSnowball ball1) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SNOWBALL_STATE.getValue()); + if (entermap) { + mplew.skip(21); + } else { + mplew.write(state);// 0 = move, 1 = roll, 2 is down disappear, 3 is up disappear + mplew.writeInt(ball0.getSnowmanHP() / 75); + mplew.writeInt(ball1.getSnowmanHP() / 75); + mplew.writeShort(ball0.getPosition());//distance snowball down, 84 03 = max + mplew.write(-1); + mplew.writeShort(ball1.getPosition());//distance snowball up, 84 03 = max + mplew.write(-1); + } + return mplew.getPacket(); + } + + public static byte[] hitSnowBall(int what, int damage) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(7); + mplew.writeShort(SendOpcode.HIT_SNOWBALL.getValue()); + mplew.write(what); + mplew.writeInt(damage); + return mplew.getPacket(); + } + + /** + * Sends a Snowball Message
+ * + * Possible values for message:
1: ... Team's snowball has + * passed the stage 1.
2: ... Team's snowball has passed the stage + * 2.
3: ... Team's snowball has passed the stage 3.
4: ... Team is + * attacking the snowman, stopping the progress
5: ... Team is moving + * again
+ * + * @param message + * + */ + public static byte[] snowballMessage(int team, int message) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(7); + mplew.writeShort(SendOpcode.SNOWBALL_MESSAGE.getValue()); + mplew.write(team);// 0 is down, 1 is up + mplew.writeInt(message); + return mplew.getPacket(); + } + + public static byte[] coconutScore(int team1, int team2) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(6); + mplew.writeShort(SendOpcode.COCONUT_SCORE.getValue()); + mplew.writeShort(team1); + mplew.writeShort(team2); + return mplew.getPacket(); + } + + public static byte[] hitCoconut(boolean spawn, int id, int type) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(7); + mplew.writeShort(SendOpcode.COCONUT_HIT.getValue()); + if (spawn) { + mplew.writeShort(-1); + mplew.writeShort(5000); + mplew.write(0); + } else { + mplew.writeShort(id); + mplew.writeShort(1000);//delay till you can attack again! + mplew.write(type); // What action to do for the coconut. + } + return mplew.getPacket(); + } + + public static byte[] customPacket(String packet) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.write(HexTool.getByteArrayFromHexString(packet)); + return mplew.getPacket(); + } + + public static byte[] customPacket(byte[] packet) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(packet.length); + mplew.write(packet); + return mplew.getPacket(); + } + + public static byte[] spawnGuide(boolean spawn) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(3); + mplew.writeShort(SendOpcode.SPAWN_GUIDE.getValue()); + if (spawn) { + mplew.write(1); + } else { + mplew.write(0); + } + return mplew.getPacket(); + } + + public static byte[] talkGuide(String talk) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.TALK_GUIDE.getValue()); + mplew.write(0); + mplew.writeMapleAsciiString(talk); + mplew.write(new byte[]{(byte) 0xC8, 0, 0, 0, (byte) 0xA0, (byte) 0x0F, 0, 0}); + return mplew.getPacket(); + } + + public static byte[] guideHint(int hint) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(11); + mplew.writeShort(SendOpcode.TALK_GUIDE.getValue()); + mplew.write(1); + mplew.writeInt(hint); + mplew.writeInt(7000); + return mplew.getPacket(); + } + + public static void addCashItemInformation(final MaplePacketLittleEndianWriter mplew, Item item, int accountId) { + addCashItemInformation(mplew, item, accountId, null); + } + + public static void addCashItemInformation(final MaplePacketLittleEndianWriter mplew, Item item, int accountId, String giftMessage) { + boolean isGift = giftMessage != null; + boolean isRing = false; + Equip equip = null; + if (item.getType() == 1) { + equip = (Equip) item; + isRing = equip.getRingId() > -1; + } + mplew.writeLong(item.getPetId() > -1 ? item.getPetId() : isRing ? equip.getRingId() : item.getCashId()); + if (!isGift) { + mplew.writeInt(accountId); + mplew.writeInt(0); + } + mplew.writeInt(item.getItemId()); + if (!isGift) { + mplew.writeInt(item.getSN()); + mplew.writeShort(item.getQuantity()); + } + mplew.writeAsciiString(StringUtil.getRightPaddedStr(item.getGiftFrom(), '\0', 13)); + if (isGift) { + mplew.writeAsciiString(StringUtil.getRightPaddedStr(giftMessage, '\0', 73)); + return; + } + addExpirationTime(mplew, item.getExpiration()); + mplew.writeLong(0); + } + + public static byte[] showWishList(MapleCharacter mc, boolean update) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.CASHSHOP_OPERATION.getValue()); + + if (update) { + mplew.write(0x55); + } else { + mplew.write(0x4F); + } + + for (int sn : mc.getCashShop().getWishList()) { + mplew.writeInt(sn); + } + + for (int i = mc.getCashShop().getWishList().size(); i < 10; i++) { + mplew.writeInt(0); + } + + return mplew.getPacket(); + } + + public static byte[] showBoughtCashItem(Item item, int accountId) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.CASHSHOP_OPERATION.getValue()); + + mplew.write(0x57); + addCashItemInformation(mplew, item, accountId); + + return mplew.getPacket(); + } + + /* + * 00 = Due to an unknown error, failed + * A4 = Due to an unknown error, failed + warpout + * A5 = You don't have enough cash. + * A6 = long as shet msg + * A7 = You have exceeded the allotted limit of price for gifts. + * A8 = You cannot send a gift to your own account. Log in on the char and purchase + * A9 = Please confirm whether the character's name is correct. + * AA = Gender restriction! + * //Skipped a few + * B0 = Wrong Coupon Code + * B1 = Disconnect from CS because of 3 wrong coupon codes < lol + * B2 = Expired Coupon + * B3 = Coupon has been used already + * B4 = Nexon internet cafes? lolfk + * + * BB = inv full + * C2 = not enough mesos? Lol not even 1 mesos xD + */ + public static byte[] showCashShopMessage(byte message) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(4); + mplew.writeShort(SendOpcode.CASHSHOP_OPERATION.getValue()); + + mplew.write(0x5C); + mplew.write(message); + + return mplew.getPacket(); + } + + public static byte[] showCashInventory(MapleClient c) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.CASHSHOP_OPERATION.getValue()); + + mplew.write(0x4B); + mplew.writeShort(c.getPlayer().getCashShop().getInventory().size()); + + for (Item item : c.getPlayer().getCashShop().getInventory()) { + addCashItemInformation(mplew, item, c.getAccID()); + } + + mplew.writeShort(c.getPlayer().getStorage().getSlots()); + mplew.writeShort(c.getCharacterSlots()); + + return mplew.getPacket(); + } + + public static byte[] showGifts(List> gifts) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.CASHSHOP_OPERATION.getValue()); + + mplew.write(0x4D); + mplew.writeShort(gifts.size()); + + for (Pair gift : gifts) { + addCashItemInformation(mplew, gift.getLeft(), 0, gift.getRight()); + } + + return mplew.getPacket(); + } + + public static byte[] showGiftSucceed(String to, CashItem item) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.CASHSHOP_OPERATION.getValue()); + + mplew.write(0x5E); //0x5D, Couldn't be sent + mplew.writeMapleAsciiString(to); + mplew.writeInt(item.getItemId()); + mplew.writeShort(item.getCount()); + mplew.writeInt(item.getPrice()); + + return mplew.getPacket(); + } + + public static byte[] showBoughtInventorySlots(int type, short slots) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(6); + mplew.writeShort(SendOpcode.CASHSHOP_OPERATION.getValue()); + + mplew.write(0x60); + mplew.write(type); + mplew.writeShort(slots); + + return mplew.getPacket(); + } + + public static byte[] showBoughtStorageSlots(short slots) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(5); + mplew.writeShort(SendOpcode.CASHSHOP_OPERATION.getValue()); + + mplew.write(0x62); + mplew.writeShort(slots); + + return mplew.getPacket(); + } + + public static byte[] showBoughtCharacterSlot(short slots) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(5); + mplew.writeShort(SendOpcode.CASHSHOP_OPERATION.getValue()); + + mplew.write(0x64); + mplew.writeShort(slots); + + return mplew.getPacket(); + } + + public static byte[] takeFromCashInventory(Item item) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.CASHSHOP_OPERATION.getValue()); + + mplew.write(0x68); + mplew.writeShort(item.getPosition()); + addItemInfo(mplew, item, true); + + return mplew.getPacket(); + } + + public static byte[] putIntoCashInventory(Item item, int accountId) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.CASHSHOP_OPERATION.getValue()); + + mplew.write(0x6A); + addCashItemInformation(mplew, item, accountId); + + return mplew.getPacket(); + } + + public static byte[] openCashShop(MapleClient c, boolean mts) throws Exception { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(mts ? SendOpcode.SET_ITC.getValue() : SendOpcode.SET_CASH_SHOP.getValue()); + + addCharacterInfo(mplew, c.getPlayer()); + + if (!mts) { + mplew.write(1); + } + + mplew.writeMapleAsciiString(c.getAccountName()); + if (mts) { + mplew.write(new byte[]{(byte) 0x88, 19, 0, 0, 7, 0, 0, 0, (byte) 0xF4, 1, 0, 0, (byte) 0x18, 0, 0, 0, (byte) 0xA8, 0, 0, 0, (byte) 0x70, (byte) 0xAA, (byte) 0xA7, (byte) 0xC5, (byte) 0x4E, (byte) 0xC1, (byte) 0xCA, 1}); + } else { + mplew.writeInt(0); + List lsci = CashItemFactory.getSpecialCashItems(); + mplew.writeShort(lsci.size());//Guess what + for (SpecialCashItem sci : lsci) { + mplew.writeInt(sci.getSN()); + mplew.writeInt(sci.getModifier()); + mplew.write(sci.getInfo()); + } + mplew.skip(121); + + for (int i = 1; i <= 8; i++) { + for (int j = 0; j < 2; j++) { + mplew.writeInt(i); + mplew.writeInt(j); + mplew.writeInt(50200004); + + mplew.writeInt(i); + mplew.writeInt(j); + mplew.writeInt(50200069); + + mplew.writeInt(i); + mplew.writeInt(j); + mplew.writeInt(50200117); + + mplew.writeInt(i); + mplew.writeInt(j); + mplew.writeInt(50100008); + + mplew.writeInt(i); + mplew.writeInt(j); + mplew.writeInt(50000047); + } + } + + mplew.writeInt(0); + mplew.writeShort(0); + mplew.write(0); + mplew.writeInt(75); + } + return mplew.getPacket(); + } + + public static byte[] resetForcedStats() { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(2); + mplew.writeShort(SendOpcode.FORCED_STAT_RESET.getValue()); + return mplew.getPacket(); + } + + public static byte[] showCombo(int count) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(6); + mplew.writeShort(SendOpcode.SHOW_COMBO.getValue()); + mplew.writeInt(count); + return mplew.getPacket(); + } + + public static byte[] earnTitleMessage(String msg) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SCRIPT_PROGRESS_MESSAGE.getValue()); + mplew.writeMapleAsciiString(msg); + return mplew.getPacket(); + } + + public static byte[] startCPQ(MapleCharacter chr, MonsterCarnivalParty enemy) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(25); + mplew.writeShort(SendOpcode.MONSTER_CARNIVAL_START.getValue()); + mplew.write(chr.getTeam()); //team + mplew.writeShort(chr.getCP()); //Obtained CP - Used CP + mplew.writeShort(chr.getObtainedCP()); //Total Obtained CP + mplew.writeShort(chr.getCarnivalParty().getAvailableCP()); //Obtained CP - Used CP of the team + mplew.writeShort(chr.getCarnivalParty().getTotalCP()); //Total Obtained CP of the team + mplew.writeShort(enemy.getAvailableCP()); //Obtained CP - Used CP of the team + mplew.writeShort(enemy.getTotalCP()); //Total Obtained CP of the team + mplew.writeShort(0); //Probably useless nexon shit + mplew.writeLong(0); //Probably useless nexon shit + return mplew.getPacket(); + } + + public static byte[] updateCP(int cp, int tcp) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(6); + mplew.writeShort(SendOpcode.MONSTER_CARNIVAL_OBTAINED_CP.getValue()); + mplew.writeShort(cp); //Obtained CP - Used CP + mplew.writeShort(tcp); //Total Obtained CP + return mplew.getPacket(); + } + + public static byte[] updatePartyCP(MonsterCarnivalParty party) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(7); + mplew.writeShort(SendOpcode.MONSTER_CARNIVAL_PARTY_CP.getValue()); + mplew.write(party.getTeam()); //Team where the points are given to. + mplew.writeShort(party.getAvailableCP()); //Obtained CP - Used CP + mplew.writeShort(party.getTotalCP()); //Total Obtained CP + return mplew.getPacket(); + } + + public static byte[] CPQSummon(int tab, int number, String name) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.MONSTER_CARNIVAL_SUMMON.getValue()); + mplew.write(tab); //Tab + mplew.writeShort(number); //Number of summon inside the tab + mplew.writeMapleAsciiString(name); //Name of the player that summons + return mplew.getPacket(); + } + + public static byte[] CPQDied(MapleCharacter chr) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.MONSTER_CARNIVAL_SUMMON.getValue()); + mplew.write(chr.getTeam()); //Team + mplew.writeMapleAsciiString(chr.getName()); //Name of the player that died + mplew.write(chr.getAndRemoveCP()); //Lost CP + return mplew.getPacket(); + } + + /** + * Sends a CPQ Message
+ * + * Possible values for message:
1: You don't have enough CP + * to continue.
2: You can no longer summon the Monster.
3: You can + * no longer summon the being.
4: This being is already summoned.
5: + * This request has failed due to an unknown error.
+ * + * @param message Displays a message inside Carnival PQ + * + */ + public static byte[] CPQMessage(byte message) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(3); + mplew.writeShort(SendOpcode.MONSTER_CARNIVAL_MESSAGE.getValue()); + mplew.write(message); //Message + return mplew.getPacket(); + } + + public static byte[] leaveCPQ(MapleCharacter chr) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.MONSTER_CARNIVAL_LEAVE.getValue()); + mplew.write(0); //Something + mplew.write(chr.getTeam()); //Team + mplew.writeMapleAsciiString(chr.getName()); //Player name + return mplew.getPacket(); + } + + public static byte[] sheepRanchInfo(byte wolf, byte sheep) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SHEEP_RANCH_INFO.getValue()); + mplew.write(wolf); + mplew.write(sheep); + return mplew.getPacket(); + } + //Know what this is? ?? >=) + + public static byte[] sheepRanchClothes(int id, byte clothes) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SHEEP_RANCH_CLOTHES.getValue()); + mplew.writeInt(id); //Character id + mplew.write(clothes); //0 = sheep, 1 = wolf, 2 = Spectator (wolf without wool) + return mplew.getPacket(); + } + + public static byte[] incubatorResult() {//lol + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(8); + mplew.writeShort(SendOpcode.INCUBATOR_RESULT.getValue()); + mplew.skip(6); + return mplew.getPacket(); + } + + public static byte[] pyramidGauge(int gauge) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(6); + mplew.writeShort(SendOpcode.PYRAMID_GAUGE.getValue()); + mplew.writeInt(gauge); + return mplew.getPacket(); + } + // f2 + + public static byte[] pyramidScore(byte score, int exp) {//Type cannot be higher than 4 (Rank D), otherwise you'll crash + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(7); + mplew.writeShort(SendOpcode.PYRAMID_SCORE.getValue()); + mplew.write(score); + mplew.writeInt(exp); + return mplew.getPacket(); + } + + public static byte[] spawnDragon(MapleDragon dragon) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SPAWN_DRAGON.getValue()); + mplew.writeInt(dragon.getOwner().getId());//objectid = owner id + mplew.writeShort(dragon.getPosition().x); + mplew.writeShort(0); + mplew.writeShort(dragon.getPosition().y); + mplew.writeShort(0); + mplew.write(dragon.getStance()); + mplew.write(0); + mplew.writeShort(dragon.getOwner().getJob().getId()); + return mplew.getPacket(); + } + + public static byte[] moveDragon(MapleDragon dragon, Point startPos, List res) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.MOVE_DRAGON.getValue()); + mplew.writeInt(dragon.getOwner().getId()); + mplew.writePos(startPos); + serializeMovementList(mplew, res); + return mplew.getPacket(); + } + + /** + * Sends a request to remove Mir
+ * + * @param charid - Needs the specific Character ID + * @return The packet + * + */ + public static byte[] removeDragon(int chrid) { + final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.REMOVE_DRAGON.getValue()); + mplew.writeInt(chrid); + return mplew.getPacket(); + } + + /** + * Changes the current background effect to either being rendered or not. + * Data is still missing, so this is pretty binary at the moment in how it + * behaves. + * + * @param remove whether or not the remove or add the specified layer. + * @param layer the targeted layer for removal or addition. + * @param transition the time it takes to transition the effect. + * + * @return a packet to change the background effect of a specified layer. + */ + public static byte[] changeBackgroundEffect(boolean remove, int layer, int transition) { + MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); + mplew.writeShort(SendOpcode.SET_BACK_EFFECT.getValue()); + mplew.writeBool(remove); + mplew.writeInt(0); // not sure what this int32 does yet + mplew.write(layer); + mplew.writeInt(transition); + return mplew.getPacket(); + } }