diff options
| author | savander <savander.pl@gmail.com> | 2014-09-27 00:34:35 +0200 |
|---|---|---|
| committer | savander <savander.pl@gmail.com> | 2014-09-27 00:34:35 +0200 |
| commit | 2a54f759145f86fce4ad2a333de6d9cd911d8861 (patch) | |
| tree | 8509c538c26ddae9c493fbaed33a8380508d7caf | |
| parent | 8c329ade7507d3f1641018f302bf2396af6a471a (diff) | |
| download | zcatch-2a54f759145f86fce4ad2a333de6d9cd911d8861.tar.gz zcatch-2a54f759145f86fce4ad2a333de6d9cd911d8861.zip | |
zCatch:Ranking
| -rw-r--r-- | src/engine/shared/config_variables.h | 10 | ||||
| -rw-r--r-- | src/game/server/entities/ranking.cpp | 273 | ||||
| -rw-r--r-- | src/game/server/gamecontext.cpp | 3 | ||||
| -rw-r--r-- | src/game/server/gamecontext.h | 8 | ||||
| -rw-r--r-- | src/game/server/gamemodes/zcatch.cpp | 20 | ||||
| -rw-r--r-- | src/game/server/gamemodes/zcatch.h | 3 | ||||
| -rw-r--r-- | src/game/server/player.h | 1 | ||||
| -rw-r--r-- | src/game/server/ranking.cpp | 271 | ||||
| -rw-r--r-- | src/game/server/ranking.h | 70 |
9 files changed, 656 insertions, 3 deletions
diff --git a/src/engine/shared/config_variables.h b/src/engine/shared/config_variables.h index 0d3b197c..b766b6c9 100644 --- a/src/engine/shared/config_variables.h +++ b/src/engine/shared/config_variables.h @@ -105,6 +105,16 @@ MACRO_CONFIG_INT(EcOutputLevel, ec_output_level, 1, 0, 2, CFGFLAG_ECON, "Adjusts MACRO_CONFIG_INT(SvGlobalBantime, sv_global_bantime, 60, 0, 1440, CFGFLAG_SERVER, "The time a client gets banned if the ban server reports it. 0 to disable") + +#if defined(CONF_SQL) +//zCatch mysql. +MACRO_CONFIG_STR(SvSqlUser, sv_sql_user, 32, "nameless", CFGFLAG_SERVER, "SQL User") +MACRO_CONFIG_STR(SvSqlPass, sv_sql_pass, 32, "tee", CFGFLAG_SERVER, "SQL Password") +MACRO_CONFIG_STR(SvSqlIp, sv_sql_ip, 32, "127.0.0.1", CFGFLAG_SERVER, "SQL Database IP") +MACRO_CONFIG_INT(SvSqlPort, sv_sql_port, 3306, 0, 65535, CFGFLAG_SERVER, "SQL Database port") +MACRO_CONFIG_STR(SvSqlDatabase, sv_sql_database, 16, "teeworlds", CFGFLAG_SERVER, "SQL Database name") +#endif + MACRO_CONFIG_INT(Debug, debug, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SERVER, "Debug mode") MACRO_CONFIG_INT(DbgStress, dbg_stress, 0, 0, 0, CFGFLAG_CLIENT|CFGFLAG_SERVER, "Stress systems") MACRO_CONFIG_INT(DbgStressNetwork, dbg_stress_network, 0, 0, 0, CFGFLAG_CLIENT|CFGFLAG_SERVER, "Stress network") diff --git a/src/game/server/entities/ranking.cpp b/src/game/server/entities/ranking.cpp new file mode 100644 index 00000000..910157b8 --- /dev/null +++ b/src/game/server/entities/ranking.cpp @@ -0,0 +1,273 @@ +#if defined(CONF_SQL) +#include <string.h> +#include <algorithm> + +#include "ranking.h" +#include <engine/shared/config.h> + +static LOCK gs_SqlLock = 0; + +CRanking::CRanking(CGameContext *pGameServer) : m_pGameServer(pGameServer), + m_pServer(pGameServer->Server()), + m_pDatabase(g_Config.m_SvSqlDatabase), + m_pUser(g_Config.m_SvSqlUser), + m_pPass(g_Config.m_SvSqlPass), + m_pIp(g_Config.m_SvSqlIp), + m_Port(g_Config.m_SvSqlPort) +{ + m_pDriver = NULL; + + if(gs_SqlLock == 0) + gs_SqlLock = lock_create(); + + Init(); +} + +CRanking::~CRanking() +{ + lock_wait(gs_SqlLock); + lock_release(gs_SqlLock); + + try + { + delete m_pStatement; + delete m_pConnection; + dbg_msg("SQL", "SQL connection disconnected"); + } + catch (sql::SQLException &e) + { + dbg_msg("SQL", "ERROR: No SQL connection"); + } +} +void CRanking::Init() +{ + // create connection + if(Connect()) + { + try + { + // create tables + char aBuf[1024]; + + str_format(aBuf, sizeof(aBuf), "CREATE TABLE IF NOT EXISTS zcatch_ranks (Name VARCHAR(%d) BINARY NOT NULL, Wins INT DEFAULT 0, UNIQUE KEY Name (Name)) CHARACTER SET utf8 ;", MAX_NAME_LENGTH); + m_pStatement->execute(aBuf); + + dbg_msg("SQL", "Ranking table were created successfully"); + // delete statement + delete m_pResults; + } + catch (sql::SQLException &e) + { + char aBuf[256]; + str_format(aBuf, sizeof(aBuf), "MySQL Error: %s", e.what()); + dbg_msg("SQL", aBuf); + dbg_msg("SQL", "ERROR: Tables were NOT created"); + } + + // disconnect from database + Disconnect(); + } +} + +bool CRanking::Connect() +{ + if (m_pDriver != NULL && m_pConnection != NULL) + { + try + { + // Connect to specific database + m_pConnection->setSchema(m_pDatabase); + } + catch (sql::SQLException &e) + { + char aBuf[256]; + str_format(aBuf, sizeof(aBuf), "MySQL Error: %s", e.what()); + dbg_msg("SQL", aBuf); + + dbg_msg("SQL", "ERROR: SQL connection failed"); + return false; + } + return true; + } + + try + { + char aBuf[256]; + + sql::ConnectOptionsMap connection_properties; + connection_properties["hostName"] = sql::SQLString(m_pIp); + connection_properties["port"] = m_Port; + connection_properties["userName"] = sql::SQLString(m_pUser); + connection_properties["password"] = sql::SQLString(m_pPass); + connection_properties["OPT_RECONNECT"] = true; + + // Create connection + m_pDriver = get_driver_instance(); + m_pConnection = m_pDriver->connect(connection_properties); + + // Create Statement + m_pStatement = m_pConnection->createStatement(); + + // Create database if not exists + str_format(aBuf, sizeof(aBuf), "CREATE DATABASE IF NOT EXISTS %s", m_pDatabase); + m_pStatement->execute(aBuf); + + // Connect to specific database + m_pConnection->setSchema(m_pDatabase); + dbg_msg("SQL", "SQL connection established"); + return true; + } + catch (sql::SQLException &e) + { + char aBuf[256]; + str_format(aBuf, sizeof(aBuf), "MySQL Error: %s", e.what()); + dbg_msg("SQL", aBuf); + + dbg_msg("SQL", "ERROR: SQL connection failed"); + return false; + } + catch (const std::exception& ex) + { + // ... + dbg_msg("SQL", "1 %s",ex.what()); + + } + catch (const std::string& ex) + { + // ... + dbg_msg("SQL", "2 %s",ex.c_str()); + } + catch( int ) + { + dbg_msg("SQL", "3 %s"); + } + catch( float ) + { + dbg_msg("SQL", "4 %s"); + } + + catch( char[] ) + { + dbg_msg("SQL", "5 %s"); + } + + catch( char ) + { + dbg_msg("SQL", "6 %s"); + } + catch (...) + { + dbg_msg("SQL", "Unknown Error cause by the MySQL/C++ Connector, my advice compile server_debug and use it"); + + dbg_msg("SQL", "ERROR: SQL connection failed"); + return false; + } + return false; +} +void CRanking::Disconnect() +{ +} + +void CRanking::SaveRanking(int ClientID){ + + CSqlRankData *Tmp = new CSqlRankData(); + Tmp->m_ClientID = ClientID; + str_copy(Tmp->m_aName, Server()->ClientName(ClientID), MAX_NAME_LENGTH); + Tmp->m_pSqlData = this; + + void *SaveRanking = thread_create(SaveRankingThread, Tmp); +#if defined(CONF_FAMILY_UNIX) + pthread_detach((pthread_t)SaveRanking); +#endif +} +void CRanking::SaveRankingThread(void *pUser){ + + lock_wait(gs_SqlLock); + CSqlRankData *pData = (CSqlRankData *)pUser; + + // Connect to database + if(pData->m_pSqlData->Connect()) + { + try + { + char aBuf[768]; + + // check strings + pData->m_pSqlData->ClearString(pData->m_aName); + + str_format(aBuf, sizeof(aBuf), "SELECT * FROM zcatch_ranks WHERE Name='%s' ORDER BY Wins ASC LIMIT 1;", pData->m_aName); + pData->m_pSqlData->m_pResults = pData->m_pSqlData->m_pStatement->executeQuery(aBuf); + + if(pData->m_pSqlData->m_pResults->next()) + { + str_format(aBuf, sizeof(aBuf), "SELECT Wins FROM zctach_ranks WHERE Name ='%s'",pData->m_aName); + pData->m_pSqlData->m_pResults = pData->m_pSqlData->m_pStatement->executeQuery(aBuf); + + if(pData->m_pSqlData->m_pResults->rowsCount() == 1){ + pData->m_pSqlData->m_pResults->next(); + + pData->m_pSqlData->GameServer()->SendChatTarget(pData->m_ClientID, aBuf); + str_format(aBuf, sizeof(aBuf), "INSERT INTO zcatch_ranks(Name, Wins) VALUES ('%s') ON duplicate key UPDATE Name=VALUES(Name), Wins=Wins+1;", pData->m_aName); + pData->m_pSqlData->m_pStatement->execute(aBuf); + } + } + + pData->m_pSqlData->GameServer()->SendChatTarget(pData->m_ClientID, aBuf); + delete pData->m_pSqlData->m_pResults; + + // if no entry found... create a new one + str_format(aBuf, sizeof(aBuf), "INSERT IGNORE INTO %s_race(Name, Wins2 VALUES ('%s', '1');",pData->m_aName); + pData->m_pSqlData->m_pStatement->execute(aBuf); + + dbg_msg("SQL", "Updating rank done"); + } + catch (sql::SQLException &e) + { + char aBuf[256]; + str_format(aBuf, sizeof(aBuf), "MySQL Error: %s", e.what()); + dbg_msg("SQL", aBuf); + dbg_msg("SQL", "ERROR: Could not update rank"); + } + pData->m_pSqlData->Disconnect(); + } + + delete pData; + lock_release(gs_SqlLock); +} + + +// anti SQL injection +void CRanking::ClearString(char *pString, int size) +{ + char newString[size*2-1]; + int pos = 0; + + for(int i=0;i<size;i++) + { + if(pString[i] == '\\') + { + newString[pos++] = '\\'; + newString[pos++] = '\\'; + } + else if(pString[i] == '\'') + { + newString[pos++] = '\\'; + newString[pos++] = '\''; + } + else if(pString[i] == '"') + { + newString[pos++] = '\\'; + newString[pos++] = '"'; + } + else + { + newString[pos++] = pString[i]; + } + } + + newString[pos] = '\0'; + + strcpy(pString,newString); +} +#endif + diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index 27d17c11..0b618d2d 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -2065,6 +2065,9 @@ void CGameContext::OnInit(/*class IKernel *pKernel*/) m_pController = new CGameControllerDM(this);*/ m_pController = new CGameController_zCatch(this); +#if defined(CONF_SQL) + m_Ranking = new CRanking(this); +#endif // setup core world //for(int i = 0; i < MAX_CLIENTS; i++) // game.players[i].core.world = &game.world.core; diff --git a/src/game/server/gamecontext.h b/src/game/server/gamecontext.h index 71f6308a..41d6d899 100644 --- a/src/game/server/gamecontext.h +++ b/src/game/server/gamecontext.h @@ -10,13 +10,16 @@ #include <game/layers.h> #include <game/voting.h> + #include "eventhandler.h" #include "gamecontroller.h" #include "gameworld.h" +#include "ranking.h" #include "player.h" + #define MAX_MUTES 35 -#define ZCATCH_VERSION "0.4.8 BETA" +#define ZCATCH_VERSION "0.4.9 BETA" /* Tick @@ -48,6 +51,7 @@ class CGameContext : public IGameServer CNetObjHandler m_NetObjHandler; CTuningParams m_Tuning; + static void ConTuneParam(IConsole::IResult *pResult, void *pUserData); static void ConTuneReset(IConsole::IResult *pResult, void *pUserData); static void ConTuneDump(IConsole::IResult *pResult, void *pUserData); @@ -95,6 +99,8 @@ public: CEventHandler m_Events; CPlayer *m_apPlayers[MAX_CLIENTS]; + class CRanking *m_Ranking; + IGameController *m_pController; CGameWorld m_World; diff --git a/src/game/server/gamemodes/zcatch.cpp b/src/game/server/gamemodes/zcatch.cpp index cd36d12f..6034d78a 100644 --- a/src/game/server/gamemodes/zcatch.cpp +++ b/src/game/server/gamemodes/zcatch.cpp @@ -248,6 +248,21 @@ void CGameController_zCatch::OnCharacterSpawn(class CCharacter *pChr) void CGameController_zCatch::EndRound() { + + //CheckWinner + int m_WinnerClientID = 0; + for(int i = 0; i < MAX_CLIENTS; i++) + { + if(GameServer()->m_apPlayers[i]) + { + if(GameServer()->m_apPlayers[i]->m_zCatchNumVictims) + m_WinnerClientID = GameServer()->m_apPlayers[i]->GetCID(); + } + } + +#if defined(CONF_SQL) + m_Ranking->SaveRanking(m_WinnerClientID); +#endif for(int i = 0; i < MAX_CLIENTS; i++) { if(GameServer()->m_apPlayers[i]) @@ -258,9 +273,13 @@ void CGameController_zCatch::EndRound() GameServer()->m_apPlayers[i]->SetTeamDirect(GameServer()->m_pController->ClampTeam(1)); char aBuf[128]; + str_format(aBuf, sizeof(aBuf), "Winner -- %s", Server()->ClientName(m_WinnerClientID)); + GameServer()->SendChatTarget(i, aBuf); str_format(aBuf, sizeof(aBuf), "Kills: %d | Deaths: %d", GameServer()->m_apPlayers[i]->m_Kills, GameServer()->m_apPlayers[i]->m_Deaths); GameServer()->SendChatTarget(i, aBuf); + + if(GameServer()->m_apPlayers[i]->m_TicksSpec != 0 || GameServer()->m_apPlayers[i]->m_TicksIngame != 0) { double TimeInSpec = (GameServer()->m_apPlayers[i]->m_TicksSpec * 100.0) / (GameServer()->m_apPlayers[i]->m_TicksIngame + GameServer()->m_apPlayers[i]->m_TicksSpec); @@ -280,6 +299,7 @@ void CGameController_zCatch::EndRound() GameServer()->m_World.m_Paused = true; m_GameOverTick = Server()->Tick(); m_SuddenDeath = 0; + } bool CGameController_zCatch::CanChangeTeam(CPlayer *pPlayer, int JoinTeam) diff --git a/src/game/server/gamemodes/zcatch.h b/src/game/server/gamemodes/zcatch.h index 4f110a03..9602c75c 100644 --- a/src/game/server/gamemodes/zcatch.h +++ b/src/game/server/gamemodes/zcatch.h @@ -6,11 +6,12 @@ #define GAME_SERVER_GAMEMODES_ZCATCH_H #include <game/server/gamecontroller.h> +#include "../ranking.h" class CGameController_zCatch: public IGameController { int m_OldMode; - + CRanking *m_Ranking; public: CGameController_zCatch(class CGameContext *pGameServer); virtual void Tick(); diff --git a/src/game/server/player.h b/src/game/server/player.h index 7189d7e2..416dccd7 100644 --- a/src/game/server/player.h +++ b/src/game/server/player.h @@ -6,7 +6,6 @@ // this include should perhaps be removed #include "entities/character.h" #include "gamecontext.h" - // player object class CPlayer { diff --git a/src/game/server/ranking.cpp b/src/game/server/ranking.cpp new file mode 100644 index 00000000..1e990e34 --- /dev/null +++ b/src/game/server/ranking.cpp @@ -0,0 +1,271 @@ +#if defined(CONF_SQL) +#include <string.h> +#include <algorithm> + +#include "ranking.h" +#include <engine/shared/config.h> + +static LOCK gs_SqlLock = 0; + +CRanking::CRanking(CGameContext *pGameServer) : m_pGameServer(pGameServer), + m_pServer(pGameServer->Server()), + m_pDatabase(g_Config.m_SvSqlDatabase), + m_pUser(g_Config.m_SvSqlUser), + m_pPass(g_Config.m_SvSqlPass), + m_pIp(g_Config.m_SvSqlIp), + m_Port(g_Config.m_SvSqlPort) +{ + m_pDriver = NULL; + + if(gs_SqlLock == 0) + gs_SqlLock = lock_create(); + + Init(); +} + +CRanking::~CRanking() +{ + lock_wait(gs_SqlLock); + lock_release(gs_SqlLock); + + try + { + delete m_pStatement; + delete m_pConnection; + dbg_msg("SQL", "SQL connection disconnected"); + } + catch (sql::SQLException &e) + { + dbg_msg("SQL", "ERROR: No SQL connection"); + } +} +void CRanking::Init() +{ + // create connection + if(Connect()) + { + try + { + // create tables + char aBuf[1024]; + + str_format(aBuf, sizeof(aBuf), "CREATE TABLE IF NOT EXISTS zcatch_ranks (Name VARCHAR(%d) BINARY NOT NULL, Wins INT DEFAULT 0, UNIQUE KEY Name (Name)) CHARACTER SET utf8 ;", MAX_NAME_LENGTH); + m_pStatement->execute(aBuf); + + dbg_msg("SQL", "Ranking table were created successfully"); + } + catch (sql::SQLException &e) + { + char aBuf[256]; + str_format(aBuf, sizeof(aBuf), "MySQL Error: %s", e.what()); + dbg_msg("SQL", aBuf); + dbg_msg("SQL", "ERROR: Tables were NOT created"); + } + + // disconnect from database + Disconnect(); + } +} + +bool CRanking::Connect() +{ + if (m_pDriver != NULL && m_pConnection != NULL) + { + try + { + // Connect to specific database + m_pConnection->setSchema(m_pDatabase); + } + catch (sql::SQLException &e) + { + char aBuf[256]; + str_format(aBuf, sizeof(aBuf), "MySQL Error: %s", e.what()); + dbg_msg("SQL", aBuf); + + dbg_msg("SQL", "ERROR: SQL connection failed"); + return false; + } + return true; + } + + try + { + char aBuf[256]; + + sql::ConnectOptionsMap connection_properties; + connection_properties["hostName"] = sql::SQLString(m_pIp); + connection_properties["port"] = m_Port; + connection_properties["userName"] = sql::SQLString(m_pUser); + connection_properties["password"] = sql::SQLString(m_pPass); + connection_properties["OPT_RECONNECT"] = true; + + // Create connection + m_pDriver = get_driver_instance(); + m_pConnection = m_pDriver->connect(connection_properties); + + // Create Statement + m_pStatement = m_pConnection->createStatement(); + + // Create database if not exists + str_format(aBuf, sizeof(aBuf), "CREATE DATABASE IF NOT EXISTS %s", m_pDatabase); + m_pStatement->execute(aBuf); + + // Connect to specific database + m_pConnection->setSchema(m_pDatabase); + dbg_msg("SQL", "SQL connection established"); + return true; + } + catch (sql::SQLException &e) + { + char aBuf[256]; + str_format(aBuf, sizeof(aBuf), "MySQL Error: %s", e.what()); + dbg_msg("SQL", aBuf); + + dbg_msg("SQL", "ERROR: SQL connection failed"); + return false; + } + catch (const std::exception& ex) + { + // ... + dbg_msg("SQL", "1 %s",ex.what()); + + } + catch (const std::string& ex) + { + // ... + dbg_msg("SQL", "2 %s",ex.c_str()); + } + catch( int ) + { + dbg_msg("SQL", "3 %s"); + } + catch( float ) + { + dbg_msg("SQL", "4 %s"); + } + + catch( char[] ) + { + dbg_msg("SQL", "5 %s"); + } + + catch( char ) + { + dbg_msg("SQL", "6 %s"); + } + catch (...) + { + dbg_msg("SQL", "Unknown Error cause by the MySQL/C++ Connector, my advice compile server_debug and use it"); + + dbg_msg("SQL", "ERROR: SQL connection failed"); + return false; + } + return false; +} +void CRanking::Disconnect() +{ +} + +void CRanking::SaveRanking(int ClientID){ + + CSqlRankData *Tmp = new CSqlRankData(); + Tmp->m_ClientID = ClientID; + str_copy(Tmp->m_aName, Server()->ClientName(ClientID), MAX_NAME_LENGTH); + Tmp->m_pSqlData = this; + + void *SaveRanking = thread_create(SaveRankingThread, Tmp); +#if defined(CONF_FAMILY_UNIX) + pthread_detach((pthread_t)SaveRanking); +#endif +} +void CRanking::SaveRankingThread(void *pUser){ + + lock_wait(gs_SqlLock); + CSqlRankData *pData = (CSqlRankData *)pUser; + + // Connect to database + if(pData->m_pSqlData->Connect()) + { + try + { + char aBuf[768]; + + // check strings + pData->m_pSqlData->ClearString(pData->m_aName); + + str_format(aBuf, sizeof(aBuf), "SELECT * FROM zcatch_ranks WHERE Name='%s' ORDER BY Wins ASC LIMIT 1;", pData->m_aName); + pData->m_pSqlData->m_pResults = pData->m_pSqlData->m_pStatement->executeQuery(aBuf); + + if(pData->m_pSqlData->m_pResults->next()) + { + str_format(aBuf, sizeof(aBuf), "SELECT Wins FROM zctach_ranks WHERE Name ='%s'",pData->m_aName); + pData->m_pSqlData->m_pResults = pData->m_pSqlData->m_pStatement->executeQuery(aBuf); + + if(pData->m_pSqlData->m_pResults->rowsCount() == 1){ + pData->m_pSqlData->m_pResults->next(); + + pData->m_pSqlData->GameServer()->SendChatTarget(pData->m_ClientID, aBuf); + str_format(aBuf, sizeof(aBuf), "INSERT INTO zcatch_ranks(Name, Wins) VALUES ('%s') ON duplicate key UPDATE Name=VALUES(Name), Wins=Wins+1;", pData->m_aName); + pData->m_pSqlData->m_pStatement->execute(aBuf); + } + } + + pData->m_pSqlData->GameServer()->SendChatTarget(pData->m_ClientID, aBuf); + delete pData->m_pSqlData->m_pResults; + + // if no entry found... create a new one + str_format(aBuf, sizeof(aBuf), "INSERT IGNORE INTO %s_race(Name, Wins2 VALUES ('%s', '1');",pData->m_aName); + pData->m_pSqlData->m_pStatement->execute(aBuf); + + dbg_msg("SQL", "Updating rank done"); + } + catch (sql::SQLException &e) + { + char aBuf[256]; + str_format(aBuf, sizeof(aBuf), "MySQL Error: %s", e.what()); + dbg_msg("SQL", aBuf); + dbg_msg("SQL", "ERROR: Could not update rank"); + } + pData->m_pSqlData->Disconnect(); + } + + delete pData; + lock_release(gs_SqlLock); +} + + +// anti SQL injection +void CRanking::ClearString(char *pString, int size) +{ + char newString[size*2-1]; + int pos = 0; + + for(int i=0;i<size;i++) + { + if(pString[i] == '\\') + { + newString[pos++] = '\\'; + newString[pos++] = '\\'; + } + else if(pString[i] == '\'') + { + newString[pos++] = '\\'; + newString[pos++] = '\''; + } + else if(pString[i] == '"') + { + newString[pos++] = '\\'; + newString[pos++] = '"'; + } + else + { + newString[pos++] = pString[i]; + } + } + + newString[pos] = '\0'; + + strcpy(pString,newString); +} +#endif + diff --git a/src/game/server/ranking.h b/src/game/server/ranking.h new file mode 100644 index 00000000..6c4d1495 --- /dev/null +++ b/src/game/server/ranking.h @@ -0,0 +1,70 @@ +#ifndef GAME_SERVER_RANKING_H +#define GAME_SERVER_RANKING_H + +#include "gamecontext.h" + +#include <mysql_connection.h> + +#include <cppconn/driver.h> +#include <cppconn/exception.h> +#include <cppconn/statement.h> + + +class CRanking +{ + CGameContext *m_pGameServer; + IServer *m_pServer; + + + sql::Driver *m_pDriver; + sql::Connection *m_pConnection; + sql::Statement *m_pStatement; + sql::ResultSet *m_pResults; + + // copy of config vars + const char* m_pDatabase; + const char* m_pUser; + const char* m_pPass; + const char* m_pIp; + int m_Port; + + CGameContext *GameServer() + { + return m_pGameServer; + } + IServer *Server() + { + return m_pServer; + } + + static void SaveRankingThread(void *pUser); + + void Init(); + + bool Connect(); + void Disconnect(); + // anti SQL injection + void ClearString(char *pString, int size = 32); + + + +public: + + CRanking(CGameContext *pGameServer); + ~CRanking(); + + void SaveRanking(int ClientID); +}; + +struct CSqlRankData +{ + CRanking *m_pSqlData; + int m_ClientID; +#if defined(CONF_FAMILY_WINDOWS) + char m_aName[16]; // Don't edit this, or all your teeth will fall http://bugs.mysql.com/bug.php?id=50046 +#else + char m_aName[MAX_NAME_LENGTH * 2 - 1]; +#endif +}; + +#endif |