/*  
	EQ2Emulator:  Everquest II Server Emulator
	Copyright (C) 2007  EQ2EMulator Development Team (http://www.eq2emulator.net)

	This file is part of EQ2Emulator.
*/
#include "../common/debug.h"
#ifdef WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock.h>
#include <process.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#endif
#include <string.h>
#include <iomanip>
#include <stdlib.h>
#include <assert.h>

#include "net.h"
#include "client.h"
#include "../common/EQStream.h"
#include "../common/packet_dump.h"
#include "../common/packet_functions.h"
#include "../common/emu_opcodes.h"
#include "../common/MiscFunctions.h"
#include "LWorld.h"
#include "LoginDatabase.h"
#include "../common/ConfigReader.h"
#include "../common/Log.h"

extern NetConnection	net;
extern LWorldList		world_list;
extern ClientList		client_list;
extern LoginDatabase	database;
extern map<int16,OpcodeManager*>EQOpcodeManager;
extern ConfigReader configReader;
using namespace std;
Client::Client(EQStream* ieqnc) {
	eqnc = ieqnc;
	ip = eqnc->GetrIP();
	port = ntohs(eqnc->GetrPort());
	account_id = 0;
	lsadmin = 0;
	worldadmin = 0;
	lsstatus = 0;
	origversion = version = 0;
	kicked = false;
	verified = false;
	memset(bannedreason, 0, sizeof(bannedreason));
	//worldresponse_timer = new Timer(10000);
	//worldresponse_timer->Disable();
	memset(key,0,10);
	LoginMode = None;
	num_updates = 0;
	updatetimer = new Timer(500);
	updatelisttimer = new Timer(10000);
	//keepalive = new Timer(5000);
	//logintimer = new Timer(500); // Give time for the servers to send updates
	//keepalive->Start();
	//updatetimer->Start();
	//logintimer->Disable();
	disconnectTimer = 0;
	memset(ClientSession,0,25);
	request_num = 0;
	login_account = 0;
	createRequest = 0;
	playWaitTimer = NULL;
	start = false;	
	update_position = 0;
	update_packets = 0;
	needs_world_list = true;
}

Client::~Client() {
	//safe_delete(worldresponse_timer);
	//safe_delete(logintimer);
	safe_delete(login_account);
	eqnc->Close();
	safe_delete(playWaitTimer);
	safe_delete(createRequest);
	safe_delete(disconnectTimer);
	safe_delete(updatetimer);
}

