www.pudn.com > loseserver.rar > Loginserver.cpp


/* 
Copyright (C) 2004  freeplay.dk 
 
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. 
 
You may contact me for further information on admin@freeplay.dk 
*/ 
 
#define WIN32_LEAN_AND_MEAN 
 
// disable map warnings for std::map 
#pragma warning (disable: 4786) 
#pragma warning (disable: 4788) 
 
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include "Loginserver.h" 
#include "resource.h" 
#include "Logging.h" 
#include "CConnection.h" 
#include "Types.h" 
#include "OpCodes.h" 
#include "Database.h" 
#include "ComWindows.h" 
 
#include "LoginMap.h" 
#include "CharMap.h" 
#include "ObjectsMultimap.h" 
#include "Serversettings.h" 
 
 
using namespace std; 
 
//******************************************* 
// class defines 
//******************************************* 
database logindb; 
ComWindows lcom; 
extern LoginMap dblmap; 
extern charmap chm; 
extern objects obj; 
extern ServerSettings ss; 
 
//*********************************************************** 
// Version packet struct from server upon connection. 
//*********************************************************** 
struct CS_AuthPacket 
{ 
	int16 hardcodedfirst; 
	unsigned long codepage; 
	int8 valueregistry; 
	int16 hardcodedlast; 
}; 
 
//*********************************************************** 
// Version packet from server upon connection. 
//*********************************************************** 
void LoginServer::sendversionpack(DWORD ptr, char * buffer) 
{ 
	CConnection* c = reinterpret_cast  (ptr); 
	char			cip[15]; 
	unsigned int	cp = 0; 
	c->PeerInfo (&cip[0], 15, &cp); 
 
	struct CS_AuthPacket ap; 
	int16* hardcoded = (int16*)(buffer + 0); 
	ap.hardcodedfirst = *hardcoded; 
	unsigned long* codepage = (unsigned long*)(buffer + 2); 
	ap.codepage = *codepage; 
	int8* regvalue = (int8*)(buffer + 6); 
	ap.valueregistry = *regvalue; 
	int16* hardcodedlast = (int16*)(buffer + 7); 
	ap.hardcodedlast = *hardcodedlast; 
 
	int8 OpCode = l_sc_versionpack; 
	int8 MustBe = 0x00; 
	int8 LowVer = 0x02; 
	unsigned long serverver = htonl( 0x7C9D0000 ); 
	unsigned long cachever	= htonl( 0x119D0000 ); 
	unsigned long authver	= htonl( 0x1A790000 ); 
	unsigned long npcver	= htonl( 0x749D0000 ); 
	unsigned long uptime	= htonl( 0x012AC740 ); 
	int8 unk1 = 0x00; 
	int8 unk2 = 0x80; 
	int8 language; 
	if(ap.codepage == 936 || ap.codepage == 950) 
	{ 
		language = 0x03; // chinese, simplyfied chinese (03) ? 
	} 
	else if(ap.codepage == 949) 
	{ 
		language = 0x02; // korean (02) ? 
	} 
	else 
	{ 
		language = 0x01; // english (01) 
	} 
 
	unsigned char rest[] = { 
	0x3D, 0xEF, 0x03, 0xB3, 0x24, 0x01 
	}; 
 
	char buf[32]; 
	char* buf_ptr = buf;  
 
	memcpy(buf_ptr,(char*)&OpCode,1); 
	buf_ptr+=1; 
	memcpy(buf_ptr,(char*)&MustBe,1); 
	buf_ptr+=1; 
	memcpy(buf_ptr,(char*)&LowVer,1); 
	buf_ptr+=1; 
	memcpy(buf_ptr,(char*)&serverver,4); 
	buf_ptr+=4; 
	memcpy(buf_ptr,(char*)&cachever,4); 
	buf_ptr+=4; 
	memcpy(buf_ptr,(char*)&authver,4); 
	buf_ptr+=4; 
	memcpy(buf_ptr,(char*)&npcver,4); 
	buf_ptr+=4; 
	memcpy(buf_ptr,(char*)&uptime,4); 
	buf_ptr+=4; 
	memcpy(buf_ptr,(char*)&unk1,1); 
	buf_ptr+=1; 
	memcpy(buf_ptr,(char*)&unk2,1); 
	buf_ptr+=1; 
	memcpy(buf_ptr,(char*)&language,1); 
	buf_ptr+=1; 
	memcpy(buf_ptr,(char*)&rest,6); 
 
	sendpacket(buf, 32, ptr); 
	CheckAmount(ptr); 
} 
 
