/**
* @class ServerHandler
* @brief Handles all packets to and from the server
* @author Sean Kasun
* @date 2000-2002
*/
/*****
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*****/
#include "uop.h"
#include <SDL/SDL.h>
#include <iostream>
#include <sstream>
#include "serverhandler.h"
#include "network.h"
#include "uopconfig.h"
#include "interfacehandler.h"
#include "message.h"
#include "texthandler.h"
#include "gumps.h"
#include "cliloc.h"
#include "world.h"
extern PacketInfo packetInfo[];
extern Network *network;
extern UOPConfig *config;
extern Gumps *gumps;
extern TextHandler *textHandler;
extern vector<Cliloc *>intlocs;
extern InterfaceHandler *interfaceHandler;
extern World *world;
/**
* Create a new serverhandler
*/
ServerHandler::ServerHandler()
{
}
ServerHandler::~ServerHandler()
{
}
/**
* The main packet handler
* This figures out which packet the server sent to us
* @param packet The packet ID
*/
void ServerHandler::handlePacket(Uint8 packet)
{
(*this.*packetInfo[packet].handler)(packet);
}
void ServerHandler::pNone(Uint8 packet)
{
Uint16 size=packetInfo[packet].size-1;
if (packetInfo[packet].flags&0x80)
{
Uint8 buffer[2];
network->read(buffer,2);
size=(buffer[0]<<8)|buffer[1];
size-=3;
}
cerr<<"Skipping "<<packetInfo[packet].name<<" ("<<size<<" bytes)"<<endl;
Uint8 *dynbuf = new Uint8[size];
network->read(dynbuf,size);
delete [] dynbuf;
}
/**
* Same as pNone, but dumps packet contents.
* For debug and protocol hacking.
* @todo fix output
*/
void ServerHandler::pDump(Uint8 packet)
{
Uint16 size=packetInfo[packet].size-1;
if (packetInfo[packet].flags&0x80)
{
network->read((Uint8*)&size,2);
size=GET_UINT16(&size);
size-=3;
}
Uint8 *dynbuf = new Uint8[size];
cout<< "Dumping "<<packetInfo[packet].name << " (" << hex
<< "0x" << (int)packet << ", "<< "0x" <<size<<" bytes)"<<": ";
network->read(dynbuf,size);
for(int i=0;i<size;i++){
cout << "0x"<< (int) dynbuf[i] << " ";
}
cout << dec << endl;
delete [] dynbuf;
}
void ServerHandler::pMove(Uint8 packet){
Uint16 size;
assert(packet==PACKET_MOVE);
Uint8 buffer[2];
network->read(buffer,2);
size=GET_UINT16(buffer);
size-=3;
//cout << "PACKET_MOVE" << endl;
//cout << "Size: " << size << endl;
Uint8 *dynbuf = new Uint8[size];
network->read(dynbuf,size);
Uint8 *cur=dynbuf;
Uint32 serial = GET_UINT32(cur); cur+=4;
Uint16 id = GET_UINT16(cur); cur+=2;
Uint16 amount = 0;
if(serial & 0x80000000){
amount=GET_UINT16(cur); cur+=2;
}
if(id & 0x8000){
id+=GET_SINT8(cur); cur++;
}
Uint16 x = GET_UINT16(cur); cur+=2;
Uint16 y = GET_UINT16(cur); cur+=2;
Uint8 dir=0;
if(x & 0x8000){
dir=GET_UINT8(cur); cur++;
}
Sint8 z = GET_SINT8(cur); cur ++;
Uint16 hue = 0;
if(y & 0x8000){
hue = GET_UINT16(cur); cur+=2;
}
Uint8 status = 0;
if(y & 0x4000){
status = GET_UINT8(cur); cur++;
}
x=x&(~0x8000);
y=y&(~(0x8000|0x4000));
//cout << "Object info:" << endl;
//cout << "serial:\t" << serial << endl;
//cout << "id:\t" << id << endl;
//cout << "amount:\t" << amount << endl;
//cout << "x:\t" << x << endl;
//cout << "y:\t" << y << endl;
//cout << "dir:\t" << (int)dir << endl;
//cout << "z:\t" << (int)z << endl;
//cout << "hue:\t" << hue << endl;
//cout << "status:\t" << (int)status << endl;
Mobile *obj = new Mobile(serial, id);
obj->x=x;
obj->y=y;
obj->z=z;
obj->dir=dir;
//world->getCell(x, y, false, false)->add(obj);
delete [] dynbuf;
}
void ServerHandler::pNakedMob(Uint8 packet){
assert(packet==PACKET_NAKED_MOB);
Uint8 buffer[16];
network->read(buffer,16);
Uint8 *cur=buffer;
Uint32 serial = GET_UINT32(cur); cur+=4;
Uint16 id = GET_UINT16(cur); cur+=2;
Uint16 x = GET_UINT16(cur); cur+=2;
Uint16 y = GET_UINT16(cur); cur+=2;
Sint8 z = GET_SINT8(cur); cur++;
Uint8 dir = GET_UINT8(cur); cur++;
Uint16 hue = GET_UINT16(cur); cur+=2;
Uint8 status = GET_UINT8(cur); cur++;
Uint8 color = GET_UINT8(cur); cur++;
Mobile *obj;
if(world->mobiles.count(serial)){
// mobile found, reusing
obj = world->mobiles[serial];
}
else{
// adding new mobile - should not be
assert(false);
obj = new Mobile(serial, id);
world->mobiles.insert(pair<int,Mobile*>(serial,obj));
}
//obj->id=id;
obj->x=x;
obj->y=y;
obj->z=z;
obj->dir=dir;
obj->status = status;
obj->color = color;
obj->hue = hue;
world->getCell(x, y, false, false)->add(obj);
}
void ServerHandler::pEquippedMob(Uint8 packet){
assert(packet == PACKET_EQUIPPED_MOB);
Uint16 size;
network->read((Uint8*)&size, 2);
size=GET_UINT16(&size);
size-=3;
Uint8* buffer=new Uint8[size];
network->read(buffer, size);
Uint8 *cur=buffer;
Uint32 serial = GET_UINT32(cur); cur+=4;
Uint16 id = GET_UINT16(cur); cur+=2;
Uint16 amount = 0;
if (serial & 0x80000000){
amount = GET_UINT16(cur); cur+=2;
}
Uint16 x = GET_UINT16(cur); cur+=2;
Uint16 y = GET_UINT16(cur); cur+=2;
Sint8 z = GET_SINT8(cur); cur ++;
Uint8 dir = GET_UINT8(cur); cur++;
Uint16 hue = GET_UINT16(cur); cur+=2;
Uint8 status = GET_UINT8(cur); cur++;
Uint8 color = GET_UINT8(cur); cur++;
// here goes weared objects, dropped for now
// ...
Mobile *obj;
if(world->mobiles.count(serial)){
// mobile found, reusing
obj = world->mobiles[serial];
}
else{
// adding new mobile
obj = new Mobile(serial, id);
world->mobiles.insert(pair<int,Mobile*>(serial,obj));
}
//obj->id=id;
obj->x=x;
obj->y=y;
obj->z=z;
obj->dir=dir;
obj->status = status;
obj->color = color;
obj->hue = hue;
world->getCell(x, y, false, false)->add(obj);
delete [] buffer;
}
void ServerHandler::pGroup(Uint8 packet){
assert(packet == PACKET_GROUP);
Uint8 command;
network->read(&command,1);
if(command == 0){ //Pause
if(!world->paused()){
world->pause();
}
else{
cerr << "Unexpected pause packet - ignoring" << endl;
}
}
else if(command == 1){ //Resume
if(world->paused()){
world->unpause();
}
else{
cerr << "Unexpected resume packet - ignoring" << endl;
}
}
else{
assert(false);
}
}
/**
* @todo Finish this incomplete packet handler.
*/
void ServerHandler::pLoginConfirm(Uint8 packet)
{
Uint8 buffer[36];
network->read(buffer,36);
Uint32 serial = SDL_SwapBE32(*(Uint32*)buffer);
Uint16 model = SDL_SwapBE16(*(Uint16*)(buffer+8));
Uint16 x = SDL_SwapBE16(*(Uint16*)(buffer+10));
Uint16 y = SDL_SwapBE16(*(Uint16*)(buffer+12));
Uint16 z = SDL_SwapBE16(*(Uint16*)(buffer+14));
Uint8 dir = *(Uint8*)(buffer+16);
Uint8 status = *(Uint8*)(buffer+26);
Uint8 color = *(Uint8*)(buffer+27);
Mobile *player = new Mobile(serial, model);
player->x = x;
player->y = y;
player->z = z;
player->inThirdDawn = false;
player->dir = dir;
player->status = status;
player->color = color;
world->getCell(x, y, false, false)->add(player);
if (world->focus)
delete world->focus;
world->focus = player;
}
void ServerHandler::pBritanniaList(Uint8 packet)
{
Uint8 buffer[10];
network->read(buffer,5);
Uint8 dynbuf[40];
Uint16 num=(buffer[3]<<8)|buffer[4];
interfaceHandler->removeAllGumps();
interfaceHandler->addGump("loginmenu");
interfaceHandler->addGump("shardselection");
GumpVList *vlist=interfaceHandler->getVList(110002);
for (Uint16 i=0;i<num;i++)
{
network->read(dynbuf,40);
string server((char *)(dynbuf+2));
Uint16 id=(dynbuf[0]<<8)|dynbuf[1];
vlist->add(new GumpVListChild(id+110002*100,"shardbuttonunpressed","shardbuttonpressed","shardbuttonhighlight",server));
}
}
void ServerHandler::pCitiesAndChars(Uint8 packet)
{
Uint8 buffer[2];
network->read(buffer,2);
Uint16 size=SDL_SwapBE16(*(Uint16*)buffer)-3;
Uint8 *dynbuf = new Uint8[size];
network->read(dynbuf,size);
Uint8 numChars=dynbuf[0];
Uint8 *ptr=dynbuf+1;
interfaceHandler->initCharacters(numChars);
int i;
for (i=0;i<numChars;i++,ptr+=60)
interfaceHandler->addCharacter((char *)ptr);
for (i=numChars;i<5;i++)
interfaceHandler->addCharacter(intlocs[0]->getString(105));
delete [] dynbuf;
interfaceHandler->removeAllGumps();
interfaceHandler->addGump("loginmenu");
interfaceHandler->addGump("charselection");
}
void ServerHandler::pUserServer(Uint8 packet)
{
IPaddress ipA;
SDLNet_ResolveHost(&ipA, (char*)config->serverIP().c_str(), 0);
Uint8 buffer[10];
network->read(buffer,10);
Uint32 ip=SDL_SwapLE32(*(Uint32*)buffer);
Uint16 port=SDL_SwapBE16(*(Uint16*)(buffer+4));
if ((ip!=ipA.host || port!=config->serverPort()) && ip!=0xffffffff)
{
network->disconnect();
network->connect(SDL_SwapBE32(ip),port);
}
Uint32 authKey=SDL_SwapBE32(*(Uint32*)(buffer+6));
pPostLogin(authKey);
}
void ServerHandler::pLoginComplete(Uint8 packet)
{
interfaceHandler->removeAllGumps();
interfaceHandler->addGump("gameplaywindow");
}
void ServerHandler::pUnicodeText(Uint8 packet)
{
Uint8 buffer[2];
Uint16 size;
network->read(buffer,2);
size=SDL_SwapBE16(*(Uint16*)buffer)-3;
Uint8 *dynbuf = new Uint8[size];
network->read(dynbuf,size);
Uint32 serial=SDL_SwapBE32(*(Uint32*)dynbuf);
Uint8 type=dynbuf[6];
Uint16 hue=SDL_SwapBE16(*(Uint16*)(dynbuf+7));
Uint16 font=SDL_SwapBE16(*(Uint16*)(dynbuf+9));
string str, tmp="";
if (type)
{
tmp=(char *)(dynbuf+15);
tmp+=": ";
}
latin2unicode(tmp,str);
for(int i=0; i<size-45;i++)
str+=(char)dynbuf[45+i];
// we have only 3 unicode fonts
if(font > 2)
font = 2;
delete [] dynbuf;
bool done=false;
Uint16 start,end;
start=0;
while (!done)
{
done=true;
end=str.length()-start;
string sub=str.substr(start,end);
if (textHandler->unicodeWidth(sub,font)>320)
{
done=false;
while (textHandler->unicodeWidth(sub,font)>320)
{
end-=2;
sub=str.substr(start,end);
}
Uint16 oldEnd=end;
while (!((str[end+start]== '\x00')
&& (str[end+start+1]== ' '))
&& (end>0)) end-=2;
if (!end)
end=oldEnd;
}
Message *msg=new Message(str.substr(start,end),true,true);
msg->font=font;
msg->hue=hue;
if (!done)
{
if(!((str[end+start]== '\x00') && (str[end+start+1]== ' ')))
start+=end;
else
start+=end+2;
}
}
}
void ServerHandler::pText(Uint8 packet)
{
Uint8 buffer[2];
Uint16 size;
network->read(buffer,2);
size=SDL_SwapBE16(*(Uint16*)buffer)-3;
Uint8 *dynbuf = new Uint8[size];
network->read(dynbuf,size);
Uint32 serial=SDL_SwapBE32(*(Uint32*)dynbuf);
Uint8 type=dynbuf[6];
Uint16 hue=SDL_SwapBE16(*(Uint16*)(dynbuf+7));
Uint16 font=SDL_SwapBE16(*(Uint16*)(dynbuf+9));
string str;
if (type)
{
str=(char *)(dynbuf+11);
str+=": ";
}
str+=(char *)(dynbuf+41);
delete [] dynbuf;
bool done=false;
Uint16 start,end;
start=0;
while (!done)
{
done=true;
end=str.length()-start;
string sub=str.substr(start,end);
if (textHandler->getWidth(sub,font)>320)
{
done=false;
while (textHandler->getWidth(sub,font)>320)
{
end--;
sub=str.substr(start,end);
}
Uint16 oldEnd=end;
while (str[end+start]!=' ' && end>0) end--;
if (!end)
end=oldEnd;
}
Message *msg=new Message(str.substr(start,end),false,true);
msg->font=font;
msg->hue=hue;
if (!done)
{
if (str[end+start]!=' ')
start+=end;
else
start+=end+1;
}
}
}
void ServerHandler::pAcctLoginReq(string &username,string &password)
{
Uint8 encKey[]={0x00,0x04,0x00,0x03};
Uint8 encKeySphere[]={0x00,0x00,0x00,0x00};
Uint8 dynbuf[62];
if (config->getBoolean("SphereCompat"))
network->write(encKeySphere,4);
else
network->write(encKey,4);
dynbuf[0]=PACKET_ACCT_LOGIN_REQ;
strncpy((char *)dynbuf+1,username.c_str(),30);
strncpy((char *)dynbuf+31,password.c_str(),30);
dynbuf[61]=0xff;
network->write(dynbuf,62);
this->username=username;
this->password=password;
}
void ServerHandler::pBritanniaSelect(Uint8 server)
{
Uint8 header[]={PACKET_BRITANNIA_SELECT,0x00,0x01};
header[2]=server;
network->write(header,3);
}
void ServerHandler::pPostLogin(Uint32 authKey)
{
Uint8 dynbuf[65];
dynbuf[0]=PACKET_POSTLOGIN;
dynbuf[1]=authKey>>24;
dynbuf[2]=(authKey>>16)&0xff;
dynbuf[3]=(authKey>>8)&0xff;
dynbuf[4]=authKey&0xff;
strncpy((char *)dynbuf+5,username.c_str(),30);
strncpy((char *)dynbuf+35,password.c_str(),30);
network->write(dynbuf,65);
network->readCrypto=true;
}
void ServerHandler::pPreLogin(Uint8 chr)
{
Uint8 header[0x49]={PACKET_PRELOGIN,0xed,0xed,0xed,0xed};
strncpy((char *)(header+5),username.c_str(),30);
header[0x44]=chr;
network->write(header,0x49);
}
void ServerHandler::pLogin(Uint8 *createData)
{
IPaddress ipA;
SDLNet_ResolveHost(&ipA, (char*)config->serverIP().c_str(),
config->serverPort());
*(Uint32 *)(createData+96)=SDL_SwapBE32(ipA.host);
network->write(createData,104);
}
PacketInfo packetInfo[]={
{"PACKET_LOGIN", 0x68, 0x00, &ServerHandler::pNone},
{"PACKET_LOGOUT", 0x05, 0x00, &ServerHandler::pNone},
{"PACKET_REQ_MOVE", 0x07, 0x00, &ServerHandler::pNone},
{"PACKET_SPEECH", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_GODMODE_TOGGLE", 0x02, 0x00, &ServerHandler::pNone},
{"PACKET_ATTACK", 0x05, 0x00, &ServerHandler::pNone},
{"PACKET_REQ_OBJUSE", 0x05, 0x00, &ServerHandler::pNone},
{"PACKET_REQ_GETOBJ", 0x07, 0x00, &ServerHandler::pNone},
{"PACKET_REQ_DROPOBJ", 0x0e, 0x00, &ServerHandler::pNone},
{"PACKET_REQ_LOOK", 0x05, 0x00, &ServerHandler::pNone},
{"PACKET_EDIT", 0x0b, 0x00, &ServerHandler::pNone},
{"PACKET_EDITAREA", 0x0a, 0x01, &ServerHandler::pNone},
{"PACKET_TILEDATA", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_NPCDATA", 0x03, 0x00, &ServerHandler::pNone},
{"PACKET_TEMPLATEDATA", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_PAPERDOLL", 0x3d, 0x00, &ServerHandler::pNone},
{"PACKET_HUEDATA", 0xd7, 0x00, &ServerHandler::pNone},
{"PACKET_MOBILESTAT", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_GODCOMMAND", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_REQ_OBJEQUIP", 0x0a, 0x00, &ServerHandler::pNone},
{"PACKET_ELEVCHANGE", 0x06, 0x00, &ServerHandler::pNone},
{"PACKET_FOLLOW", 0x09, 0x00, &ServerHandler::pNone},
{"PACKET_REQUEST_SCRIPT_NAMES", 0x01, 0x00, &ServerHandler::pNone},
{"PACKET_SCRIPT_TREE_CMD", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_SCRIPT_ATTACH", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_NPCCONVO_DATA", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_MOVE", 0x00, 0x80, &ServerHandler::pMove},
{"PACKET_LOGIN_CONFIRM", 0x25, 0x00, &ServerHandler::pLoginConfirm},
{"PACKET_TEXT", 0x00, 0x80, &ServerHandler::pText},
{"PACKET_DESTROY_OBJECT", 0x05, 0x00, &ServerHandler::pNone},
{"PACKET_ANIMATE", 0x04, 0x00, &ServerHandler::pNone},
{"PACKET_EXPLODE", 0x08, 0x00, &ServerHandler::pNone},
{"PACKET_ZMOVE", 0x13, 0x00, &ServerHandler::pNone},
{"PACKET_BLOCKED_MOVE", 0x08, 0x00, &ServerHandler::pNone},
{"PACKET_OK_MOVE", 0x03, 0x00, &ServerHandler::pNone},
{"PACKET_OBJMOVE", 0x1a, 0x00, &ServerHandler::pNone},
{"PACKET_OPEN_GUMP", 0x07, 0x00, &ServerHandler::pNone},
{"PACKET_OBJ_TO_OBJ", 0x14, 0x00, &ServerHandler::pNone},
{"PACKET_OLD_CLIENT", 0x05, 0x00, &ServerHandler::pNone},
{"PACKET_GETOBJ_FAILED", 0x02, 0x00, &ServerHandler::pNone},
{"PACKET_DROPOBJ_FAILED", 0x05, 0x00, &ServerHandler::pNone},
{"PACKET_DROPOBJ_OK", 0x01, 0x00, &ServerHandler::pNone},
{"PACKET_BLOOD", 0x05, 0x00, &ServerHandler::pNone},
{"PACKET_GODMODE", 0x02, 0x00, &ServerHandler::pNone},
{"PACKET_DEATH", 0x02, 0x00, &ServerHandler::pNone},
{"PACKET_HEALTH", 0x11, 0x00, &ServerHandler::pNone},
{"PACKET_EQUIP_ITEM", 0x0f, 0x00, &ServerHandler::pNone},
{"PACKET_SWING", 0x0a, 0x00, &ServerHandler::pNone},
{"PACKET_ATTACK_OK", 0x05, 0x00, &ServerHandler::pNone},
{"PACKET_ATTACK_END", 0x01, 0x00, &ServerHandler::pNone},
{"PACKET_HACK_MOVER", 0x02, 0x00, &ServerHandler::pNone},
{"PACKET_GROUP", 0x02, 0x00, &ServerHandler::pGroup},
{"PACKET_CLIENTQUERY", 0x0a, 0x00, &ServerHandler::pNone},
{"PACKET_RESOURCETYPE", 0x8d, 0x02, &ServerHandler::pNone},
{"PACKET_RESOURCETILEDATA", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_MOVEOBJECT", 0x08, 0x00, &ServerHandler::pNone},
{"PACKET_FOLLOWMOVE", 0x07, 0x00, &ServerHandler::pNone},
{"PACKET_GROUPS", 0x09, 0x00, &ServerHandler::pNone},
{"PACKET_SKILLS", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_OFFERACCEPT", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_MULTI_OBJ_TO_OBJ", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_SHIP", 0x02, 0x00, &ServerHandler::pNone},
{"PACKET_VERSIONS", 0x25, 0x00, &ServerHandler::pNone},
{"PACKET_UPD_OBJCHUNK", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_UPD_TERRCHUNK", 0xc9, 0x00, &ServerHandler::pNone},
{"PACKET_UPD_TILEDATA", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_UPD_ART", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_UPD_ANIM", 0x29, 0x02, &ServerHandler::pNone},
{"PACKET_UPD_HUES", 0xc9, 0x02, &ServerHandler::pNone},
{"PACKET_VER_OK", 0x05, 0x00, &ServerHandler::pNone},
{"PACKET_NEW_ART", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_NEW_TERR", 0x0b, 0x00, &ServerHandler::pNone},
{"PACKET_NEW_ANIM", 0x49, 0x00, &ServerHandler::pNone},
{"PACKET_NEW_HUES", 0x5d, 0x00, &ServerHandler::pNone},
{"PACKET_DESTROY_ART", 0x05, 0x00, &ServerHandler::pNone},
{"PACKET_CHECK_VER", 0x09, 0x00, &ServerHandler::pNone},
{"PACKET_SCRIPT_NAMES", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_SCRIPT_FILE", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_LIGHTCHANGE", 0x06, 0x00, &ServerHandler::pNone},
{"PACKET_SUNLIGHT", 0x02, 0x00, &ServerHandler::pNone},
{"PACKET_BOARDHEADER", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_BOARDMSG", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_POSTMSG", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_LOGIN_REJECT", 0x02, 0x00, &ServerHandler::pNone},
{"PACKET_SOUND", 0x0c, 0x00, &ServerHandler::pNone},
{"PACKET_LOGIN_COMPLETE", 0x01, 0x00, &ServerHandler::pLoginComplete},
{"PACKET_MAP_COMMAND", 0x0b, 0x00, &ServerHandler::pNone},
{"PACKET_UPD_REGIONS", 0x6e, 0x00, &ServerHandler::pNone},
{"PACKET_NEW_REGION", 0x6a, 0x00, &ServerHandler::pNone},
{"PACKET_NEW_CONTEXTFX", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_UPD_CONTEXTFX", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_GAMETIME", 0x04, 0x00, &ServerHandler::pNone},
{"PACKET_RESTARTVER", 0x02, 0x00, &ServerHandler::pNone},
{"PACKET_PRELOGIN", 0x49, 0x00, &ServerHandler::pNone},
{"PACKET_SERVERLIST", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_SERVERADD", 0x31, 0x00, &ServerHandler::pNone},
{"PACKET_SERVERREMOVE", 0x05, 0x00, &ServerHandler::pNone},
{"PACKET_DESTROY_STATIC", 0x09, 0x00, &ServerHandler::pNone},
{"PACKET_MOVESTATIC", 0x0f, 0x00, &ServerHandler::pNone},
{"PACKET_AREA_LOAD", 0x0d, 0x00, &ServerHandler::pNone},
{"PACKET_AREA_LOAD_REQ", 0x01, 0x00, &ServerHandler::pNone},
{"PACKET_WEATHERCHANGE", 0x04, 0x00, &ServerHandler::pNone},
{"PACKET_BOOKPAGE", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_SIMPED", 0x15, 0x00, &ServerHandler::pNone},
{"PACKET_SCRIPT_LS_ATTACH", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_FRIENDS", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_FRIENDNOTIFY", 0x03, 0x00, &ServerHandler::pNone},
{"PACKET_KEY_USE", 0x09, 0x00, &ServerHandler::pNone},
{"PACKET_TARGET", 0x13, 0x00, &ServerHandler::pNone},
{"PACKET_MUSIC", 0x03, 0x00, &ServerHandler::pNone},
{"PACKET_ANIM", 0x0e, 0x00, &ServerHandler::pNone},
{"PACKET_TRADE", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_EFFECT", 0x1c, 0x00, &ServerHandler::pNone},
{"PACKET_BBOARD", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_COMBAT", 0x05, 0x00, &ServerHandler::pNone},
{"PACKET_PING", 0x02, 0x00, &ServerHandler::pNone},
{"PACKET_SHOP_DATA", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_RENAME_MOB", 0x23, 0x00, &ServerHandler::pNone},
{"PACKET_SERVERCHANGE", 0x10, 0x00, &ServerHandler::pNone},
{"PACKET_NAKED_MOB", 0x11, 0x00, &ServerHandler::pNakedMob},
{"PACKET_EQUIPPED_MOB", 0x00, 0x80, &ServerHandler::pEquippedMob},
{"PACKET_RESOURCE_QUERY", 0x09, 0x00, &ServerHandler::pNone},
{"PACKET_RESOURCE_DATA", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_SEQUENCE", 0x02, 0x00, &ServerHandler::pNone},
{"PACKET_OBJPICKER", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_PICKEDOBJ", 0x0d, 0x00, &ServerHandler::pNone},
{"PACKET_GODVIEW_QUERY", 0x02, 0x00, &ServerHandler::pNone},
{"PACKET_GODVIEW_DATA", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_ACCT_LOGIN_REQ", 0x3e, 0x00, &ServerHandler::pNone},
{"PACKET_ACCT_LOGIN_OK", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_ACCT_LOGIN_FAIL", 0x02, 0x00, &ServerHandler::pNone},
{"PACKET_ACCT_DEL_CHAR", 0x27, 0x00, &ServerHandler::pNone},
{"PACKET_CHG_CHAR_PW", 0x45, 0x00, &ServerHandler::pNone},
{"PACKET_CHG_CHAR_RESULT", 0x02, 0x00, &ServerHandler::pNone},
{"PACKET_ALL_CHARACTERS", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_SEND_RESOURCES", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_OPEN_PAPERDOLL", 0x42, 0x00, &ServerHandler::pNone},
{"PACKET_CORPSE_EQ", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_TRIGGEREDIT", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_DISPLAY_SIGN", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_USER_SERVER", 0x0b, 0x00, &ServerHandler::pUserServer},
{"PACKET_UNUSED3", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_MOVE_CHARACTER", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_UNUSED4", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_OPEN_COURSEGUMP", 0x13, 0x00, &ServerHandler::pNone},
{"PACKET_POSTLOGIN", 0x41, 0x00, &ServerHandler::pNone},
{"PACKET_UPD_MULTI", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_BOOKHDR", 0x63, 0x00, &ServerHandler::pNone},
{"PACKET_UPD_SKILL", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_HUEPICKER", 0x09, 0x00, &ServerHandler::pNone},
{"PACKET_GAMECENT_MON", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_PLAYERMOVE", 0x02, 0x00, &ServerHandler::pNone},
{"PACKET_MOBNAME", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_TARGET_MULTI", 0x1a, 0x00, &ServerHandler::pNone},
{"PACKET_TEXT_ENTRY", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_REQUEST_ASSIST", 0x02, 0x01, &ServerHandler::pNone},
{"PACKET_ASSIST_REQUEST", 0x35, 0x01, &ServerHandler::pNone},
{"PACKET_GM_SINGLE", 0x33, 0x00, &ServerHandler::pNone},
{"PACKET_SHOP_SELL", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_SHOP_OFFER", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_BRITANNIA_SELECT", 0x03, 0x00, &ServerHandler::pNone},
{"PACKET_HP_HEALTH", 0x09, 0x00, &ServerHandler::pNone},
{"PACKET_MANA_HEALTH", 0x09, 0x00, &ServerHandler::pNone},
{"PACKET_FAT_HEALTH", 0x09, 0x00, &ServerHandler::pNone},
{"PACKET_HARDWARE_INFO", 0x95, 0x00, &ServerHandler::pNone},
{"PACKET_WEB_BROWSE", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_MESSAGE", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_REQ_TIP", 0x04, 0x00, &ServerHandler::pNone},
{"PACKET_BRITANNIA_LIST", 0x00, 0x80, &ServerHandler::pBritanniaList},
{"PACKET_CITIES_AND_CHARS", 0x00, 0x80, &ServerHandler::pCitiesAndChars},
{"PACKET_CURRENT_TARGET", 0x05, 0x00, &ServerHandler::pNone},
{"PACKET_STRING_QUERY", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_STRING_RESPONSE", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_SPEECH_UNICODE", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_TEXT_UNICODE", 0x00, 0x80, &ServerHandler::pUnicodeText},
{"PACKET_DEATH_ANIM", 0x0d, 0x00, &ServerHandler::pNone},
{"PACKET_GENERIC_GUMP", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_GENGUMP_TRIG", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_CHAT_MSG", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_CHAT_TEXT", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_TARGET_OBJLIST", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_CHAT_OPEN", 0x40, 0x00, &ServerHandler::pNone},
{"PACKET_HELP_REQUEST", 0x09, 0x00, &ServerHandler::pNone},
{"PACKET_HELP_UNICODE_TEXT", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_CHAR_PROFILE", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_FEATURES", 0x03, 0x00, &ServerHandler::pNone},
{"PACKET_POINTER", 0x06, 0x00, &ServerHandler::pNone},
{"PACKET_ACCT_ID", 0x09, 0x00, &ServerHandler::pNone},
{"PACKET_GAMESEASON", 0x03, 0x00, &ServerHandler::pNone},
{"PACKET_CLIENTVERSION", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_ASSISTVERSION", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_GENERIC_COMMAND", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_EFFECT_HUEDFX", 0x24, 0x00, &ServerHandler::pNone},
{"PACKET_TEXT_ID", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_TEXT_ENTRY_UNICODE", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_GQ_REQUEST", 0x00, 0x80, &ServerHandler::pNone},
{"PACKET_SEMIVISIBLE", 0x06, 0x00, &ServerHandler::pNone},
{"PACKET_INVALIDMAP", 0xcb, 0x00, &ServerHandler::pNone},
{"PACKET_INVALIDMAP_ENABLE", 0x01, 0x00, &ServerHandler::pNone},
{"PACKET_PARTICLE_EFFECT", 0x31, 0x00, &ServerHandler::pNone},
{"PACKET_UPDATE_RANGE_CHANGE", 0x02, 0x00, &ServerHandler::pNone},
{"PACKET_TRIPTIME", 0x06, 0x00, &ServerHandler::pNone},
{"PACKET_UTRIPTIME", 0x06, 0x00, &ServerHandler::pNone},
{"PACKET_GQ_COUNT", 0x07, 0x00, &ServerHandler::pNone},
{"PACKET_TEXT_ID_PLUS_STRING", 0x00, 0x80, &ServerHandler::pNone},
};