bool Client::Process() {
	if(!start && !eqnc->CheckActive()){
		if(!playWaitTimer)
			playWaitTimer = new Timer(5000);
		else if(playWaitTimer->Check()){
			safe_delete(playWaitTimer);
			return false;
		}
		return true;
	}
	else if(!start){
		safe_delete(playWaitTimer);
		start = true;
	}
	//if(disconnectTimer && disconnectTimer->Check())
	//	getConnection()->SendDisconnect();
	if (!kicked) {
		/************ Get all packets from packet manager out queue and process them ************/
		EQApplicationPacket *app = 0;
		/*if(logintimer && logintimer->Check())
		{
		database.LoadCharacters(GetLoginAccount());
		SendLoginAccepted();
		logintimer->Disable();
		}*/
		/*if(worldresponse_timer && worldresponse_timer->Check())
		{
		FatalError(WorldDownErrorMessage);
		worldresponse_timer->Disable();
		}*/
		
		if(playWaitTimer != NULL && playWaitTimer->Check ( ) )
		{
			SendPlayFailed(PLAY_ERROR_SERVER_TIMEOUT);
			safe_delete(playWaitTimer);
		}
		if(!needs_world_list && updatetimer && updatetimer->Check()){
			if(updatelisttimer && updatelisttimer->Check()){
				if(num_updates >= 180){ //30 minutes
					getConnection()->SendDisconnect();
				}
				else{					
					vector<PacketStruct*>::iterator itr;
					if(update_packets){
						for(itr = update_packets->begin(); itr != update_packets->end(); itr++){
							safe_delete(*itr);
						}
					}
					safe_delete(update_packets);
					update_packets = world_list.GetServerListUpdate(version);
				}
				num_updates++;
			}
			else{
				if(!update_packets){
					update_packets = world_list.GetServerListUpdate(version);
				}
				else{
					if(update_position < update_packets->size()){
						QueuePacket(update_packets->at(update_position)->serialize());
						update_position++;
					}
					else
						update_position = 0;
				}
			}
		}

		while(app = eqnc->PopPacket())
		{
			switch(app->GetOpcode())
			{
			case OP_LoginRequestMsg:{
//				DumpPacket(app);
				PacketStruct* packet = configReader.getStruct("LS_LoginRequest", 1);
				if(packet->LoadPacketData(app->pBuffer,app->size)){
					version = packet->getType_int32_ByName("version");

					LogWrite(LOGIN__DEBUG, 0, "Login", "Client Version Provided: %i", version);

					// Image 2020 Notes
					// we keep the original version for special packets like char creation to pass to world server
					origversion = version;
					// forced version to 60085 for now since those structures seem to work best for steam AoM 12133L Aug 17 2015 11:19:13 build
					version = 60085;

				if (EQOpcodeManager.count(GetOpcodeVersion(version)) == 0) {
					LogWrite(LOGIN__ERROR, 0, "Login", "Incompatible client version provided: %i", version);
					SendLoginDenied();
					return false;
				}
				
						if(EQOpcodeManager.count(GetOpcodeVersion(version)) > 0 && getConnection()){
						getConnection()->SetClientVersion(GetOrigVersion());
						EQ2_16BitString username = packet->getType_EQ2_16BitString_ByName("username");
						EQ2_16BitString password = packet->getType_EQ2_16BitString_ByName("password");
						LoginAccount* acct = database.LoadAccount(username.data.c_str(),password.data.c_str());
						if(acct){
							Client* otherclient = client_list.FindByLSID(acct->getLoginAccountID());
							if(otherclient)
								otherclient->getConnection()->SendDisconnect(); // This person is already logged in, we don't want them logged in twice, kick the previous client as it might be a ghost
						}
						if(acct){
							SetAccountName(username.data.c_str());
							database.UpdateAccountIPAddress(acct->getLoginAccountID(), getConnection()->GetrIP());
							LogWrite(LOGIN__INFO, 0, "Login", "%s successfully logged in.", (char*)username.data.c_str());
						}
						else
						{
							if (username.size > 0)
								LogWrite(LOGIN__ERROR, 0, "Login", "%s login failed!", (char*)username.data.c_str());
							else
								LogWrite(LOGIN__ERROR, 0, "Login", "[UNKNOWN USER] login failed!");
						}

						if(!acct)
							SendLoginDenied();
						else{
							needs_world_list = true;
							SetLoginAccount(acct);							
							SendLoginAccepted();							
						}
					}
					else{
						cout << "Error bad version: " << version << endl;
						SendLoginDeniedBadVersion();
					}
				}
				else{
					cout << "Error loading LS_LoginRequest packet: \n";
					//DumpPacket(app);
				}
				safe_delete(packet);
				break;
			}
			case OP_KeymapLoadMsg:{
			//	cout << "Received OP_KeymapNoneMsg\n";
				//dunno what this is for
				break;
								  }
			case OP_AllWSDescRequestMsg:{				
				SendWorldList();
				needs_world_list = false;
				database.LoadCharacters(GetLoginAccount(), GetOrigVersion());				
				SendCharList();				
				break;
										}
			case OP_LsClientCrashlogReplyMsg:{
//				DumpPacket(app);
				SaveErrorsToDB(app, "Crash Log");
				break;
											 }
			case OP_LsClientVerifylogReplyMsg:{
//				DumpPacket(app);
				SaveErrorsToDB(app, "Verify Log");
				break;
											  }
			case OP_LsClientAlertlogReplyMsg:{
//				DumpPacket(app);
				SaveErrorsToDB(app, "Alert Log");
				break;
											 }
			case OP_LsClientBaselogReplyMsg:{
//				DumpPacket(app);
				SaveErrorsToDB(app, "Base Log");
				break;
											}
			case OP_AllCharactersDescRequestMsg:{
				break;
			}
			case OP_CreateCharacterRequestMsg:{
				PacketStruct* packet = configReader.getStruct("CreateCharacter", GetOrigVersion());

				playWaitTimer = new Timer ( 15000 );
				playWaitTimer->Start ( );
				cout << "Char Create Request From: " << GetAccountName() << "....";
				if(packet->LoadPacketData(app->pBuffer,app->size)){
					cout << "Loaded Successfully\n";
					packet->setDataByName("account_id",GetAccountID());
					LWorld* world_server = world_list.FindByID(packet->getType_int32_ByName("server_id"));
					if(!world_server)
					{
						cout << GetAccountName() << " attempted creation of character with an invalid server id of: " << packet->getType_int32_ByName("server_id") << "\n";
						break;
					}
					else
					{
						ServerPacket* outpack = new ServerPacket(ServerOP_CharacterCreate, app->size+sizeof(int16));
						int16 out_version = GetOrigVersion();
						memcpy(outpack->pBuffer, &out_version, sizeof(int16));
						memcpy(outpack->pBuffer + sizeof(int16), app->pBuffer, app->size);
						uchar* tmp = outpack->pBuffer;
						tmp+=7;
						int32 account_id = GetAccountID();
						memcpy(tmp, &account_id, sizeof(int32));
						world_server->SendPacket(outpack);
						safe_delete(outpack);
						createRequest = packet;
					}
				}
				else{
					cout << "Error loading Char Create Packet!!\n";
					safe_delete(packet);
				}
				//	world_list.SendWorldChanged(create.profile.server_id, false, this);
				break;
											  }
			case OP_PlayCharacterRequestMsg:{
				int32 char_id = 0;
				int32 server_id = 0;
				PacketStruct* request = configReader.getStruct("LS_PlayRequest",GetVersion());

				if(request && request->LoadPacketData(app->pBuffer,app->size)){
					char_id = request->getType_int32_ByName("char_id");
					server_id = request->getType_int32_ByName("server_id");
					LWorld* world = world_list.FindByID(server_id);
					string name = database.GetCharacterName(char_id,server_id);
					if(world && name.length() > 0){
						pending_play_char_id = char_id;
						ServerPacket* outpack = new ServerPacket(ServerOP_UsertoWorldReq, sizeof(UsertoWorldRequest_Struct));
						UsertoWorldRequest_Struct* req = (UsertoWorldRequest_Struct*)outpack->pBuffer;
						req->char_id = char_id;
						req->lsaccountid = GetAccountID();
						req->worldid = server_id;

						struct in_addr in;
						in.s_addr = GetIP();
						strcpy(req->ip_address, inet_ntoa(in));
						world->SendPacket(outpack);
						delete outpack;

						safe_delete(playWaitTimer);

						playWaitTimer = new Timer ( 5000 );
						playWaitTimer->Start ( );
					}
					else{
						cout << GetAccountName() << " sent invalid Play Request: \n";
						SendPlayFailed(PLAY_ERROR_PROBLEM);
						DumpPacket(app);
					}
				}
				safe_delete(request);
				break;
											}
			case OP_DeleteCharacterRequestMsg:{
				PacketStruct* request = configReader.getStruct("LS_DeleteCharacterRequest", GetVersion());
				PacketStruct* response = configReader.getStruct("LS_DeleteCharacterResponse", GetVersion());
				if(request && response && request->LoadPacketData(app->pBuffer,app->size)){
					EQ2_16BitString name = request->getType_EQ2_16BitString_ByName("name");
					int32 acct_id = GetAccountID();
					int32 char_id = request->getType_int32_ByName("char_id");
					int32 server_id = request->getType_int32_ByName("server_id");
					if(database.VerifyDelete(acct_id, char_id, name.data.c_str())){
						response->setDataByName("response", 1);
						GetLoginAccount()->removeCharacter((char*)name.data.c_str());
						LWorld* world_server = world_list.FindByID(server_id);
						if(world_server != NULL)
							world_server->SendDeleteCharacter ( char_id , acct_id );
					}
					else
						response->setDataByName("response", 0);
					response->setDataByName("server_id", server_id);
					response->setDataByName("char_id", char_id);
					response->setDataByName("account_id", account_id);
					response->setMediumStringByName("name", (char*)name.data.c_str());
					response->setDataByName("max_characters", 10);

					EQ2Packet* outapp = response->serialize();
					QueuePacket(outapp);
				}
				safe_delete(request);
				safe_delete(response);
				break;
											  }
			default: {
				char* name = (char*)app->GetOpcodeName();
				if(name)
					cout << name;
				else
					cout << "Unknown";
				cout << " Packet: OPCode: 0x" << hex << setw(2) << setfill('0') << app->GetOpcode() << dec << ", size: " << setw(5) << setfill(' ') << app->Size() << " from " << GetAccountName() << endl;
				if (app->Size() < 128)
					DumpPacket(app);
					 }
			}
			delete app;
		}
	}

	if (!eqnc->CheckActive()) {
		return false;
	}

	return true;
}

void Client::SaveErrorsToDB(EQApplicationPacket* app, char* type){
	int32 size = 0;
	memcpy(&size, app->pBuffer + sizeof(int32), sizeof(int32));
	size++;
	char* message = new char[size];
	memset(message, 0, size);
	z_stream zstream;
	int zerror = 0;
	zstream.next_in		= app->pBuffer + 8;
	zstream.avail_in	= app->size - 8;
	zstream.next_out	= (BYTE*)message;
	zstream.avail_out	= size;
	zstream.zalloc    = Z_NULL;
	zstream.zfree     = Z_NULL;
	zstream.opaque		= Z_NULL;

	zerror = inflateInit( &zstream); 
	if(zerror != Z_OK) {
		safe_delete_array(message);
		return;
	}
	zerror = inflate( &zstream, 0 );
	if(message && strlen(message) > 0)
		database.SaveClientLog(type, message, GetLoginAccount()->getLoginName(), GetVersion());
	safe_delete_array(message);
}