//*********************************************************** 
// Check if server is full 
//*********************************************************** 
void LoginServer::CheckAmount(DWORD ptr) 
{ 
	CConnection* c = reinterpret_cast  (ptr); 
 
	int maxusers = atoi(ss.getMaxusers("Maxusers")); 
	int currentusers = ss.getUsersonline(); 
 
	if(maxusers == currentusers) 
	{ 
		// send message and disconnect user 
		// TODO : NEED PACKET TO SEND. 
		c->Disconnect(); 
	} 
	return; 
} 
 
//*********************************************************** 
// Check the user name and password 
//*********************************************************** 
struct CS_LoginPacket 
{ 
	string username; 
	string password; 
	DWORD ip; 
}; 
 
void LoginServer::checkname(HWND hdwnd, char * buffer, DWORD ptr) 
{ 
	CConnection* c = reinterpret_cast  (ptr); 
	char			cip[15]; 
	unsigned int	cp = 0; 
	c->PeerInfo (&cip[0], 15, &cp); 
 
	struct CS_LoginPacket lp; 
 
    char* username = (char*)&buffer[0]; 
    lp.username = username; 
    char* password = buffer + strlen(username) + 1; 
    lp.password = password; 
    int* ip = (int*)(buffer + strlen(username) + 1 + strlen(password) + 1); 
    lp.ip = *ip; 
 
	lcom.WriteDataStr(hdwnd , "Login request for account : %s", lp.username.c_str()); 
	Log2File(TRUE, "Login request for account : %s\n", lp.username.c_str()); 
 
	int loginreq = logindb.checklogin(hdwnd, ptr, (char *)lp.username.c_str(), (char *)lp.password.c_str()); 
 
	if(loginreq == 0) 
	{ 
		// login failed, wrong username or password. 
		char buf[16]; 
		char* buf_ptr = buf; 
 
		int8 opcode = l_sc_loginstatus; 
		unsigned char loginerror[] = { 
		0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 
		}; 
 
		memcpy(buf_ptr,(char*)&opcode,1); 
		buf_ptr+=1; 
		memcpy(buf_ptr,(char*)loginerror, sizeof(loginerror)); 
 
		sendpacket( buf, 16, ptr); 
 
		lcom.WriteDataStr(hdwnd , "Login failed for account : %s", lp.username.c_str()); 
		Log2File(TRUE, "Login failed for account : %s\n", lp.username.c_str()); 
	} 
	else if(loginreq == 2) 
	{ 
		// send packet to new user that other user is playing. 
		char buf[16]; 
		char* buf_ptr = buf;		 
		 
		int8 opcode = l_sc_loginstatus; 
		unsigned char alreadyon[] = { 
		0x16, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 
		}; 
 
		memcpy(buf_ptr,(char*)&opcode,1); 
		buf_ptr+=1; 
		memcpy(buf_ptr,(char*)alreadyon, sizeof(alreadyon)); 
 
		sendpacket( buf, 16, ptr); 
	} 
	else 
	{ 
		// login success 
		lcom.WriteDataStr(hdwnd , "Login success for account : %s", lp.username.c_str()); 
		Log2File(TRUE, "Login success for account : %s\n", lp.username.c_str()); 
		lcom.AddUserOnline(hdwnd, lp.username.c_str()); 
		sendloginoktest((char *)lp.username.c_str(), ptr); 
	} 
	return; 
} 
 
//*********************************************************** 
// Login successful 
//*********************************************************** 
void LoginServer::sendloginoktest(char * username, DWORD ptr) 
{ 
	CConnection* c = reinterpret_cast  (ptr); 
	char			cip[15]; 
	unsigned int	cp = 0; 
	c->PeerInfo (&cip[0], 15, &cp); 
 
	char buf[16]; 
	char* buf_ptr = buf; 
 
	int8 opcode = l_sc_loginstatus; 
	unsigned char plain[] = { 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x12 
	}; 
 
	memcpy(buf_ptr,(char*)&opcode,1); 
	buf_ptr+=1; 
	memcpy(buf_ptr,(char*)plain, sizeof(plain)); 
 
	sendpacket( buf, 16, ptr); 
	 
	charamount(username, ptr); 
	return; 
} 
 
//*********************************************************** 
// packet sent after successful login, contains amount 
// of chars users got in the database on byte[2] 
//*********************************************************** 
struct charpack 
{ 
	BYTE OpCode; 
	BYTE amount; 
	long leftovers; 
	int16 leftovers1; 
}; 
 
