package handling; import client.MapleCharacter; import client.MapleClient; import client.inventory.Item; import client.inventory.MaplePet; import client.inventory.PetDataFactory; import constants.GameConstants; import constants.ServerConstants; import handling.cashshop.CashShopServer; import handling.cashshop.handler.CashShopOperation; import handling.cashshop.handler.MTSOperation; import handling.channel.ChannelServer; import handling.channel.handler.AllianceHandler; import handling.channel.handler.BBSHandler; import handling.channel.handler.BuddyListHandler; import handling.channel.handler.ChatHandler; import handling.channel.handler.DueyHandler; import handling.channel.handler.FamilyHandler; import handling.channel.handler.GuildHandler; import handling.channel.handler.HiredMerchantHandler; import handling.channel.handler.InterServerHandler; import handling.channel.handler.InventoryHandler; import handling.channel.handler.ItemMakerHandler; import handling.channel.handler.MobHandler; import handling.channel.handler.MonsterCarnivalHandler; import handling.channel.handler.NPCHandler; import handling.channel.handler.PartyHandler; import handling.channel.handler.PetHandler; import handling.channel.handler.PlayerHandler; import handling.channel.handler.PlayerInteractionHandler; import handling.channel.handler.PlayersHandler; import handling.channel.handler.StatsHandling; import handling.channel.handler.SummonHandler; import handling.channel.handler.UserInterfaceHandler; import handling.login.LoginServer; import handling.login.handler.CharLoginHandler; import handling.mina.MaplePacketDecoder; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.lang.management.ManagementFactory; import java.util.ArrayList; import java.util.EnumSet; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.ReentrantReadWriteLock; import javax.management.InstanceAlreadyExistsException; import javax.management.MBeanRegistrationException; import javax.management.MBeanServer; import javax.management.MalformedObjectNameException; import javax.management.NotCompliantMBeanException; import javax.management.ObjectName; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; import scripting.NPCScriptManager; import server.CashItemFactory; import server.CashItemInfo; import server.MTSStorage; import server.Randomizer; import tools.FileoutputUtil; import tools.HexTool; import tools.MapleAESOFB; import tools.Pair; import tools.StringUtil; import tools.data.ByteArrayByteStream; import tools.data.LittleEndianAccessor; import tools.packet.CField; import tools.packet.CWvsContext; import tools.packet.LoginPacket; import tools.packet.MTSCSPacket; public class MapleServerHandler extends IoHandlerAdapter implements MapleServerHandlerMBean { public static boolean Log_Packets = false; private int channel = -1; private static int numDC = 0; private static long lastDC = System.currentTimeMillis(); private boolean cs; private boolean farm; private final List<String> BlockedIP = new ArrayList<>(); private final Map<String, Pair<Long, Byte>> tracker = new ConcurrentHashMap<>(); private static final EnumSet<RecvPacketOpcode> blocked = EnumSet.noneOf(RecvPacketOpcode.class), sBlocked = EnumSet.noneOf(RecvPacketOpcode.class); // <editor-fold defaultstate="collapsed" desc="Packet Log Implementation"> private static final int Log_Size = 10000, Packet_Log_Size = 25; private static final ArrayList<LoggedPacket> Packet_Log = new ArrayList<>(Log_Size); private static final ReentrantReadWriteLock Packet_Log_Lock = new ReentrantReadWriteLock(); private static String Packet_Log_Output = "/var/www/logs/"; private static int Packet_Log_Index = 0; public static void log(String packet, String op, MapleClient c, IoSession io) { try { Packet_Log_Lock.writeLock().lock(); LoggedPacket logged = null; if (Packet_Log.size() == Log_Size) { logged = Packet_Log.remove(0); } //This way, we don't create new LoggedPacket objects, we reuse them =] if (logged == null) { logged = new LoggedPacket(packet, op, io.getRemoteAddress().toString(), c == null ? -1 : c.getAccID(), FileoutputUtil.CurrentReadable_Time(), c == null || c.getAccountName() == null ? "[Null]" : c.getAccountName(), c == null || c.getPlayer() == null || c.getPlayer().getName() == null ? "[Null]" : c.getPlayer().getName(), c == null || c.getPlayer() == null || c.getPlayer().getMap() == null ? "[Null]" : String.valueOf(c.getPlayer().getMapId()), c == null || NPCScriptManager.getInstance().getCM(c) == null ? "[Null]" : String.valueOf(NPCScriptManager.getInstance().getCM(c).getNpc())); } else { logged.setInfo(packet, op, io.getRemoteAddress().toString(), c == null ? -1 : c.getAccID(), FileoutputUtil.CurrentReadable_Time(), c == null || c.getAccountName() == null ? "[Null]" : c.getAccountName(), c == null || c.getPlayer() == null || c.getPlayer().getName() == null ? "[Null]" : c.getPlayer().getName(), c == null || c.getPlayer() == null || c.getPlayer().getMap() == null ? "[Null]" : String.valueOf(c.getPlayer().getMapId()), c == null || NPCScriptManager.getInstance().getCM(c) == null ? "[Null]" : String.valueOf(NPCScriptManager.getInstance().getCM(c).getNpc())); } Packet_Log.add(logged); } finally { Packet_Log_Lock.writeLock().unlock(); } } private static class LoggedPacket { private static final String nl = System.getProperty("line.separator"); private String ip, accName, accId, chrName, packet, mapId, npcId, op, time; private long timestamp; public LoggedPacket(String p, String op, String ip, int id, String time, String accName, String chrName, String mapId, String npcId) { setInfo(p, op, ip, id, time, accName, chrName, mapId, npcId); } public final void setInfo(String p, String op, String ip, int id, String time, String accName, String chrName, String mapId, String npcId) { this.ip = ip; this.op = op; this.time = time; this.packet = p; this.accName = accName; this.chrName = chrName; this.mapId = mapId; this.npcId = npcId; timestamp = System.currentTimeMillis(); this.accId = String.valueOf(id); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("[IP: ").append(ip).append("] [").append(accId).append('|').append(accName).append('|').append(chrName).append("] [").append(npcId).append('|').append(mapId).append("] [Time: ").append(timestamp).append("] [").append(time).append(']'); sb.append(nl); sb.append("[Op: ").append(op).append("] [").append(packet).append(']'); return sb.toString(); } } public static void registerMBean() { MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer(); try { MapleServerHandler mbean = new MapleServerHandler(); //The log is a static object, so we can just use this hacky method. mBeanServer.registerMBean(mbean, new ObjectName("handling:type=MapleServerHandler")); } catch (MalformedObjectNameException | InstanceAlreadyExistsException | MBeanRegistrationException | NotCompliantMBeanException e) { System.out.println("Error registering PacketLog MBean"); } } @Override public void writeLog() { writeLog(false); } public void writeLog(boolean crash) { Packet_Log_Lock.readLock().lock(); try { try (FileWriter fw = new FileWriter(new File(Packet_Log_Output + Packet_Log_Index + (crash ? "_DC.txt" : ".txt")), true)) { String nl = System.getProperty("line.separator"); for (LoggedPacket loggedPacket : Packet_Log) { fw.write(loggedPacket.toString()); fw.write(nl); } final String logString = "Log has been written at " + lastDC + " [" + FileoutputUtil.CurrentReadable_Time() + "] - " + numDC + " have disconnected, within " + (System.currentTimeMillis() - lastDC) + " milliseconds. (" + System.currentTimeMillis() + ")"; System.out.println(logString); fw.write(logString); fw.write(nl); fw.flush(); } Packet_Log.clear(); Packet_Log_Index++; if (Packet_Log_Index > Packet_Log_Size) { Packet_Log_Index = 0; Log_Packets = false; } } catch (IOException ex) { System.out.println("Error writing log to file."); } finally { Packet_Log_Lock.readLock().unlock(); } } public static void initiate() { //RecvPacketOpcode[] block = new RecvPacketOpcode[]{RecvPacketOpcode.NPC_ACTION, RecvPacketOpcode.MOVE_PLAYER, RecvPacketOpcode.PONG, RecvPacketOpcode.MOVE_PET, RecvPacketOpcode.MOVE_SUMMON, RecvPacketOpcode.MOVE_DRAGON, RecvPacketOpcode.MOVE_LIFE, RecvPacketOpcode.MOVE_ANDROID, RecvPacketOpcode.HEAL_OVER_TIME, RecvPacketOpcode.AUTO_AGGRO, RecvPacketOpcode.CANCEL_DEBUFF, RecvPacketOpcode.MOVE_FAMILIAR}; // RecvPacketOpcode[] serverBlock = new RecvPacketOpcode[]{RecvPacketOpcode.CHANGE_KEYMAP, RecvPacketOpcode.ITEM_PICKUP, RecvPacketOpcode.PET_LOOT, RecvPacketOpcode.TAKE_DAMAGE, RecvPacketOpcode.FACE_EXPRESSION, RecvPacketOpcode.USE_ITEM, RecvPacketOpcode.CLOSE_RANGE_ATTACK, RecvPacketOpcode.MAGIC_ATTACK, RecvPacketOpcode.RANGED_ATTACK, RecvPacketOpcode.ARAN_COMBO, RecvPacketOpcode.SPECIAL_MOVE, RecvPacketOpcode.GENERAL_CHAT, RecvPacketOpcode.MONSTER_BOMB, RecvPacketOpcode.PASSIVE_ENERGY, RecvPacketOpcode.PET_AUTO_POT, RecvPacketOpcode.USE_CASH_ITEM, RecvPacketOpcode.PARTYCHAT, RecvPacketOpcode.CANCEL_BUFF, RecvPacketOpcode.SKILL_EFFECT, RecvPacketOpcode.CHAR_INFO_REQUEST, RecvPacketOpcode.ALLIANCE_OPERATION, RecvPacketOpcode.AUTO_ASSIGN_AP, RecvPacketOpcode.DISTRIBUTE_AP, RecvPacketOpcode.USE_MAGNIFY_GLASS, RecvPacketOpcode.SPAWN_PET, RecvPacketOpcode.SUMMON_ATTACK, RecvPacketOpcode.ITEM_MOVE, RecvPacketOpcode.PARTY_SEARCH_STOP}; // blocked.addAll(Arrays.asList(block)); // sBlocked.addAll(Arrays.asList(serverBlock)); if (Log_Packets) { for (int i = 1; i <= Packet_Log_Size; i++) { if (!(new File(Packet_Log_Output + i + ".txt")).exists() && !(new File(Packet_Log_Output + i + "_DC.txt")).exists()) { Packet_Log_Index = i; break; } } // if (Packet_Log_Index <= 0) { //25+ files, do not log // Log_Packets = false; // } } registerMBean(); } public MapleServerHandler() { //ONLY FOR THE MBEAN } // </editor-fold> public MapleServerHandler(final int channel, final boolean cs, final boolean farm) { this.channel = channel; this.cs = cs; this.farm = farm; } @Override public void exceptionCaught(final IoSession session, final Throwable cause) throws Exception { MapleClient client = (MapleClient) session.getAttribute(MapleClient.CLIENT_KEY); FileoutputUtil.log("exceptionCaught.txt", MapleClient.getLogMessage(client, cause.getMessage()) + "\n" + cause); cause.printStackTrace(); } @Override public void sessionOpened(IoSession session) { StringBuilder pSb = new StringBuilder(); pSb.append("IoSession With " + session.getRemoteAddress() + " Opened"); System.out.println(pSb); byte pAESKey[] = {0x46, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x3C, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xA3, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xB6, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x2F, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xAE, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x57, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xB7, (byte) 0x00, (byte) 0x00, (byte) 0x00 }; byte ivRecv[] = {70, 114, 122, 82}; byte ivSend[] = {82, 48, 120, 115}; ivRecv[3] = (byte) (Math.random() * 255); ivSend[3] = (byte) (Math.random() * 255); MapleAESOFB sendCypher = new MapleAESOFB(pAESKey, ivSend, (short) (0xFFFF - ServerConstants.MAPLE_VERSION)); MapleAESOFB recvCypher = new MapleAESOFB(pAESKey, ivRecv, (short) ServerConstants.MAPLE_VERSION); MapleClient client = new MapleClient(sendCypher, recvCypher, session); client.setChannel(channel); session.write(LoginPacket.getHello(ivSend, ivRecv)); session.setAttribute(MapleClient.CLIENT_KEY, client); } @Override public void sessionClosed(final IoSession session) throws Exception { final MapleClient client = (MapleClient) session.getAttribute(MapleClient.CLIENT_KEY); if (client != null) { byte state = MapleClient.CHANGE_CHANNEL; if (Log_Packets && !LoginServer.isShutdown() && !cs && channel > -1) { state = client.getLoginState(); } if (state != MapleClient.CHANGE_CHANNEL) { log("Data: " + numDC, "CLOSED", client, session); if (System.currentTimeMillis() - lastDC < 600000) { //within the minute numDC++; if (numDC >= 1) { //100+ people have dc'd in minute in channelserver System.out.println("Writing log..."); writeLog(); numDC = 0; lastDC = System.currentTimeMillis(); //intentionally place here } } else { numDC = 0; lastDC = System.currentTimeMillis(); //intentionally place here } } try { client.disconnect(true, cs); } finally { session.close(true); session.removeAttribute(MapleClient.CLIENT_KEY); } } super.sessionClosed(session); } @Override public void sessionIdle(final IoSession session, final IdleStatus status) throws Exception { //final MapleClient client = (MapleClient) session.getAttribute(MapleClient.CLIENT_KEY); /* if (client != null && client.getPlayer() != null) { System.out.println("Player "+ client.getPlayer().getName() +" went idle"); }*/ // if (client != null) { // client.sendPing(); // } //super.sessionIdle(session, status); } @Override public void messageReceived(final IoSession session, final Object message) { if (message == null || session == null) { return; } final LittleEndianAccessor slea = new LittleEndianAccessor(new ByteArrayByteStream((byte[]) message)); if (slea.available() < 2) { return; } final MapleClient c = (MapleClient) session.getAttribute(MapleClient.CLIENT_KEY); if (c == null || !c.isReceiving()) { return; } final short pHeader = slea.readShort(); for (final RecvPacketOpcode recv : RecvPacketOpcode.values()) { if (recv.getValue() == pHeader) { if (recv.NeedsChecking()) { if (!c.isLoggedIn()) { return; } } try { final StringBuilder sb = new StringBuilder("Received Data :\n"); sb.append(HexTool.toString((byte[]) message)).append("\n").append(HexTool.toStringFromAscii((byte[]) message)); System.out.println(sb.toString()); handlePacket(recv, slea, c, cs, farm); return; } catch(Exception Ex) { Ex.getMessage(); } } } } public static void handlePacket(RecvPacketOpcode header, LittleEndianAccessor slea, MapleClient c, final boolean cs, final boolean farm) throws Exception { switch (header) { case PONG: c.pongReceived(); break; case STRANGE_DATA: break; case CLIENT_START: CharLoginHandler.login("admin", c, "admin"); c.getSession().write(LoginPacket.getAuthSuccessRequest(c)); break; case LOGIN_PASSWORD: CharLoginHandler.login(slea, c); break; case AUTH_REQUEST: int pRequest = slea.readInt(); int pResponse; pResponse = ((pRequest >> 5) << 5) + (((((pRequest & 0x1F) >> 3) ^ 2) << 3) + (7 - (pRequest & 7))); pResponse |= ((pRequest >> 7) << 7); pResponse -= 1; c.getSession().write(CField.getClientAuth(pResponse)); break; case VIEW_SERVERLIST: if (slea.readByte() == 0) { CharLoginHandler.ServerListRequest(c); } break; case REDISPLAY_SERVERLIST: case SERVERLIST_REQUEST: CharLoginHandler.ServerListRequest(c); break; case CLIENT_HELLO: if (slea.readByte() != 8 || slea.readShort() != ServerConstants.MAPLE_VERSION || !String.valueOf(slea.readShort()).equals(ServerConstants.MAPLE_PATCH)) { c.getSession().close(true); } break; case CHARLIST_REQUEST: CharLoginHandler.CharlistRequest(slea, c); break; case SERVERSTATUS_REQUEST: CharLoginHandler.ServerStatusRequest(c); break; case CHECK_CHAR_NAME: CharLoginHandler.CheckCharName(slea.readMapleAsciiString(), c); break; case CREATE_CHAR: CharLoginHandler.CreateChar(slea, c); break; case DELETE_CHAR: CharLoginHandler.DeleteChar(slea, c); break; case CHAR_SELECT_NO_PIC: CharLoginHandler.Character_WithoutSecondPassword(slea, c, false, false); break; case VIEW_REGISTER_PIC: CharLoginHandler.Character_WithoutSecondPassword(slea, c, true, true); break; case CHAR_SELECT: CharLoginHandler.Character_WithoutSecondPassword(slea, c, true, false); break; case VIEW_SELECT_PIC: System.out.println("Going to handle"); CharLoginHandler.Character_WithSecondPassword(slea, c, true); break; case AUTH_SECOND_PASSWORD: CharLoginHandler.Character_WithSecondPassword(slea, c, false); break; case CHARACTER_CARD: CharLoginHandler.updateCCards(slea, c); break; case CLIENT_ERROR: //might not be correct if (slea.available() >= 6L) { slea.skip(6); short badPacketSize = slea.readShort(); slea.skip(4); int pHeader = slea.readShort(); String pHeaderStr = Integer.toHexString(pHeader).toUpperCase(); pHeaderStr = StringUtil.getLeftPaddedStr(pHeaderStr, '0', 4); String op = SendPacketOpcode.getOpcodeName(pHeader); String from = ""; if (c.getPlayer() != null) { from = new StringBuilder().append("Chr: ").append(c.getPlayer().getName()).append(" LVL(").append(c.getPlayer().getLevel()).append(") job: ").append(c.getPlayer().getJob()).append(" MapID: ").append(c.getPlayer().getMapId()).toString(); if (c.getPlayer() != null) { from = new StringBuilder().append(from).append(" MAPCHR: ").toString(); for (ChannelServer css : ChannelServer.getAllInstances()) { if ((css.getChannel() == c.getChannel()) && (css.getPlayerStorage().getAllCharacters().size() > 0)) { for (MapleCharacter chrss : css.getPlayerStorage().getAllCharacters()) { if (chrss.getMapId() == c.getPlayer().getMapId()) { from = new StringBuilder().append(from).append(chrss.getName()).append("[").append(chrss.getId()).append("] ,Lv").append(chrss.getLevel()).append(",job:").append(chrss.getJob()).append(" .").toString(); } } } } } } String Recv = new StringBuilder().append(from).append("\r\n").append("SendOP(-38): ").append(op).append(" [").append(pHeaderStr).append("] (").append(badPacketSize - 4).append(")").append(slea.toString(false)).append("\r\n\r\n").toString(); FileoutputUtil.log("38.txt", Recv); } break; case ENABLE_SPECIAL_CREATION: c.getSession().write(LoginPacket.enableSpecialCreation(c.getAccID(), true)); break; case RSA_KEY: break; case CHANGE_CHANNEL: case CHANGE_ROOM_CHANNEL: InterServerHandler.ChangeChannel(slea, c, c.getPlayer(), header == RecvPacketOpcode.CHANGE_ROOM_CHANNEL); break; case PLAYER_LOGGEDIN: slea.readInt(); final int playerid = slea.readInt(); if (cs) { CashShopOperation.EnterCS(playerid, c); } else { InterServerHandler.Loggedin(playerid, c); } break; case ENTER_PVP: case ENTER_PVP_PARTY: PlayersHandler.EnterPVP(slea, c); break; case PVP_RESPAWN: PlayersHandler.RespawnPVP(slea, c); break; case LEAVE_PVP: PlayersHandler.LeavePVP(slea, c); break; case PVP_ATTACK: PlayersHandler.AttackPVP(slea, c); break; case PVP_SUMMON: SummonHandler.SummonPVP(slea, c); break; case ENTER_CASH_SHOP: InterServerHandler.EnterCS(c, c.getPlayer(), false); break; case MOVE_PLAYER: PlayerHandler.MovePlayer(slea, c, c.getPlayer()); break; case CHAR_INFO_REQUEST: slea.readInt(); PlayerHandler.CharInfoRequest(slea.readInt(), c, c.getPlayer()); break; case CLOSE_RANGE_ATTACK: PlayerHandler.closeRangeAttack(slea, c, c.getPlayer(), false); break; case RANGED_ATTACK: PlayerHandler.rangedAttack(slea, c, c.getPlayer()); break; case MAGIC_ATTACK: PlayerHandler.MagicDamage(slea, c, c.getPlayer()); break; case SPECIAL_MOVE: PlayerHandler.SpecialMove(slea, c, c.getPlayer()); break; case PASSIVE_ENERGY: PlayerHandler.closeRangeAttack(slea, c, c.getPlayer(), false); break; case GET_BOOK_INFO: PlayersHandler.MonsterBookInfoRequest(slea, c, c.getPlayer()); break; case MONSTER_BOOK_DROPS: PlayersHandler.MonsterBookDropsRequest(slea, c, c.getPlayer()); break; case CHANGE_CODEX_SET: PlayersHandler.ChangeSet(slea, c, c.getPlayer()); break; case PROFESSION_INFO: ItemMakerHandler.ProfessionInfo(slea, c); break; case CRAFT_DONE: ItemMakerHandler.CraftComplete(slea, c, c.getPlayer()); break; case CRAFT_MAKE: ItemMakerHandler.CraftMake(slea, c, c.getPlayer()); break; case CRAFT_EFFECT: ItemMakerHandler.CraftEffect(slea, c, c.getPlayer()); break; case START_HARVEST: ItemMakerHandler.StartHarvest(slea, c, c.getPlayer()); break; case STOP_HARVEST: ItemMakerHandler.StopHarvest(slea, c, c.getPlayer()); break; case MAKE_EXTRACTOR: ItemMakerHandler.MakeExtractor(slea, c, c.getPlayer()); break; case USE_BAG: ItemMakerHandler.UseBag(slea, c, c.getPlayer()); break; case USE_FAMILIAR: MobHandler.UseFamiliar(slea, c, c.getPlayer()); break; case SPAWN_FAMILIAR: MobHandler.SpawnFamiliar(slea, c, c.getPlayer()); break; case RENAME_FAMILIAR: MobHandler.RenameFamiliar(slea, c, c.getPlayer()); break; case MOVE_FAMILIAR: MobHandler.MoveFamiliar(slea, c, c.getPlayer()); break; case ATTACK_FAMILIAR: MobHandler.AttackFamiliar(slea, c, c.getPlayer()); break; case TOUCH_FAMILIAR: MobHandler.TouchFamiliar(slea, c, c.getPlayer()); break; case USE_RECIPE: ItemMakerHandler.UseRecipe(slea, c, c.getPlayer()); break; case MOVE_HAKU: PlayerHandler.MoveHaku(slea, c, c.getPlayer()); break; case CHANGE_HAKU: PlayerHandler.ChangeHaku(slea, c, c.getPlayer()); break; case MOVE_ANDROID: PlayerHandler.MoveAndroid(slea, c, c.getPlayer()); break; case FACE_EXPRESSION: PlayerHandler.ChangeEmotion(slea.readInt(), c.getPlayer()); break; case FACE_ANDROID: PlayerHandler.ChangeAndroidEmotion(slea.readInt(), c.getPlayer()); break; case TAKE_DAMAGE: PlayerHandler.TakeDamage(slea, c, c.getPlayer()); break; case HEAL_OVER_TIME: PlayerHandler.Heal(slea, c.getPlayer()); break; case CANCEL_BUFF: PlayerHandler.CancelBuffHandler(slea.readInt(), c.getPlayer()); break; case MECH_CANCEL: PlayerHandler.CancelMech(slea, c.getPlayer()); break; case CANCEL_ITEM_EFFECT: PlayerHandler.CancelItemEffect(slea.readInt(), c.getPlayer()); break; case USE_TITLE: PlayerHandler.UseTitle(slea.readInt(), c, c.getPlayer()); break; case ANGELIC_CHANGE: PlayerHandler.ANGELICCHANGE(slea, c, c.getPlayer()); break; case USE_CHAIR: PlayerHandler.UseChair(slea.readInt(), c, c.getPlayer()); break; case CANCEL_CHAIR: PlayerHandler.CancelChair(slea.readShort(), c, c.getPlayer()); break; case WHEEL_OF_FORTUNE: break; case USE_ITEMEFFECT: PlayerHandler.UseItemEffect(slea.readInt(), c, c.getPlayer()); break; case SKILL_EFFECT: PlayerHandler.SkillEffect(slea, c.getPlayer()); break; case QUICK_SLOT: PlayerHandler.QuickSlot(slea, c.getPlayer()); break; case MESO_DROP: slea.readInt(); PlayerHandler.DropMeso(slea.readInt(), c.getPlayer()); break; case CHANGE_KEYMAP: PlayerHandler.ChangeKeymap(slea, c.getPlayer()); break; case UPDATE_ENV: break; case CHANGE_MAP: if (cs) { CashShopOperation.LeaveCS(slea, c, c.getPlayer()); } else { PlayerHandler.ChangeMap(slea, c, c.getPlayer()); } break; case CHANGE_MAP_SPECIAL: slea.skip(1); PlayerHandler.ChangeMapSpecial(slea.readMapleAsciiString(), c, c.getPlayer()); break; case USE_INNER_PORTAL: slea.skip(1); PlayerHandler.InnerPortal(slea, c, c.getPlayer()); break; case TROCK_ADD_MAP: PlayerHandler.TrockAddMap(slea, c, c.getPlayer()); break; case ARAN_COMBO: PlayerHandler.AranCombo(c, c.getPlayer(), 1); break; case SKILL_MACRO: PlayerHandler.ChangeSkillMacro(slea, c.getPlayer()); break; case GIVE_FAME: PlayersHandler.GiveFame(slea, c, c.getPlayer()); break; case TRANSFORM_PLAYER: PlayersHandler.TransformPlayer(slea, c, c.getPlayer()); break; case NOTE_ACTION: PlayersHandler.Note(slea, c.getPlayer()); break; case USE_DOOR: PlayersHandler.UseDoor(slea, c.getPlayer()); break; case USE_MECH_DOOR: PlayersHandler.UseMechDoor(slea, c.getPlayer()); break; case DAMAGE_REACTOR: PlayersHandler.HitReactor(slea, c); break; case CLICK_REACTOR: case TOUCH_REACTOR: PlayersHandler.TouchReactor(slea, c); break; case CLOSE_CHALKBOARD: c.getPlayer().setChalkboard(null); break; case ITEM_SORT: InventoryHandler.ItemSort(slea, c); break; case ITEM_GATHER: InventoryHandler.ItemGather(slea, c); break; case ITEM_MOVE: InventoryHandler.ItemMove(slea, c); break; case MOVE_BAG: InventoryHandler.MoveBag(slea, c); break; case SWITCH_BAG: InventoryHandler.SwitchBag(slea, c); break; case ITEM_MAKER: ItemMakerHandler.ItemMaker(slea, c); break; case ITEM_PICKUP: InventoryHandler.Pickup_Player(slea, c, c.getPlayer()); break; case USE_CASH_ITEM: InventoryHandler.UseCashItem(slea, c); break; case USE_ITEM: InventoryHandler.UseItem(slea, c, c.getPlayer()); break; case USE_COSMETIC: InventoryHandler.UseCosmetic(slea, c, c.getPlayer()); break; case USE_MAGNIFY_GLASS: InventoryHandler.UseMagnify(slea, c); break; case USE_SCRIPTED_NPC_ITEM: InventoryHandler.UseScriptedNPCItem(slea, c, c.getPlayer()); break; case USE_RETURN_SCROLL: InventoryHandler.UseReturnScroll(slea, c, c.getPlayer()); break; case USE_NEBULITE: InventoryHandler.UseNebulite(slea, c); break; case USE_ALIEN_SOCKET: InventoryHandler.UseAlienSocket(slea, c); break; case USE_ALIEN_SOCKET_RESPONSE: slea.skip(4); c.getSession().write(MTSCSPacket.useAlienSocket(false)); break; case VICIOUS_HAMMER: slea.skip(4); slea.skip(4); c.getSession().write(MTSCSPacket.ViciousHammer(false, 0)); break; case GOLDEN_HAMMER: InventoryHandler.UseGoldHammer(slea, c); break; case USE_NEBULITE_FUSION: InventoryHandler.UseNebuliteFusion(slea, c); break; case USE_UPGRADE_SCROLL: slea.readInt(); InventoryHandler.UseUpgradeScroll(slea.readShort(), slea.readShort(), slea.readShort(), c, c.getPlayer(), false, slea.readByte() > 0); break; case USE_FLAG_SCROLL: //maybe? slea.readInt(); InventoryHandler.UseSpecialScroll(slea, c.getPlayer()); break; case USE_POTENTIAL_SCROLL: case USE_EQUIP_SCROLL: slea.readInt(); InventoryHandler.UseUpgradeScroll(slea.readShort(), slea.readShort(), (short) 0, c, c.getPlayer(), false, slea.readByte() > 0); break; case USE_SUMMON_BAG: InventoryHandler.UseSummonBag(slea, c, c.getPlayer()); break; case USE_TREASURE_CHEST: InventoryHandler.UseTreasureChest(slea, c, c.getPlayer()); break; case USE_SKILL_BOOK: slea.readInt(); InventoryHandler.UseSkillBook((byte) slea.readShort(), slea.readInt(), c, c.getPlayer()); break; case USE_CATCH_ITEM: InventoryHandler.UseCatchItem(slea, c, c.getPlayer()); break; case USE_MOUNT_FOOD: InventoryHandler.UseMountFood(slea, c, c.getPlayer()); break; case REWARD_ITEM: InventoryHandler.UseRewardItem((byte) slea.readShort(), slea.readInt(), c, c.getPlayer()); break; case HYPNOTIZE_DMG: MobHandler.HypnotizeDmg(slea, c.getPlayer()); break; case MOB_NODE: MobHandler.MobNode(slea, c.getPlayer()); break; case DISPLAY_NODE: MobHandler.DisplayNode(slea, c.getPlayer()); break; case MOVE_LIFE: MobHandler.MoveMonster(slea, c, c.getPlayer()); break; case AUTO_AGGRO: MobHandler.AutoAggro(slea.readInt(), c.getPlayer()); break; case FRIENDLY_DAMAGE: MobHandler.FriendlyDamage(slea, c.getPlayer()); break; case REISSUE_MEDAL: PlayerHandler.ReIssueMedal(slea, c, c.getPlayer()); break; case MONSTER_BOMB: MobHandler.MonsterBomb(slea.readInt(), c.getPlayer()); break; case MOB_BOMB: MobHandler.MobBomb(slea, c.getPlayer()); break; case NPC_SHOP: NPCHandler.NPCShop(slea, c, c.getPlayer()); break; case NPC_TALK: NPCHandler.NPCTalk(slea, c, c.getPlayer()); break; case NPC_TALK_MORE: NPCHandler.NPCMoreTalk(slea, c); break; case NPC_ACTION: NPCHandler.NPCAnimation(slea, c); break; case QUEST_ACTION: NPCHandler.QuestAction(slea, c, c.getPlayer()); break; case STORAGE: if (c.getPlayer().getGMLevel() == 6 && c.getPlayer().getDGM() == 0) { c.getPlayer().dropMessage(1, "You may not do this as a GM."); c.getPlayer().getClient().getSession().write(CWvsContext.enableActions()); break; } NPCHandler.Storage(slea, c, c.getPlayer()); break; case GENERAL_CHAT: if ((c.getPlayer() != null) && (c.getPlayer().getMap() != null)) { slea.readInt(); ChatHandler.GeneralChat(slea.readMapleAsciiString(), slea.readByte(), c, c.getPlayer()); } break; case PARTYCHAT: slea.readInt(); ChatHandler.Others(slea, c, c.getPlayer()); break; case WHISPER: ChatHandler.Whisper_Find(slea, c); break; case MESSENGER: ChatHandler.Messenger(slea, c); break; case AUTO_ASSIGN_AP: StatsHandling.AutoAssignAP(slea, c, c.getPlayer()); break; case SPECIAL_STAT: PlayerHandler.updateSpecialStat(slea, c); break; case DISTRIBUTE_AP: StatsHandling.DistributeAP(slea, c, c.getPlayer()); break; case DISTRIBUTE_SP: slea.readInt(); StatsHandling.DistributeSP(slea.readInt(), slea.readByte(), c, c.getPlayer()); break; case PLAYER_INTERACTION: PlayerInteractionHandler.PlayerInteraction(slea, c, c.getPlayer()); break; case GUILD_OPERATION: GuildHandler.Guild(slea, c); break; case DENY_GUILD_REQUEST: slea.skip(1); GuildHandler.DenyGuildRequest(slea.readMapleAsciiString(), c); break; case ALLIANCE_OPERATION: AllianceHandler.HandleAlliance(slea, c, false); break; case DENY_ALLIANCE_REQUEST: AllianceHandler.HandleAlliance(slea, c, true); break; case QUICK_MOVE: NPCHandler.OpenPublicNpc(slea, c); break; case BBS_OPERATION: BBSHandler.BBSOperation(slea, c); break; case PARTY_OPERATION: PartyHandler.PartyOperation(slea, c); break; case DENY_PARTY_REQUEST: PartyHandler.DenyPartyRequest(slea, c); break; case ALLOW_PARTY_INVITE: PartyHandler.AllowPartyInvite(slea, c); break; case BUDDYLIST_MODIFY: BuddyListHandler.BuddyOperation(slea, c); break; case CYGNUS_SUMMON: UserInterfaceHandler.CygnusSummon_NPCRequest(c); break; case SHIP_OBJECT: UserInterfaceHandler.ShipObjectRequest(slea.readInt(), c); break; case BUY_CS_ITEM: CashShopOperation.BuyCashItem(slea, c, c.getPlayer()); break; case CASH_CATEGORY: CashShopOperation.BuyCashItem(slea, c, c.getPlayer()); break; case COUPON_CODE: CashShopOperation.doCSPackets(c); break; case TWIN_DRAGON_EGG: System.out.println(new StringBuilder().append("TWIN_DRAGON_EGG: ").append(slea.toString()).toString()); CashItemInfo item = CashItemFactory.getInstance().getItem(10003055); c.getPlayer().getCashInventory().toItem(item); break; case XMAS_SURPRISE: System.out.println(new StringBuilder().append("XMAS_SURPRISE: ").append(slea.toString()).toString()); break; case CS_UPDATE: CashShopOperation.CSUpdate(c); break; case USE_POT: ItemMakerHandler.UsePot(slea, c); break; case CLEAR_POT: ItemMakerHandler.ClearPot(slea, c); break; case FEED_POT: ItemMakerHandler.FeedPot(slea, c); break; case CURE_POT: ItemMakerHandler.CurePot(slea, c); break; case REWARD_POT: ItemMakerHandler.RewardPot(slea, c); break; case DAMAGE_SUMMON: slea.skip(4); SummonHandler.DamageSummon(slea, c.getPlayer()); break; case MOVE_SUMMON: SummonHandler.MoveSummon(slea, c.getPlayer()); break; case SUMMON_ATTACK: SummonHandler.SummonAttack(slea, c, c.getPlayer()); break; case MOVE_DRAGON: SummonHandler.MoveDragon(slea, c.getPlayer()); break; case SUB_SUMMON: SummonHandler.SubSummon(slea, c.getPlayer()); break; case REMOVE_SUMMON: SummonHandler.RemoveSummon(slea, c); break; case SPAWN_PET: PetHandler.SpawnPet(slea, c, c.getPlayer()); break; case MOVE_PET: PetHandler.MovePet(slea, c.getPlayer()); break; case PET_CHAT: if (slea.available() >= 12L) { int petid = GameConstants.GMS ? c.getPlayer().getPetIndex((int) slea.readLong()) : slea.readInt(); slea.readInt(); PetHandler.PetChat(petid, slea.readShort(), slea.readMapleAsciiString(), c.getPlayer()); } break; case PET_COMMAND: MaplePet pet = null; if (GameConstants.GMS) { pet = c.getPlayer().getPet(c.getPlayer().getPetIndex((int) slea.readLong())); } else { pet = c.getPlayer().getPet((byte) slea.readInt()); } slea.readByte(); if (pet == null) { return; } PetHandler.PetCommand(pet, PetDataFactory.getPetCommand(pet.getPetItemId(), slea.readByte()), c, c.getPlayer()); break; case PET_FOOD: PetHandler.PetFood(slea, c, c.getPlayer()); break; case PET_LOOT: InventoryHandler.Pickup_Pet(slea, c, c.getPlayer()); break; case PET_AUTO_POT: PetHandler.Pet_AutoPotion(slea, c, c.getPlayer()); break; case MONSTER_CARNIVAL: MonsterCarnivalHandler.MonsterCarnival(slea, c); break; case PACKAGE_OPERATION: DueyHandler.DueyOperation(slea, c); break; case USE_HIRED_MERCHANT: HiredMerchantHandler.UseHiredMerchant(c, true); break; case MERCH_ITEM_STORE: HiredMerchantHandler.MerchantItemStore(slea, c); break; case CANCEL_DEBUFF: break; case REPAIR: NPCHandler.repair(slea, c); break; case REPAIR_ALL: NPCHandler.repairAll(c); break; case OWL: InventoryHandler.Owl(slea, c); break; case OWL_WARP: InventoryHandler.OwlWarp(slea, c); break; case USE_OWL_MINERVA: InventoryHandler.OwlMinerva(slea, c); break; case RPS_GAME: NPCHandler.RPSGame(slea, c); break; case UPDATE_QUEST: NPCHandler.UpdateQuest(slea, c); break; case USE_ITEM_QUEST: NPCHandler.UseItemQuest(slea, c); break; case FOLLOW_REQUEST: PlayersHandler.FollowRequest(slea, c); break; case AUTO_FOLLOW_REPLY: case FOLLOW_REPLY: PlayersHandler.FollowReply(slea, c); break; case RING_ACTION: PlayersHandler.RingAction(slea, c); break; case REQUEST_FAMILY: FamilyHandler.RequestFamily(slea, c); break; case OPEN_FAMILY: FamilyHandler.OpenFamily(slea, c); break; case FAMILY_OPERATION: FamilyHandler.FamilyOperation(slea, c); break; case DELETE_JUNIOR: FamilyHandler.DeleteJunior(slea, c); break; case DELETE_SENIOR: FamilyHandler.DeleteSenior(slea, c); break; case USE_FAMILY: FamilyHandler.UseFamily(slea, c); break; case FAMILY_PRECEPT: FamilyHandler.FamilyPrecept(slea, c); break; case FAMILY_SUMMON: FamilyHandler.FamilySummon(slea, c); break; case ACCEPT_FAMILY: FamilyHandler.AcceptFamily(slea, c); break; case SOLOMON: PlayersHandler.Solomon(slea, c); break; case GACH_EXP: PlayersHandler.GachExp(slea, c); break; case PARTY_SEARCH_START: PartyHandler.MemberSearch(slea, c); break; case PARTY_SEARCH_STOP: PartyHandler.PartySearch(slea, c); break; case EXPEDITION_LISTING: PartyHandler.PartyListing(slea, c); break; case EXPEDITION_OPERATION: PartyHandler.Expedition(slea, c); break; case USE_TELE_ROCK: InventoryHandler.TeleRock(slea, c); break; case INNER_CIRCULATOR: InventoryHandler.useInnerCirculator(slea, c); break; case PAM_SONG: InventoryHandler.PamSong(slea, c); break; case RESET_CORE_AURA: InventoryHandler.ResetCoreAura(slea.readInt(), c, c.getPlayer()); break; case REPORT: break; case CANCEL_OUT_SWIPE: slea.readInt(); break; case VIEW_SKILLS: PlayersHandler.viewSkills(slea, c); break; case SKILL_SWIPE: PlayersHandler.StealSkill(slea, c); break; case CHOOSE_SKILL: PlayersHandler.ChooseSkill(slea, c); break; case MAGIC_WHEEL: System.out.println(new StringBuilder().append("[MAGIC_WHEEL] [").append(slea.toString()).append("]").toString()); byte mode = slea.readByte(); if (mode == 2) { int idk = slea.readInt(); short toUseSlot = (short) slea.readInt(); int tokenId = slea.readInt(); } break; default: System.out.println(new StringBuilder().append("[UNHANDLED] Recv [").append(header.toString()).append("] found").toString()); } } }