void Client::CharacterApproved(int32 server_id,int32 char_id)
{
	if(createRequest && server_id == createRequest->getType_int32_ByName("server_id")){
		LWorld* world_server = world_list.FindByID(server_id);
		if(!world_server)
			return;

		PacketStruct* packet = configReader.getStruct("LS_CreateCharacterReply", GetVersion());
		if(packet){
			packet->setDataByName("account_id", GetAccountID());
			packet->setDataByName("response", CREATESUCCESS_REPLY);
			packet->setMediumStringByName("name", (char*)createRequest->getType_EQ2_16BitString_ByName("name").data.c_str());
			EQ2Packet* outapp = packet->serialize();
			QueuePacket(outapp);
			safe_delete(packet);
			database.SaveCharacter(createRequest, GetLoginAccount(),char_id);

			// refresh characters for this account
			database.LoadCharacters(GetLoginAccount(), GetVersion());
			
			SendCharList();
		}
	}
	else{
		cout << GetAccountName() << " received invalid CharacterApproval from server: " << server_id << endl;
	}
	safe_delete(createRequest);
}

void Client::CharacterRejected(int8 reason_number)
{
	PacketStruct* packet = configReader.getStruct("LS_CreateCharacterReply", GetVersion());
	if(createRequest && packet){
		packet->setDataByName("account_id", GetAccountID());
		int8 clientReasonNum = reason_number;
		// reason numbers change and instead of updating the world server
		// the login server will hold the up to date #'s
/*
		switch(reason_number)
		{
			// these error codes seem to be removed now, they shutdown the client rather immediately
			// for now we are just going to play a joke on them and say they can't create a new character.
		case INVALIDRACE_REPLY:
		case INVALIDGENDER_REPLY:
			clientReasonNum = 8;
			break;
		case BADNAMELENGTH_REPLY:
			clientReasonNum = 9;
			break;
		case NAMEINVALID_REPLY:
			clientReasonNum = 10;
			break;
		case NAMEFILTER_REPLY:
			clientReasonNum = 11;
			break;
		case NAMETAKEN_REPLY:
			clientReasonNum = 12;
			break;
		case OVERLOADEDSERVER_REPLY:
			clientReasonNum = 13;
			break;
		}
*/
		packet->setDataByName("response", clientReasonNum);
		packet->setMediumStringByName("name", "");
		EQ2Packet* outapp = packet->serialize();
		QueuePacket(outapp);
		safe_delete(packet);
	}
	/*LS_CreateCharacterReply reply(GetAccountID(), reason_number, create.profile.name.data);
	EQ2Packet* outapp = reply.serialize();
	QueuePacket(outapp);
	create.Clear();*/
}

void Client::SendCharList(){
	/*PacketStruct* packet = configReader.getStruct("LS_CreateCharacterReply");
	packet->setDataByName("account_id", GetAccountID());
	packet->setDataByName("response", reason_number);
	packet->setDataByName("name", &create.profile.name);
	EQ2Packet* outapp = packet->serialize();
	QueuePacket(outapp);
	safe_delete(packet);*/
	LogWrite(LOGIN__INFO, 0, "Login", "[%s] sending character list.", GetAccountName());
	LS_CharSelectList list;
	list.loadData(GetAccountID(), GetLoginAccount()->charlist, GetVersion()); 
	EQ2Packet* outapp = list.serialize(GetVersion());
//	DumpPacket(outapp);
	QueuePacket(outapp);

}
void Client::SendLoginDeniedBadVersion(){
	EQ2Packet* app = new EQ2Packet(OP_LoginReplyMsg, 0, sizeof(LS_LoginResponse));
	LS_LoginResponse* ls_response = (LS_LoginResponse*)app->pBuffer;
	ls_response->reply_code = 6;
	ls_response->unknown03 = 0xFFFFFFFF;
	ls_response->unknown04 = 0xFFFFFFFF;
	QueuePacket(app);
}
void Client::SendLoginDenied(){
	EQ2Packet* app = new EQ2Packet(OP_LoginReplyMsg, 0, sizeof(LS_LoginResponse));
	LS_LoginResponse* ls_response = (LS_LoginResponse*)app->pBuffer;
	ls_response->reply_code = 1;
	ls_response->unknown03 = 0xFFFFFFFF;
	ls_response->unknown04 = 0xFFFFFFFF;
	QueuePacket(app);
}

