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; }