Files
ROSS/Src/Char Server/charserver.cpp
T
2025-08-11 11:09:09 -05:00

205 lines
8.2 KiB
C++

/*
Rose Online Server Emulator
Copyright (C) 2006,2007 OSRose Team http://osroseon.to.md
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
depeloped with Main erose/hrose source server + some change from the original eich source
*/
#include "charserver.h"
// Constructor
CCharServer::CCharServer( string fn )
{
LoadConfigurations( (char*)fn.c_str() );
GServer = this;
}
// Deconstructor
CCharServer::~CCharServer( )
{
}
// Return a new clientsocket structure
CCharClient* CCharServer::CreateClientSocket( )
{
CCharClient* thisclient = new (nothrow) CCharClient( );
return thisclient;
}
//loadserver encryption
void CCharServer::LoadEncryption( )
{
GenerateCryptTables( CryptTable, 0x87654321 );
}
// When Server is ready
bool CCharServer::OnServerReady( )
{
DB->QExecute( "DELETE FROM channels WHERE id=%u", Config.ServerID);
if(!DB->QExecute("INSERT INTO channels (id,name,host,port,connected,maxconnections,owner) VALUES (%i,'%s','%s',%i,0,%i,%i)",
Config.ServerID, Config.ServerName, Config.CharIP, Config.CharPort, Config.MaxConnections, Config.ParentID))
{
Log(MSG_WARNING, "Error accessing to database, the other server will not connect to CharServer" );
}
MYSQL_RES *result;
MYSQL_ROW row;
// Load all our clans
result = DB->QStore("SELECT id,logo,back,name,cp,grade,slogan,news FROM list_clan");
if(result==NULL) return false;
while(row = mysql_fetch_row(result))
{
CClans* thisclan = new CClans;
assert(thisclan); // maybe remove
thisclan->id = atoi(row[0]);
thisclan->logo = atoi(row[1]);
thisclan->back = atoi(row[2]);
strcpy(thisclan->name,row[3]);
thisclan->cp = atoi(row[4]);
thisclan->grade = atoi(row[5]);
strcpy(thisclan->slogan,row[6]);
strcpy(thisclan->news,row[7]);
ClanList.push_back( thisclan );
}
DB->QFree( );
// Load Clans
for(UINT i=0;i<ClanList.size( );i++)
{
CClans* Clan = ClanList.at( i );
result = DB->QStore("SELECT id,char_name,clan_rank FROM characters WHERE clanid=%i order by clan_rank",Clan->id);
if(result==NULL) return false;
while(row = mysql_fetch_row(result))
{
CClanMembers* newmember = new CClanMembers;
assert(newmember);
newmember->id = atoi(row[0]);
strcpy(newmember->name,row[1]);
newmember->clan_rank = atoi(row[2]);
Clan->ClanMembers.push_back( newmember );
}
DB->QFree( );
}
Log( MSG_INFO, "Clans Information Loaded" );
return true;
}
// When a a client is disconnected
void CCharServer::OnClientDisconnect( CClientSocket* thisclient )
{
CCharClient* thisclientwc = (CCharClient*)thisclient;
DB->QExecute( "UPDATE accounts SET online=0 WHERE username='%s'", thisclientwc->username );
if(!thisclientwc->logout)
{
// Send logout message to friends
for(UINT i=0;i<thisclientwc->FriendList.size( );i++)
{
CFriendList* Friend = thisclientwc->FriendList.at( i );;
CCharClient* otherclient = GetClientByID( Friend->id );
if(otherclient!=NULL)
{
ChangeMessengerStatus ( thisclientwc, otherclient, 0x08);
}
}
//set logout messga to clan
CClans* thisclan = GetClanByID(thisclientwc->clanid);
if(thisclan==NULL)
return;
for(UINT i=0;i<thisclan->ClanMembers.size( );i++)
{
CClanMembers* ClanMember = thisclan->ClanMembers.at( i );
CCharClient* otherclient = GetClientByID( ClanMember->id );
if(otherclient!=NULL)
ChangeClanStatus (thisclientwc, otherclient, 0xff);
}
}
}
// Deletes an old clientsocket structure
void CCharServer::DeleteClientSocket( CClientSocket* thisclient )
{
if (thisclient->isserver)
Log( MSG_INFO, "Server disconnected" );
else
Log( MSG_INFO, "User disconnected" );
delete (CCharClient*)thisclient;
}
// Load Server configuration
void CCharServer::LoadConfigurations( const char* file )
{
//Database
Config.SQLServer.pcServer = ConfigGetString ( file, "mysql_host", "localhost" );
Config.SQLServer.pcDatabase = ConfigGetString ( file, "mysql_database", "roseon_beta" );
Config.SQLServer.pcUserName = ConfigGetString ( file, "mysql_user", "root" );
Config.SQLServer.pcPassword = ConfigGetString ( file, "mysql_pass", "" );
Config.SQLServer.pcPort = ConfigGetInt ( file, "mysql_port", 3306 );
//Server
Config.ServerID = ConfigGetInt ( file, "serverid", 1 );
Config.ServerType = 1; // Char always = 1
Config.CharIP = ConfigGetString ( file, "serverip", "127.0.0.1" );
Config.CharPort = ConfigGetInt ( file, "serverport", 29100 );
Config.ParentID = ConfigGetInt ( file, "parentid", 0 );
Config.ServerName = ConfigGetString ( file, "servername", "Server" );
Config.CharsPort = ConfigGetInt ( file, "CharsPort", 29110 );
//Char
Config.usethreads = ConfigGetInt ( file, "usethreads", 0 )==0?false:true;
Config.DeleteTime = ConfigGetInt ( file, "deletetime", 36000 );
Config.MinimumAccessLevel = ConfigGetInt ( file, "accesslevel", 100 );
//Password
Config.LoginPass = ConfigGetInt ( file, "loginpass", 123456 );
Config.CharPass = ConfigGetInt ( file, "charpass", 123456 );
Config.WorldPass = ConfigGetInt ( file, "worldpass", 123456 );
}
// Incoming packet
bool CCharServer::OnReceivePacket( CClientSocket* thisclient, CPacket *P )
{
Log(MSG_INFO,"Packet received at OnReceivePacket");
switch( P->Command )
{
case 0x0500: return pakWSReady ( (CCharClient*)thisclient, P );
case 0x0501: return pakLoginConnected ( (CCharClient*)thisclient, P );
case 0x0502: return pakLoginDSClient ( (CCharClient*)thisclient, P );
case 0x0505: return pakWSCharSelect ( (CCharClient*)thisclient, P );
case 0x070b: return pakDoIdentify ( (CCharClient*)thisclient, P );
case 0x0712: return pakGetCharacters ( (CCharClient*)thisclient, P );
case 0x0713: return pakCreateChar ( (CCharClient*)thisclient, P );
case 0x0714: return pakDeleteChar ( (CCharClient*)thisclient, P );
case 0x0715: return pakRequestWorld ( (CCharClient*)thisclient, P );
case 0x0787: return pakClanChat ( (CCharClient*)thisclient, P );
case 0x07e0: return pakClanManager ( (CCharClient*)thisclient, P );
case 0x07e1: return pakMessengerManager ( (CCharClient*)thisclient, P );
case 0x07e2: return pakMessengerChat ( (CCharClient*)thisclient, P );
case 0x07e3: return pakChatrooms ( (CCharClient*)thisclient, P );
case 0x07e5: return pak7e5 ( (CCharClient*)thisclient, P );
case 0x07e6: return pakUploadCM ( (CCharClient*)thisclient, P );
case 0x07e7: return pakDownloadCM ( (CCharClient*)thisclient, P );
case 0x07e8: return pakClanIconTime ( (CCharClient*)thisclient, P );
case 0x079e: return pakUpdateLevel ( (CCharClient*)thisclient, P );
default:
Log( MSG_WARNING, "(SID:%i) Received unknown packet. Command:%04x Size:%04x", thisclient->sock, P->Command, P->Size );
break;
}
return true;
}
bool CCharServer::Ping( )
{
return DB->Ping( );
}