void Client::SendLoginAccepted(){ //all 0s are a success :)

	
	PacketStruct* packet = configReader.getStruct("LS_LoginReplyMsg",version);
	int i =0;
	if ( packet )
	{
	packet->setDataByName("account_id", 1);
	packet->setDataByName("login_response", 0);
	packet->setDataByName("reset_appearance", 0);
	packet->setDataByName("do_not_force_soga", 1);
	packet->setDataByName("race_unknown", 0x3F);
	packet->setDataByName("unknown11", 2); // can be 7
	packet->setDataByName("sub_level", 2);
	packet->setDataByName("race_flag", 0x1FFFFF);
	packet->setDataByName("class_flag", 0x7FFFFFE);
	packet->setMediumStringByName("username", GetAccountName());
	packet->setMediumStringByName("password", GetAccountName());
	packet->setDataByName("unknown5", 0x7C);
	packet->setDataByName("unknown7", 0xFF6FFFBF);

	// Image 2020 Notes
	// Login Server only supports AoM at current time, but we will need to keep in mind the structure for 60100 or later calls for additional custom fields
	// >=60100
	//packet->setDataByName("unknown7a", 0xFFFF);
	//packet->setDataByName("unknown8", 0xFF, 1);
		EQ2Packet* outapp = packet->serialize();
		QueuePacket(outapp);
		safe_delete(packet);
	}
	return;
	if(version >= 843){
		uchar login_accepted_packet[] ={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x7C,0x00,0x00,0xBF,0xBF,0xED,0x03
,0x1F,0x00,0x00,0x00,0x00,0x01,0x18,0x03,0x05,0x3C,0x02,0x03,0x01,0x00,0xF4,0xF4
,0xF4,0xFF,0xFF,0xFF,0x3D,0x02,0x08,0x01,0x00,0xF4,0xF4,0xF4,0xFF,0xFF,0xFF,0x41
,0x02,0x07,0x01,0x00,0xF4,0xF4,0xF4,0xFF,0xFF,0xFF,0xAE,0x0C,0x00,0x00,0x00,0xFF
,0xFF,0xFF,0xFF,0xFF,0xFF,0x34,0x0F,0x10,0x01,0x01,0x93,0x62,0x44,0xCF,0xCF,0xAF
,0x04,0x06,0x3C,0x02,0x03,0x01,0x00,0xB6,0x36,0x36,0xFF,0xFF,0xFF,0x41,0x02,0x07
,0x01,0x00,0xB6,0x36,0x36,0xFF,0xFF,0xFF,0x3D,0x02,0x08,0x01,0x00,0xB6,0x36,0x36
,0xFF,0xFF,0xFF,0x0F,0x09,0x00,0x01,0x01,0x67,0x54,0x42,0xA0,0xA0,0x50,0x0F,0x09
,0x00,0x01,0x01,0x67,0x54,0x42,0xA0,0xA0,0x50,0x34,0x0F,0x10,0x01,0x01,0x93,0x62
,0x44,0xCF,0xCF,0xAF,0x06,0x06,0x31,0x00,0x00,0x01,0x01,0xF4,0xF4,0xF4,0xF4,0xF4
,0xF4,0x31,0x00,0x00,0x01,0x01,0xF4,0xF4,0xF4,0xF4,0xF4,0xF4,0xF3,0x02,0x03,0x00
,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x31,0x00,0x07,0x00,0x00,0xFF,0xFF,0xFF,0xFF
,0xFF,0xFF,0x31,0x00,0x08,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,0x0E,0x10
,0x01,0x01,0xFF,0xFF,0x00,0x80,0x80,0x00,0x07,0x06,0xE6,0x09,0x00,0x01,0x01,0xBA
,0x7B,0x42,0xBA,0x7B,0x42,0xE6,0x09,0x00,0x01,0x01,0xBA,0x7B,0x42,0xBA,0x7B,0x42
,0xA6,0x01,0x08,0x01,0x01,0x77,0x60,0x46,0x77,0x60,0x46,0xAA,0x01,0x07,0x01,0x01
,0x77,0x60,0x46,0x77,0x60,0x46,0xC7,0x0F,0x03,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF
,0xFF,0xB2,0x0C,0x10,0x01,0x01,0xFF,0xFF,0x00,0x80,0x80,0x00,0x09,0x05,0x33,0x02
,0x03,0x01,0x00,0x2D,0x2D,0x2D,0xFF,0xFF,0xFF,0x34,0x02,0x08,0x01,0x00,0x2D,0x2D
,0x2D,0xFF,0xFF,0xFF,0x38,0x02,0x07,0x01,0x00,0x2D,0x2D,0x2D,0xFF,0xFF,0xFF,0x69
,0x09,0x00,0x01,0x01,0x6D,0x1C,0x1C,0x93,0x6B,0x6B,0x34,0x0F,0x10,0x01,0x01,0x93
,0x62,0x44,0xCF,0xCF,0xAF,0x0A,0x05,0x69,0x09,0x00,0x01,0x01,0xA7,0xA7,0xEB,0xA7
,0xA7,0xEB,0x33,0x02,0x03,0x01,0x00,0xF4,0xF4,0xF4,0xFF,0xFF,0xFF,0x38,0x02,0x07
,0x01,0x00,0xF4,0xF4,0xF4,0xFF,0xFF,0xFF,0x34,0x02,0x08,0x01,0x00,0xF4,0xF4,0xF4
,0xFF,0xFF,0xFF,0x34,0x0F,0x10,0x01,0x01,0x93,0x62,0x44,0xCF,0xCF,0xAF,0x0D,0x04
,0xEA,0x09,0x00,0x01,0x01,0xDD,0xDD,0x8C,0xDD,0xDD,0x8C,0x95,0x02,0x08,0x01,0x00
,0xF4,0xF4,0x0A,0xFF,0xFF,0xFF,0x94,0x02,0x03,0x01,0x00,0xF4,0xF4,0x0A,0xFF,0xFF
,0xFF,0x99,0x02,0x07,0x01,0x00,0xF4,0xF4,0x0A,0xFF,0xFF,0xFF,0x0E,0x04,0xC6,0x02
,0x08,0x01,0x00,0x13,0x13,0x13,0xFF,0xFF,0xFF,0xC5,0x02,0x03,0x01,0x00,0x13,0x13
,0x13,0xFF,0xFF,0xFF,0xCA,0x02,0x07,0x01,0x00,0x13,0x13,0x13,0xFF,0xFF,0xFF,0x14
,0x09,0x00,0x01,0x01,0x9C,0x4F,0x4F,0x2B,0x15,0x15,0x10,0x04,0xDF,0x09,0x00,0x01
,0x01,0x70,0xBA,0x70,0xBA,0x7B,0x42,0x38,0x04,0x08,0x01,0x00,0xB6,0xCD,0x2F,0xFF
,0xFF,0xFF,0x37,0x04,0x03,0x01,0x00,0xB6,0xCD,0x2F,0xFF,0xFF,0xFF,0x3C,0x04,0x07
,0x01,0x00,0xB6,0xCD,0x2F,0xFF,0xFF,0xFF,0x11,0x04,0xDF,0x09,0x00,0x01,0x01,0xBA
,0x7B,0x42,0x62,0xB3,0x62,0x38,0x04,0x08,0x01,0x00,0x1A,0x41,0x1A,0xFF,0xFF,0xFF
,0x3C,0x04,0x07,0x01,0x00,0x1A,0x41,0x1A,0xFF,0xFF,0xFF,0x37,0x04,0x03,0x01,0x00
,0x1A,0x41,0x1A,0xFF,0xFF,0xFF,0x13,0x04,0x59,0x0E,0x00,0x01,0x01,0x3B,0x7C,0x3B
,0xE2,0xE2,0x85,0xB6,0x03,0x08,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB5,0x03
,0x03,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBA,0x03,0x07,0x00,0x00,0xFF,0xFF
,0xFF,0xFF,0xFF,0xFF,0x14,0x04,0x59,0x0E,0x00,0x01,0x01,0x2B,0x34,0x21,0xE2,0xE2
,0x85,0xA8,0x03,0x08,0x01,0x01,0x18,0x18,0x18,0x18,0x18,0x18,0xA7,0x03,0x03,0x01
,0x01,0x18,0x18,0x18,0x18,0x18,0x18,0xAC,0x03,0x07,0x01,0x01,0x18,0x18,0x18,0x18
,0x18,0x18,0x17,0x04,0x4B,0x0E,0x00,0x01,0x01,0xE6,0x95,0xE6,0xE6,0x95,0xE6,0xDA
,0x01,0x07,0x01,0x01,0x9E,0x9E,0xD8,0xA3,0x6B,0x80,0x92,0x17,0x03,0x01,0x01,0x66
,0x42,0x4B,0x9E,0x9E,0xD8,0xD6,0x01,0x08,0x01,0x01,0x9E,0x9E,0xD8,0xA3,0x6B,0x80
,0x18,0x04,0x4D,0x0E,0x00,0x01,0x01,0xCF,0x2F,0xCF,0xE6,0x95,0xE6,0x92,0x17,0x03
,0x01,0x01,0x70,0x70,0x70,0x67,0x2B,0x67,0xD6,0x01,0x08,0x01,0x01,0x67,0x2B,0x67
,0x50,0x50,0x50,0xDA,0x01,0x07,0x01,0x01,0x67,0x2B,0x67,0x50,0x50,0x50,0x1A,0x04
,0xE4,0x0C,0x00,0x01,0x01,0xBA,0xFF,0xBA,0xD4,0xE9,0xFF,0x92,0x17,0x03,0x01,0x01
,0xDA,0xDA,0xA5,0x60,0x60,0x9E,0xDA,0x01,0x07,0x01,0x01,0x60,0x60,0x9E,0xDA,0xDA
,0xA5,0xD6,0x01,0x08,0x01,0x01,0x60,0x60,0x9E,0xDA,0xDA,0xA5,0x1B,0x04,0x92,0x17
,0x03,0x01,0x01,0x99,0x48,0x48,0xF7,0xCF,0x82,0xDA,0x01,0x07,0x01,0x01,0xF7,0xCF
,0x82,0x99,0x48,0x48,0xD6,0x01,0x08,0x01,0x01,0xF7,0xCF,0x82,0x99,0x48,0x48,0xD7
,0x0E,0x00,0x01,0x01,0x8E,0x46,0x46,0x2B,0x15,0x15,0x1D,0x04,0xA9,0x08,0x00,0x01
,0x01,0xE8,0xB6,0x85,0xE8,0xB6,0x85,0x92,0x17,0x03,0x01,0x01,0x57,0x85,0xAE,0xD8
,0xE8,0xF4,0xD6,0x01,0x08,0x01,0x01,0xD8,0xE8,0xF4,0x95,0xB3,0xCD,0xDA,0x01,0x07
,0x01,0x01,0xD8,0xE8,0xF4,0x95,0xB3,0xCD,0x1E,0x04,0x92,0x17,0x03,0x01,0x01,0x62
,0x57,0x4D,0xA3,0x9E,0x9A,0xD6,0x01,0x08,0x01,0x01,0xFF,0xDA,0xB6,0x6B,0x57,0x44
,0xDA,0x01,0x07,0x01,0x01,0xFF,0xDA,0xB6,0x6B,0x57,0x44,0x3A,0x0E,0x00,0x01,0x01
,0x2B,0x54,0x54,0x2B,0x15,0x15,0x21,0x06,0x64,0x03,0x08,0x01,0x00,0x7E,0x4B,0x46
,0xFF,0xFF,0xFF,0x68,0x03,0x07,0x01,0x00,0x7E,0x4B,0x46,0xFF,0xFF,0xFF,0x63,0x03
,0x03,0x01,0x00,0x7E,0x4B,0x46,0xFF,0xFF,0xFF,0xA9,0x08,0x00,0x01,0x01,0x1F,0x3F
,0x60,0x62,0x62,0x62,0xA9,0x08,0x00,0x01,0x01,0x1F,0x3F,0x60,0x62,0x62,0x62,0x42
,0x0F,0x10,0x01,0x01,0xFF,0xFF,0x00,0x80,0x80,0x00,0x22,0x06,0xD6,0x0C,0x00,0x01
,0x01,0xE6,0x95,0xE6,0x1A,0x1A,0x70,0xD6,0x0C,0x00,0x01,0x01,0xE6,0x95,0xE6,0x1A
,0x1A,0x70,0x64,0x03,0x08,0x01,0x00,0x5D,0x42,0x5D,0xFF,0xFF,0xFF,0x68,0x03,0x07
,0x01,0x00,0x5D,0x42,0x5D,0xFF,0xFF,0xFF,0x63,0x03,0x03,0x01,0x00,0x5D,0x42,0x5D
,0xFF,0xFF,0xFF,0x42,0x0F,0x10,0x01,0x01,0xFF,0xFF,0x00,0x80,0x80,0x00,0x24,0x06
,0x63,0x03,0x03,0x01,0x00,0x99,0xC8,0xE2,0xFF,0xFF,0xFF,0x64,0x03,0x08,0x01,0x00
,0x99,0xC8,0xE2,0xFF,0xFF,0xFF,0x68,0x03,0x07,0x01,0x00,0x99,0xC8,0xE2,0xFF,0xFF
,0xFF,0xD6,0x0C,0x00,0x01,0x01,0x85,0x85,0xA7,0xD1,0xD1,0xAC,0xD6,0x0C,0x00,0x01
,0x01,0x85,0x85,0xA7,0xD1,0xD1,0xAC,0x34,0x0F,0x10,0x01,0x01,0x93,0x62,0x44,0xCF
,0xCF,0xAF,0x25,0x06,0x63,0x03,0x03,0x01,0x00,0xBF,0xA5,0x7E,0xFF,0xFF,0xFF,0x5C
,0x03,0x08,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x60,0x03,0x07,0x00,0x00,0xFF
,0xFF,0xFF,0xFF,0xFF,0xFF,0xB1,0x08,0x00,0x01,0x01,0x90,0x48,0x48,0x90,0x48,0x48
,0xB1,0x08,0x00,0x01,0x01,0x90,0x48,0x48,0x90,0x48,0x48,0x34,0x0F,0x10,0x01,0x01
,0x93,0x62,0x44,0xCF,0xCF,0xAF,0x27,0x06,0xB9,0x16,0x08,0x01,0x01,0x3D,0x54,0x3D
,0xBC,0xBC,0xBC,0xB8,0x16,0x03,0x01,0x01,0x3D,0x54,0x3D,0xBC,0xBC,0xBC,0xBD,0x16
,0x07,0x01,0x01,0x3D,0x54,0x3D,0xBC,0xBC,0xBC,0x34,0x0F,0x10,0x01,0x01,0x31,0x4D
,0x3F,0xCF,0xCF,0xAF,0xCD,0x08,0x00,0x01,0x01,0x2B,0x54,0x3F,0x3F,0x98,0x6B,0xCD
,0x08,0x00,0x01,0x01,0x2B,0x54,0x3F,0x3F,0x98,0x6B,0x28,0x06,0xB9,0x16,0x08,0x01
,0x01,0x21,0x21,0x31,0x3F,0x3F,0x3F,0xB8,0x16,0x03,0x01,0x01,0x21,0x21,0x31,0x3F
,0x3F,0x3F,0xBD,0x16,0x07,0x01,0x00,0x48,0x48,0x54,0xFF,0xFF,0xFF,0x34,0x0F,0x10
,0x01,0x01,0x31,0x4D,0x3F,0xCF,0xCF,0xAF,0xA9,0x08,0x00,0x01,0x01,0x1A,0x1A,0x70
,0xE6,0x95,0xE6,0xA9,0x08,0x00,0x01,0x01,0x1A,0x1A,0x70,0xE6,0x95,0xE6,0x0A,0xD1
,0x00,0x00,0x00,0xD0,0x00,0x00,0x00,0xCF,0x00,0x00,0x00,0x6E,0x00,0x00,0x00,0x70
,0x00,0x00,0x00,0x71,0x00,0x00,0x00,0x72,0x00,0x00,0x00,0x73,0x00,0x00,0x00,0x74
,0x00,0x00,0x00,0x76,0x00,0x00,0x00};
		memcpy(login_accepted_packet+16, &account_id, sizeof(int32));
		EQ2Packet* app = new EQ2Packet(OP_LoginReplyMsg, login_accepted_packet, sizeof(login_accepted_packet));		
		QueuePacket(app);
	}
	else{
		uchar login_accepted_packet[] ={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
			,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x40,0x18,0x00,0x00,0xff,0xde,0x0d
			,0x00,0x00,0x01,0x18,0x03,0x05,0x3c,0x02,0x03,0x01,0x00,0xf4,0xf4,0xf4,0xff,0xff
			,0xff,0x3d,0x02,0x08,0x01,0x00,0xf4,0xf4,0xf4,0xff,0xff,0xff,0x41,0x02,0x07,0x01
			,0x00,0xf4,0xf4,0xf4,0xff,0xff,0xff,0xae,0x0c,0x00,0x00,0x00,0xff,0xff,0xff,0xff
			,0xff,0xff,0x34,0x0f,0x00,0x01,0x01,0x93,0x62,0x44,0xcf,0xcf,0xaf,0x04,0x06,0x3c
			,0x02,0x03,0x01,0x00,0xb6,0x36,0x36,0xff,0xff,0xff,0x41,0x02,0x07,0x01,0x00,0xb6
			,0x36,0x36,0xff,0xff,0xff,0x3d,0x02,0x08,0x01,0x00,0xb6,0x36,0x36,0xff,0xff,0xff
			,0x0f,0x09,0x00,0x01,0x01,0x67,0x54,0x42,0xa0,0xa0,0x50,0x0f,0x09,0x00,0x01,0x01
			,0x67,0x54,0x42,0xa0,0xa0,0x50,0x34,0x0f,0x00,0x01,0x01,0x93,0x62,0x44,0xcf,0xcf
			,0xaf,0x06,0x06,0x31,0x00,0x00,0x01,0x01,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0x31,0x00
			,0x00,0x01,0x01,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf3,0x02,0x03,0x00,0x00,0xff,0xff
			,0xff,0xff,0xff,0xff,0x31,0x00,0x07,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x31
			,0x00,0x08,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xf8,0x0e,0x00,0x01,0x01,0xff
			,0xff,0x00,0x80,0x80,0x00,0x07,0x06,0xe6,0x09,0x00,0x01,0x01,0xba,0x7b,0x42,0xba
			,0x7b,0x42,0xe6,0x09,0x00,0x01,0x01,0xba,0x7b,0x42,0xba,0x7b,0x42,0xa6,0x01,0x08
			,0x01,0x01,0x77,0x60,0x46,0x77,0x60,0x46,0xaa,0x01,0x07,0x01,0x01,0x77,0x60,0x46
			,0x77,0x60,0x46,0xc7,0x0f,0x03,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xb2,0x0c
			,0x00,0x01,0x01,0xff,0xff,0x00,0x80,0x80,0x00,0x09,0x05,0x33,0x02,0x03,0x01,0x00
			,0x2d,0x2d,0x2d,0xff,0xff,0xff,0x34,0x02,0x08,0x01,0x00,0x2d,0x2d,0x2d,0xff,0xff
			,0xff,0x38,0x02,0x07,0x01,0x00,0x2d,0x2d,0x2d,0xff,0xff,0xff,0x69,0x09,0x00,0x01
			,0x01,0x6d,0x1c,0x1c,0x93,0x6b,0x6b,0x34,0x0f,0x00,0x01,0x01,0x93,0x62,0x44,0xcf
			,0xcf,0xaf,0x0a,0x05,0x69,0x09,0x00,0x01,0x01,0xa7,0xa7,0xeb,0xa7,0xa7,0xeb,0x33
			,0x02,0x03,0x01,0x00,0xf4,0xf4,0xf4,0xff,0xff,0xff,0x38,0x02,0x07,0x01,0x00,0xf4
			,0xf4,0xf4,0xff,0xff,0xff,0x34,0x02,0x08,0x01,0x00,0xf4,0xf4,0xf4,0xff,0xff,0xff
			,0x34,0x0f,0x00,0x01,0x01,0x93,0x62,0x44,0xcf,0xcf,0xaf,0x0d,0x04,0xea,0x09,0x00
			,0x01,0x01,0xdd,0xdd,0x8c,0xdd,0xdd,0x8c,0x95,0x02,0x08,0x01,0x00,0xf4,0xf4,0x0a
			,0xff,0xff,0xff,0x94,0x02,0x03,0x01,0x00,0xf4,0xf4,0x0a,0xff,0xff,0xff,0x99,0x02
			,0x07,0x01,0x00,0xf4,0xf4,0x0a,0xff,0xff,0xff,0x0e,0x04,0xc6,0x02,0x08,0x01,0x00
			,0x13,0x13,0x13,0xff,0xff,0xff,0xc5,0x02,0x03,0x01,0x00,0x13,0x13,0x13,0xff,0xff
			,0xff,0xca,0x02,0x07,0x01,0x00,0x13,0x13,0x13,0xff,0xff,0xff,0x14,0x09,0x00,0x01
			,0x01,0x9c,0x4f,0x4f,0x2b,0x15,0x15,0x10,0x04,0xdf,0x09,0x00,0x01,0x01,0x70,0xba
			,0x70,0xba,0x7b,0x42,0x38,0x04,0x08,0x01,0x00,0xb6,0xcd,0x2f,0xff,0xff,0xff,0x37
			,0x04,0x03,0x01,0x00,0xb6,0xcd,0x2f,0xff,0xff,0xff,0x3c,0x04,0x07,0x01,0x00,0xb6
			,0xcd,0x2f,0xff,0xff,0xff,0x11,0x04,0xdf,0x09,0x00,0x01,0x01,0xba,0x7b,0x42,0x62
			,0xb3,0x62,0x38,0x04,0x08,0x01,0x00,0x1a,0x41,0x1a,0xff,0xff,0xff,0x3c,0x04,0x07
			,0x01,0x00,0x1a,0x41,0x1a,0xff,0xff,0xff,0x37,0x04,0x03,0x01,0x00,0x1a,0x41,0x1a
			,0xff,0xff,0xff,0x13,0x04,0x59,0x0e,0x00,0x01,0x01,0x3b,0x7c,0x3b,0xe2,0xe2,0x85
			,0xb6,0x03,0x08,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xb5,0x03,0x03,0x00,0x00
			,0xff,0xff,0xff,0xff,0xff,0xff,0xba,0x03,0x07,0x00,0x00,0xff,0xff,0xff,0xff,0xff
			,0xff,0x14,0x04,0x59,0x0e,0x00,0x01,0x01,0x2b,0x34,0x21,0xe2,0xe2,0x85,0xa8,0x03
			,0x08,0x01,0x01,0x18,0x18,0x18,0x18,0x18,0x18,0xa7,0x03,0x03,0x01,0x01,0x18,0x18
			,0x18,0x18,0x18,0x18,0xac,0x03,0x07,0x01,0x01,0x18,0x18,0x18,0x18,0x18,0x18,0x17
			,0x04,0x4b,0x0e,0x00,0x01,0x01,0xe6,0x95,0xe6,0xe6,0x95,0xe6,0xda,0x01,0x07,0x01
			,0x01,0x9e,0x9e,0xd8,0xa3,0x6b,0x80,0x92,0x17,0x03,0x01,0x01,0x66,0x42,0x4b,0x9e
			,0x9e,0xd8,0xd6,0x01,0x08,0x01,0x01,0x9e,0x9e,0xd8,0xa3,0x6b,0x80,0x18,0x04,0x4d
			,0x0e,0x00,0x01,0x01,0xcf,0x2f,0xcf,0xe6,0x95,0xe6,0x92,0x17,0x03,0x01,0x01,0x70
			,0x70,0x70,0x67,0x2b,0x67,0xd6,0x01,0x08,0x01,0x01,0x67,0x2b,0x67,0x50,0x50,0x50
			,0xda,0x01,0x07,0x01,0x01,0x67,0x2b,0x67,0x50,0x50,0x50,0x1a,0x04,0xe4,0x0c,0x00
			,0x01,0x01,0xba,0xff,0xba,0xd4,0xe9,0xff,0x92,0x17,0x03,0x01,0x01,0xda,0xda,0xa5
			,0x60,0x60,0x9e,0xda,0x01,0x07,0x01,0x01,0x60,0x60,0x9e,0xda,0xda,0xa5,0xd6,0x01
			,0x08,0x01,0x01,0x60,0x60,0x9e,0xda,0xda,0xa5,0x1b,0x04,0x92,0x17,0x03,0x01,0x01
			,0x99,0x48,0x48,0xf7,0xcf,0x82,0xda,0x01,0x07,0x01,0x01,0xf7,0xcf,0x82,0x99,0x48
			,0x48,0xd6,0x01,0x08,0x01,0x01,0xf7,0xcf,0x82,0x99,0x48,0x48,0xd7,0x0e,0x00,0x01
			,0x01,0x8e,0x46,0x46,0x2b,0x15,0x15,0x1d,0x04,0xa9,0x08,0x00,0x01,0x01,0xe8,0xb6
			,0x85,0xe8,0xb6,0x85,0x92,0x17,0x03,0x01,0x01,0x57,0x85,0xae,0xd8,0xe8,0xf4,0xd6
			,0x01,0x08,0x01,0x01,0xd8,0xe8,0xf4,0x95,0xb3,0xcd,0xda,0x01,0x07,0x01,0x01,0xd8
			,0xe8,0xf4,0x95,0xb3,0xcd,0x1e,0x04,0x92,0x17,0x03,0x01,0x01,0x62,0x57,0x4d,0xa3
			,0x9e,0x9a,0xd6,0x01,0x08,0x01,0x01,0xff,0xda,0xb6,0x6b,0x57,0x44,0xda,0x01,0x07
			,0x01,0x01,0xff,0xda,0xb6,0x6b,0x57,0x44,0x3a,0x0e,0x00,0x01,0x01,0x2b,0x54,0x54
			,0x2b,0x15,0x15,0x21,0x06,0x64,0x03,0x08,0x01,0x00,0x7e,0x4b,0x46,0xff,0xff,0xff
			,0x68,0x03,0x07,0x01,0x00,0x7e,0x4b,0x46,0xff,0xff,0xff,0x63,0x03,0x03,0x01,0x00
			,0x7e,0x4b,0x46,0xff,0xff,0xff,0xa9,0x08,0x00,0x01,0x01,0x1f,0x3f,0x60,0x62,0x62
			,0x62,0xa9,0x08,0x00,0x01,0x01,0x1f,0x3f,0x60,0x62,0x62,0x62,0x42,0x0f,0x00,0x01
			,0x01,0xff,0xff,0x00,0x80,0x80,0x00,0x22,0x06,0xd6,0x0c,0x00,0x01,0x01,0xe6,0x95
			,0xe6,0x1a,0x1a,0x70,0xd6,0x0c,0x00,0x01,0x01,0xe6,0x95,0xe6,0x1a,0x1a,0x70,0x64
			,0x03,0x08,0x01,0x00,0x5d,0x42,0x5d,0xff,0xff,0xff,0x68,0x03,0x07,0x01,0x00,0x5d
			,0x42,0x5d,0xff,0xff,0xff,0x63,0x03,0x03,0x01,0x00,0x5d,0x42,0x5d,0xff,0xff,0xff
			,0x42,0x0f,0x00,0x01,0x01,0xff,0xff,0x00,0x80,0x80,0x00,0x24,0x06,0x63,0x03,0x03
			,0x01,0x00,0x99,0xc8,0xe2,0xff,0xff,0xff,0x64,0x03,0x08,0x01,0x00,0x99,0xc8,0xe2
			,0xff,0xff,0xff,0x68,0x03,0x07,0x01,0x00,0x99,0xc8,0xe2,0xff,0xff,0xff,0xd6,0x0c
			,0x00,0x01,0x01,0x85,0x85,0xa7,0xd1,0xd1,0xac,0xd6,0x0c,0x00,0x01,0x01,0x85,0x85
			,0xa7,0xd1,0xd1,0xac,0x34,0x0f,0x00,0x01,0x01,0x93,0x62,0x44,0xcf,0xcf,0xaf,0x25
			,0x06,0x63,0x03,0x03,0x01,0x00,0xbf,0xa5,0x7e,0xff,0xff,0xff,0x5c,0x03,0x08,0x00
			,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x60,0x03,0x07,0x00,0x00,0xff,0xff,0xff,0xff
			,0xff,0xff,0xb1,0x08,0x00,0x01,0x01,0x90,0x48,0x48,0x90,0x48,0x48,0xb1,0x08,0x00
			,0x01,0x01,0x90,0x48,0x48,0x90,0x48,0x48,0x34,0x0f,0x00,0x01,0x01,0x93,0x62,0x44
			,0xcf,0xcf,0xaf,0x27,0x06,0xb9,0x16,0x08,0x01,0x01,0x3d,0x54,0x3d,0xbc,0xbc,0xbc
			,0xb8,0x16,0x03,0x01,0x01,0x3d,0x54,0x3d,0xbc,0xbc,0xbc,0x68,0x03,0x07,0x01,0x00
			,0x3d,0x54,0x3d,0xff,0xff,0xff,0x34,0x0f,0x00,0x01,0x01,0x31,0x4d,0x3f,0xcf,0xcf
			,0xaf,0xcd,0x08,0x00,0x01,0x01,0x2b,0x54,0x3f,0x3f,0x98,0x6b,0xcd,0x08,0x00,0x01
			,0x01,0x2b,0x54,0x3f,0x3f,0x98,0x6b,0x28,0x06,0xb9,0x16,0x08,0x01,0x01,0x21,0x21
			,0x31,0x3f,0x3f,0x3f,0xb8,0x16,0x03,0x01,0x01,0x21,0x21,0x31,0x3f,0x3f,0x3f,0x68
			,0x03,0x07,0x01,0x00,0x48,0x48,0x54,0xff,0xff,0xff,0x34,0x0f,0x00,0x01,0x01,0x31
			,0x4d,0x3f,0xcf,0xcf,0xaf,0xa9,0x08,0x00,0x01,0x01,0x1a,0x1a,0x70,0xe6,0x95,0xe6
			,0xa9,0x08,0x00,0x01,0x01,0x1a,0x1a,0x70,0xe6,0x95,0xe6,0x0a,0xd1,0x00,0x00,0x00
			,0xd0,0x00,0x00,0x00,0xcf,0x00,0x00,0x00,0x6e,0x00,0x00,0x00,0x70,0x00,0x00,0x00
			,0x71,0x00,0x00,0x00,0x72,0x00,0x00,0x00,0x73,0x00,0x00,0x00,0x74,0x00,0x00,0x00
			,0x76,0x00,0x00,0x00};
		memcpy(login_accepted_packet+16, &account_id, sizeof(int32));
		EQ2Packet* app = new EQ2Packet(OP_LoginReplyMsg, login_accepted_packet, sizeof(login_accepted_packet));
		QueuePacket(app);
	}
	
	/*EQ2Packet* app = new EQ2Packet(OP_LoginReplyMsg, 0, sizeof(LS_LoginResponse));
	LS_LoginResponse* ls_response = (LS_LoginResponse*)app->pBuffer;
	ls_response->accountid = GetAccountID();
	QueuePacket(app);*/
}
void Client::SendWorldList(){
	EQ2Packet* pack = world_list.MakeServerListPacket(lsadmin, version);
	EQ2Packet* dupe = pack->Copy();
	DumpPacket(dupe->pBuffer,dupe->size);
	QueuePacket(dupe);
	return;
}
void Client::QueuePacket(EQ2Packet* app){
	eqnc->EQ2QueuePacket(app);
}