void LoginServer::charamount(char * username, DWORD ptr) 
{ 
	CConnection* c = reinterpret_cast  (ptr); 
	char			cip[15]; 
	unsigned int	cp = 0; 
	c->PeerInfo (&cip[0], 15, &cp); 
	struct charpack cpk; 
 
	int getvalue; 
	getvalue = logindb.loginamountchars(username); 
 
	cpk.OpCode = l_sc_charamount; 
	cpk.amount = getvalue; 
	cpk.leftovers = 0x4DB1CC7C; // unknown (perhaps some form of gmtime() ) 
	cpk.leftovers1 = 0x7427; // unknown 
 
	sendpacket((char*)&cpk, 8, ptr); 
	logindb.getcharids(getvalue, username, ptr); 
 
	return; 
} 
 
//*********************************************************** 
// user want to create a character 
//*********************************************************** 
struct character 
{ 
	string charname; 
	BYTE charclass; 
	BYTE gender; 
	BYTE str; 
	BYTE dex; 
	BYTE con; 
	BYTE wis; 
	BYTE cha; 
	BYTE intel; 
}; 
 
void LoginServer::createchar(int accid, char * buffer, DWORD ptr) 
{ 
	CConnection* c = reinterpret_cast  (ptr); 
	char			cip[15]; 
	unsigned int	cp = 0; 
	c->PeerInfo (&cip[0], 15, &cp); 
 
	struct character ch; 
 
    char* username = (char*)&buffer[0]; 
    ch.charname = username; 
    BYTE charclass = (int)buffer[strlen(username) + 1]; 
    ch.charclass = charclass; 
	BYTE gender = (int)buffer[strlen(username) + 2]; 
	ch.gender = gender; 
	BYTE str = (BYTE)buffer[strlen(username) + 3]; 
	ch.str = str; 
	BYTE dex = (BYTE)buffer[strlen(username) + 4]; 
	ch.dex = dex; 
	BYTE con = (BYTE)buffer[strlen(username) + 5]; 
	ch.con = con; 
	BYTE wis = (BYTE)buffer[strlen(username) + 6]; 
	ch.wis = wis; 
	BYTE cha = (BYTE)buffer[strlen(username) + 7]; 
	ch.cha = cha; 
	BYTE intel = (BYTE)buffer[strlen(username) + 8]; 
	ch.intel = intel; 
 
	BYTE totalvalue = ch.str + ch.dex + ch.con + ch.wis + ch.cha + ch.intel; 
 
	if(totalvalue < 75) 
	{ 
		// need to add all the points (send points still leftover). 
		char buf[8]; 
		char* buf_ptr = buf; 
		 
		int8 opcode = l_sc_createcharstatus; 
		unsigned char valuewrong[] = { 0x15, 0x06, 0x27, 0x39, 0xB6, 0xB9, 0x2B }; 
 
		memcpy(buf_ptr,(char*)&opcode,1); 
		buf_ptr+=1; 
		memcpy(buf_ptr,(char*)valuewrong, sizeof(valuewrong)); 
 
		sendpacket( buf, 8, ptr); 
	} 
	else 
	{ 
		if (logindb.createnewchar(accid, (char *)ch.charname.c_str(), ch.charclass, ch.gender, ch.str, ch.dex, ch.con, ch.wis, ch.cha, ch.intel) == 0) 
		{ 
			// create char failed (already exsists) 
			char buf[8]; 
			char* buf_ptr = buf; 
			 
			int8 opcode = l_sc_createcharstatus; 
			unsigned char failed[] = { 0x06, 0x00, 0x8F, 0xB2, 0x28, 0x01, 0x53 }; 
 
			memcpy(buf_ptr,(char*)&opcode,1); 
			buf_ptr+=1; 
			memcpy(buf_ptr,(char*)failed, sizeof(failed)); 
 
			sendpacket( buf, 8, ptr); 
		} 
		else 
		{ 
			// create char success 
			char buf[8]; 
			char* buf_ptr = buf; 
 
			int8 opcode = l_sc_createcharstatus; 
			unsigned char success[] = { 0x02, 0x66, 0x2D, 0x01, 0x56, 0xB7, 0x2D }; 
 
			memcpy(buf_ptr,(char*)&opcode,1); 
			buf_ptr+=1; 
			memcpy(buf_ptr,(char*)success, sizeof(success)); 
 
			sendpacket( buf, 8, ptr); 
			logindb.generatenewcharpack(ptr, (char *)ch.charname.c_str()); 
		} 
	} 
} 
 