void Client::WorldResponse(int32 worldid, int8 response, char* ip_address, int32 port, int32 access_key)
{
	LWorld* world = world_list.FindByID(worldid);
	if(world == 0) {
		FatalError(0);
		return;
	}
	if(response != 1){
		if(response == PLAY_ERROR_CHAR_NOT_LOADED){
			string pending_play_char_name = database.GetCharacterName(pending_play_char_id, worldid);
			if(database.VerifyDelete(GetAccountID(), pending_play_char_id, pending_play_char_name.c_str())){
				GetLoginAccount()->removeCharacter((char*)pending_play_char_name.c_str());
			}
		}
		FatalError(response);
		return;
	}

	PacketStruct* response_packet = configReader.getStruct("LS_PlayResponse", GetVersion());
	if(response_packet){
		safe_delete(playWaitTimer);
		response_packet->setDataByName("response", 1);
		response_packet->setSmallStringByName("server", ip_address);
		response_packet->setDataByName("port", port);
		response_packet->setDataByName("account_id", GetAccountID());
		response_packet->setDataByName("access_code", access_key);
		EQ2Packet* outapp = response_packet->serialize();
		QueuePacket(outapp);
		safe_delete(response_packet);
		disconnectTimer = new Timer(1000);
		disconnectTimer->Start();
	}
	return;
}
void Client::FatalError(int8 response) {
	safe_delete(playWaitTimer);
	SendPlayFailed(response);
}

void Client::SendPlayFailed(int8 response){
	PacketStruct* response_packet = configReader.getStruct("LS_PlayResponse", GetVersion());
	if(response_packet){
		response_packet->setDataByName("response", response);
		response_packet->setSmallStringByName("server", "");
		response_packet->setDataByName("port", 0);
		response_packet->setDataByName("account_id", GetAccountID());
		response_packet->setDataByName("access_code", 0);
		EQ2Packet* outapp = response_packet->serialize();
		QueuePacket(outapp);
		safe_delete(response_packet);
	}
}

void ClientList::Add(Client* client) {
	MClientList.writelock();
	client_list[client] = true;
	MClientList.releasewritelock();
}

Client* ClientList::Get(int32 ip, int16 port) {
	Client* ret = 0;
	map<Client*, bool>::iterator itr;
	MClientList.readlock();
	for(itr = client_list.begin(); itr != client_list.end(); itr++){
		if(itr->first->GetIP() == ip && itr->first->GetPort() == port){
			ret = itr->first;
			break;
		}
	}
	MClientList.releasereadlock();
	return ret;
}

void ClientList::FindByCreateRequest(){
	Client* client = 0;
	map<Client*, bool>::iterator itr;
	MClientList.readlock();
	for(itr = client_list.begin(); itr != client_list.end(); itr++){
		if(itr->first->AwaitingCharCreationRequest()){
			if(!client)
				client = itr->first;
			else{
				client = 0;//more than 1 character waiting, dont want to send rejection to wrong one
				break;
			}
		}
	}
	MClientList.releasereadlock();
	if(client)
		client->CharacterRejected(UNKNOWNERROR_REPLY);
}