//*********************************************************** 
// request login to gameserver 
//*********************************************************** 
void LoginServer::reqlogin(HWND hdwnd, DWORD ptr, char * charname) 
{ 
	CConnection* c = reinterpret_cast  (ptr); 
	char			cip[15]; 
	unsigned int	cp = 0; 
	c->PeerInfo (&cip[0], 15, &cp); 
 
	// remove all previous known objects if any (multimap). 
	obj.removeMap(cp); 
	// set user into memory (charmap) 
	chm.setSocket(cp, cp); 
	chm.setCharname(cp, (string)charname); 
	chm.setPtr(cp, ptr); 
	unsigned long objid = logindb.getnewid(); 
	chm.setObjectid(cp, objid); 
 
	// needs to be analyzed. 
	char buf[8]; 
	char* buf_ptr = buf; 
 
	int8 opcode = l_sc_unknown1; 
	unsigned char pack1[] = { 
	0x03, 0x01, 0x14, 0x0B, 0x12, 0x00, 0x8B 
	}; 
 
	memcpy(buf_ptr,(char*)&opcode,1); 
	buf_ptr+=1; 
	memcpy(buf_ptr,(char*)pack1, sizeof(pack1)); 
 
	sendpacket( buf, 8, ptr); 
 
	// need analyzing aswell 
	char buf1[24]; 
	char* buf_ptr1 = buf1; 
 
	int8 opcode1 = l_sc_unknown2; 
	unsigned char pack2[] = { 
	0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0xFA, 0x00, 0x1C, 0x82, 0xDE, 0x7D 
	}; 
 
	memcpy(buf_ptr1,(char*)&opcode1,1); 
	buf_ptr1+=1; 
	memcpy(buf_ptr1,(char*)pack2, sizeof(pack2)); 
 
	sendpacket( buf1, 24, ptr); 
 
	sendinv(hdwnd, ptr); 
} 
 
//*********************************************************** 
// send inventory list to user 
//*********************************************************** 
void LoginServer::sendinv(HWND hdwnd, DWORD ptr) 
{ 
	CConnection* c = reinterpret_cast  (ptr); 
	char			cip[15]; 
	unsigned int	cp = 0; 
	c->PeerInfo (&cip[0], 15, &cp); 
 
	string us = chm.getCharname(cp); 
	char * charname = strdup(us.c_str()); 
 
	logindb.statuspacket(charname, ptr); 
	logindb.getmapid(charname, ptr); 
	logindb.dbownchar(charname, ptr); 
 
	// server ingame settings 
	char buf1[8]; 
	char* buf_ptr1 = buf1; 
 
	int8 opcode1 = l_sc_serversettings; 
	unsigned char sendtest3[] = { 
	// is it snowing, raining ect, ect.. 0x01 = light snow, 0x02 = heavy snow, 0x03 =  
	0x00, 0xFC, 0x5D, 0xC9, 0xC4, 0x05, 0xB5 
	}; 
 
	memcpy(buf_ptr1,(char*)&opcode1,1); 
	buf_ptr1+=1; 
	memcpy(buf_ptr1,(char*)sendtest3, sizeof(sendtest3)); 
 
	sendpacket( buf1, 8, ptr); 
	/* 
	char bufx[43]; 
	char* buf_ptr = bufx; 
 
	int8 opcode = g_sc_chat; 
	int8 type = 0x00; 
	char * welcomemessage = "*** Welcome to LoSE Version 0.3 Beta ***"; 
	int8 end = 0x00; 
 
	memcpy(buf_ptr,(char*)&opcode,1); 
	buf_ptr+=1; 
	memcpy(buf_ptr,(char*)&type,1); 
	buf_ptr+=1; 
	memcpy(buf_ptr,(char*)welcomemessage, strlen(welcomemessage)); 
	buf_ptr+=strlen(welcomemessage); 
	memcpy(buf_ptr,(char*)&end,1); 
 
	int size = strlen(welcomemessage)+3; 
 
	sendpacket( bufx, size, ptr); 
	*/ 
	sendtimenow( ptr ); 
} 
 
//*********************************************************** 
// send current time (final before passing to gameserver). 
//*********************************************************** 
int LoginServer::sendtimenow(DWORD ptr) 
{	 
	long mytime1; 
	mytime1 = ( logindb.getservertime() ); // maybe need add -300 
 
    tm * ptm; 
    ptm = gmtime ( &mytime1 ); 
 
	CConnection* c = reinterpret_cast  (ptr); 
	char			cip[15]; 
	unsigned int	cp = 0; 
	c->PeerInfo (&cip[0], 15, &cp); 
 
	char buftime[8]; 
	char* buf_ptr = buftime; 
	int8 opcode = g_sc_ingametime; 
	unsigned char unknown[] = { 0x01, 0x08, 0x00 }; 
 
	memcpy(buf_ptr,(char*)&opcode,1); 
	buf_ptr+=1; 
	memcpy(buf_ptr,(char*)&mytime1,4); 
	buf_ptr+=4; 
	memcpy(buf_ptr,(char*)&unknown,3); 
 
	sendpacket( buftime, 8, ptr ); 
 
	mytime1 = NULL; 
	return 0; 
}