Client* ClientList::FindByLSID(int32 lsaccountid) {
	Client* client = 0;
	map<Client*, bool>::iterator itr;
	MClientList.readlock();
	for(itr = client_list.begin(); itr != client_list.end(); itr++){
		if(itr->first->GetAccountID() == lsaccountid){
			client = itr->first;
			break;
		}
	}
	MClientList.releasereadlock();
	return client;
}
void ClientList::SendPacketToAllClients(EQ2Packet* app){
	Client* client = 0;
	map<Client*, bool>::iterator itr;
	MClientList.readlock();
	if(client_list.size() > 0){
		for(itr = client_list.begin(); itr != client_list.end(); itr++){
			itr->first->QueuePacket(app->Copy());
		}
	}
	safe_delete(app);
	MClientList.releasereadlock();
}
void ClientList::Process() {
	Client* client = 0;
	vector<Client*> erase_list;
	map<Client*, bool>::iterator itr;
	MClientList.readlock();	
	for(itr = client_list.begin(); itr != client_list.end(); itr++){		
		client = itr->first;
		if(!client->Process())
			erase_list.push_back(client);		
	}
	MClientList.releasereadlock();
	if(erase_list.size() > 0){
		vector<Client*>::iterator erase_itr;
		MClientList.writelock();
		for(erase_itr = erase_list.begin(); erase_itr != erase_list.end(); erase_itr++){
			client = *erase_itr;					
			struct in_addr	in;
			in.s_addr = client->getConnection()->GetRemoteIP();
			net.numclients--;
			cout << Timer::GetCurrentTime2() << " Removing client from ip: " << inet_ntoa(in) << " port: " << ntohs(client->getConnection()->GetRemotePort()) << " Name: " << client->GetAccountName() << endl;
			client->getConnection()->SetState(CLOSED);
			net.UpdateWindowTitle();
			client_list.erase(client);
		}
		MClientList.releasewritelock();
	}
}
