diff --git a/src/engine/server.h b/src/engine/server.h index 2502929e9..86f36194c 100644 --- a/src/engine/server.h +++ b/src/engine/server.h @@ -213,6 +213,7 @@ public: virtual bool IsClientReady(int ClientID) = 0; virtual bool IsClientPlayer(int ClientID) = 0; + virtual CUuid GameUuid() = 0; virtual const char *GameType() = 0; virtual const char *Version() = 0; virtual const char *NetVersion() = 0; diff --git a/src/engine/server/sql_server.cpp b/src/engine/server/sql_server.cpp index 65e1b74d8..17e9f99dc 100644 --- a/src/engine/server/sql_server.cpp +++ b/src/engine/server/sql_server.cpp @@ -173,7 +173,7 @@ void CSqlServer::CreateTables() str_format(aBuf, sizeof(aBuf), "CREATE TABLE IF NOT EXISTS %s_race (Map VARCHAR(128) BINARY NOT NULL, Name VARCHAR(%d) BINARY NOT NULL, Timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP , Time FLOAT DEFAULT 0, Server CHAR(4), cp1 FLOAT DEFAULT 0, cp2 FLOAT DEFAULT 0, cp3 FLOAT DEFAULT 0, cp4 FLOAT DEFAULT 0, cp5 FLOAT DEFAULT 0, cp6 FLOAT DEFAULT 0, cp7 FLOAT DEFAULT 0, cp8 FLOAT DEFAULT 0, cp9 FLOAT DEFAULT 0, cp10 FLOAT DEFAULT 0, cp11 FLOAT DEFAULT 0, cp12 FLOAT DEFAULT 0, cp13 FLOAT DEFAULT 0, cp14 FLOAT DEFAULT 0, cp15 FLOAT DEFAULT 0, cp16 FLOAT DEFAULT 0, cp17 FLOAT DEFAULT 0, cp18 FLOAT DEFAULT 0, cp19 FLOAT DEFAULT 0, cp20 FLOAT DEFAULT 0, cp21 FLOAT DEFAULT 0, cp22 FLOAT DEFAULT 0, cp23 FLOAT DEFAULT 0, cp24 FLOAT DEFAULT 0, cp25 FLOAT DEFAULT 0, GameID VARCHAR(64), KEY (Map, Name)) CHARACTER SET utf8mb4;", m_aPrefix, MAX_NAME_LENGTH); executeSql(aBuf); - str_format(aBuf, sizeof(aBuf), "CREATE TABLE IF NOT EXISTS %s_teamrace (Map VARCHAR(128) BINARY NOT NULL, Name VARCHAR(%d) BINARY NOT NULL, Timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, Time FLOAT DEFAULT 0, ID VARBINARY(16) NOT NULL, KEY Map (Map)) CHARACTER SET utf8mb4;", m_aPrefix, MAX_NAME_LENGTH); + str_format(aBuf, sizeof(aBuf), "CREATE TABLE IF NOT EXISTS %s_teamrace (Map VARCHAR(128) BINARY NOT NULL, Name VARCHAR(%d) BINARY NOT NULL, Timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, Time FLOAT DEFAULT 0, ID VARBINARY(16) NOT NULL, GameID VARCHAR(64), KEY Map (Map)) CHARACTER SET utf8mb4;", m_aPrefix, MAX_NAME_LENGTH); executeSql(aBuf); str_format(aBuf, sizeof(aBuf), "CREATE TABLE IF NOT EXISTS %s_maps (Map VARCHAR(128) BINARY NOT NULL, Server VARCHAR(32) BINARY NOT NULL, Mapper VARCHAR(128) BINARY NOT NULL, Points INT DEFAULT 0, Stars INT DEFAULT 0, Timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP, UNIQUE KEY Map (Map)) CHARACTER SET utf8mb4;", m_aPrefix); diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index bb0a78895..69a43c912 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -3001,6 +3001,7 @@ bool CGameContext::IsClientPlayer(int ClientID) return m_apPlayers[ClientID] && m_apPlayers[ClientID]->GetTeam() == TEAM_SPECTATORS ? false : true; } +CUuid CGameContext::GameUuid() { return m_GameUuid; } const char *CGameContext::GameType() { return m_pController && m_pController->m_pGameType ? m_pController->m_pGameType : ""; } const char *CGameContext::Version() { return GAME_VERSION; } const char *CGameContext::NetVersion() { return GAME_NETVERSION; } diff --git a/src/game/server/gamecontext.h b/src/game/server/gamecontext.h index 27915c82a..5bde00489 100644 --- a/src/game/server/gamecontext.h +++ b/src/game/server/gamecontext.h @@ -68,6 +68,7 @@ class CGameContext : public IGameServer bool m_TeeHistorianActive; CTeeHistorian m_TeeHistorian; ASYNCIO *m_pTeeHistorianFile; + CUuid m_GameUuid; static void CommandCallback(int ClientID, int FlagMask, const char *pCmd, IConsole::IResult *pResult, void *pUser); static void TeeHistorianWrite(const void *pData, int DataSize, void *pUser); @@ -125,7 +126,6 @@ public: IGameController *m_pController; CGameWorld m_World; - CUuid m_GameUuid; // helper functions class CCharacter *GetPlayerChar(int ClientID); @@ -232,6 +232,7 @@ public: virtual bool IsClientReady(int ClientID); virtual bool IsClientPlayer(int ClientID); + virtual CUuid GameUuid(); virtual const char *GameType(); virtual const char *Version(); virtual const char *NetVersion(); diff --git a/src/game/server/score/sql_score.cpp b/src/game/server/score/sql_score.cpp index 7bb2888e0..7ff59c3e5 100644 --- a/src/game/server/score/sql_score.cpp +++ b/src/game/server/score/sql_score.cpp @@ -19,6 +19,7 @@ CGameContext* CSqlData::ms_pGameServer = 0; IServer* CSqlData::ms_pServer = 0; CPlayerData* CSqlData::ms_pPlayerData = 0; const char* CSqlData::ms_pMap = 0; +const char* CSqlData::ms_pGameUuid = 0; bool CSqlData::ms_GameContextAvailable = false; int CSqlData::ms_Instance = 0; @@ -43,11 +44,13 @@ m_pGameServer(pGameServer), m_pServer(pGameServer->Server()) { str_copy(m_aMap, g_Config.m_SvMap, sizeof(m_aMap)); + FormatUuid(m_pGameServer->GameUuid(), m_aGameUuid, sizeof(m_aGameUuid)); CSqlData::ms_pGameServer = m_pGameServer; CSqlData::ms_pServer = m_pServer; CSqlData::ms_pPlayerData = PlayerData(0); CSqlData::ms_pMap = m_aMap; + CSqlData::ms_pGameUuid = m_aGameUuid; CSqlData::ms_GameContextAvailable = true; ++CSqlData::ms_Instance; @@ -488,10 +491,6 @@ bool CSqlScore::SaveScoreThread(CSqlServer* pSqlServer, const CSqlData *pGameDat { const CSqlScoreData *pData = dynamic_cast(pGameData); - char aGameUuid[UUID_MAXSTRSIZE]; - FormatUuid(pData->GameServer()->m_GameUuid, aGameUuid, sizeof(aGameUuid)); - sqlstr::ClearString(aGameUuid, sizeof(aGameUuid)); - if (HandleFailure) { if (!g_Config.m_SvSqlFailureFile[0]) @@ -507,7 +506,7 @@ bool CSqlScore::SaveScoreThread(CSqlServer* pSqlServer, const CSqlData *pGameDat sqlstr::GetTimeStamp(aTimestamp, sizeof(aTimestamp)); char aBuf[768]; - str_format(aBuf, sizeof(aBuf), "INSERT IGNORE INTO %%s_race(Map, Name, Timestamp, Time, Server, cp1, cp2, cp3, cp4, cp5, cp6, cp7, cp8, cp9, cp10, cp11, cp12, cp13, cp14, cp15, cp16, cp17, cp18, cp19, cp20, cp21, cp22, cp23, cp24, cp25, GameID) VALUES ('%s', '%s', '%s', '%.2f', '%s', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%s');", pData->m_Map.ClrStr(), pData->m_Name.ClrStr(), aTimestamp, pData->m_Time, g_Config.m_SvSqlServerName, pData->m_aCpCurrent[0], pData->m_aCpCurrent[1], pData->m_aCpCurrent[2], pData->m_aCpCurrent[3], pData->m_aCpCurrent[4], pData->m_aCpCurrent[5], pData->m_aCpCurrent[6], pData->m_aCpCurrent[7], pData->m_aCpCurrent[8], pData->m_aCpCurrent[9], pData->m_aCpCurrent[10], pData->m_aCpCurrent[11], pData->m_aCpCurrent[12], pData->m_aCpCurrent[13], pData->m_aCpCurrent[14], pData->m_aCpCurrent[15], pData->m_aCpCurrent[16], pData->m_aCpCurrent[17], pData->m_aCpCurrent[18], pData->m_aCpCurrent[19], pData->m_aCpCurrent[20], pData->m_aCpCurrent[21], pData->m_aCpCurrent[22], pData->m_aCpCurrent[23], pData->m_aCpCurrent[24], aGameUuid); + str_format(aBuf, sizeof(aBuf), "INSERT IGNORE INTO %%s_race(Map, Name, Timestamp, Time, Server, cp1, cp2, cp3, cp4, cp5, cp6, cp7, cp8, cp9, cp10, cp11, cp12, cp13, cp14, cp15, cp16, cp17, cp18, cp19, cp20, cp21, cp22, cp23, cp24, cp25, GameID) VALUES ('%s', '%s', '%s', '%.2f', '%s', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%s');", pData->m_Map.ClrStr(), pData->m_Name.ClrStr(), aTimestamp, pData->m_Time, g_Config.m_SvSqlServerName, pData->m_aCpCurrent[0], pData->m_aCpCurrent[1], pData->m_aCpCurrent[2], pData->m_aCpCurrent[3], pData->m_aCpCurrent[4], pData->m_aCpCurrent[5], pData->m_aCpCurrent[6], pData->m_aCpCurrent[7], pData->m_aCpCurrent[8], pData->m_aCpCurrent[9], pData->m_aCpCurrent[10], pData->m_aCpCurrent[11], pData->m_aCpCurrent[12], pData->m_aCpCurrent[13], pData->m_aCpCurrent[14], pData->m_aCpCurrent[15], pData->m_aCpCurrent[16], pData->m_aCpCurrent[17], pData->m_aCpCurrent[18], pData->m_aCpCurrent[19], pData->m_aCpCurrent[20], pData->m_aCpCurrent[21], pData->m_aCpCurrent[22], pData->m_aCpCurrent[23], pData->m_aCpCurrent[24], pData->m_GameUuid.ClrStr()); io_write(File, aBuf, str_length(aBuf)); io_write_newline(File); io_close(File); @@ -552,7 +551,7 @@ bool CSqlScore::SaveScoreThread(CSqlServer* pSqlServer, const CSqlData *pGameDat } // if no entry found... create a new one - str_format(aBuf, sizeof(aBuf), "INSERT IGNORE INTO %s_race(Map, Name, Timestamp, Time, Server, cp1, cp2, cp3, cp4, cp5, cp6, cp7, cp8, cp9, cp10, cp11, cp12, cp13, cp14, cp15, cp16, cp17, cp18, cp19, cp20, cp21, cp22, cp23, cp24, cp25, GameID) VALUES ('%s', '%s', CURRENT_TIMESTAMP(), '%.2f', '%s', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%s');", pSqlServer->GetPrefix(), pData->m_Map.ClrStr(), pData->m_Name.ClrStr(), pData->m_Time, g_Config.m_SvSqlServerName, pData->m_aCpCurrent[0], pData->m_aCpCurrent[1], pData->m_aCpCurrent[2], pData->m_aCpCurrent[3], pData->m_aCpCurrent[4], pData->m_aCpCurrent[5], pData->m_aCpCurrent[6], pData->m_aCpCurrent[7], pData->m_aCpCurrent[8], pData->m_aCpCurrent[9], pData->m_aCpCurrent[10], pData->m_aCpCurrent[11], pData->m_aCpCurrent[12], pData->m_aCpCurrent[13], pData->m_aCpCurrent[14], pData->m_aCpCurrent[15], pData->m_aCpCurrent[16], pData->m_aCpCurrent[17], pData->m_aCpCurrent[18], pData->m_aCpCurrent[19], pData->m_aCpCurrent[20], pData->m_aCpCurrent[21], pData->m_aCpCurrent[22], pData->m_aCpCurrent[23], pData->m_aCpCurrent[24], aGameUuid); + str_format(aBuf, sizeof(aBuf), "INSERT IGNORE INTO %s_race(Map, Name, Timestamp, Time, Server, cp1, cp2, cp3, cp4, cp5, cp6, cp7, cp8, cp9, cp10, cp11, cp12, cp13, cp14, cp15, cp16, cp17, cp18, cp19, cp20, cp21, cp22, cp23, cp24, cp25, GameID) VALUES ('%s', '%s', CURRENT_TIMESTAMP(), '%.2f', '%s', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%s');", pSqlServer->GetPrefix(), pData->m_Map.ClrStr(), pData->m_Name.ClrStr(), pData->m_Time, g_Config.m_SvSqlServerName, pData->m_aCpCurrent[0], pData->m_aCpCurrent[1], pData->m_aCpCurrent[2], pData->m_aCpCurrent[3], pData->m_aCpCurrent[4], pData->m_aCpCurrent[5], pData->m_aCpCurrent[6], pData->m_aCpCurrent[7], pData->m_aCpCurrent[8], pData->m_aCpCurrent[9], pData->m_aCpCurrent[10], pData->m_aCpCurrent[11], pData->m_aCpCurrent[12], pData->m_aCpCurrent[13], pData->m_aCpCurrent[14], pData->m_aCpCurrent[15], pData->m_aCpCurrent[16], pData->m_aCpCurrent[17], pData->m_aCpCurrent[18], pData->m_aCpCurrent[19], pData->m_aCpCurrent[20], pData->m_aCpCurrent[21], pData->m_aCpCurrent[22], pData->m_aCpCurrent[23], pData->m_aCpCurrent[24], pData->m_GameUuid.ClrStr()); dbg_msg("sql", "%s", aBuf); pSqlServer->executeSql(aBuf); @@ -610,7 +609,7 @@ bool CSqlScore::SaveTeamScoreThread(CSqlServer* pSqlServer, const CSqlData *pGam char aBuf[2300]; for(unsigned int i = 0; i < pData->m_Size; i++) { - str_format(aBuf, sizeof(aBuf), "INSERT IGNORE INTO %%s_teamrace(Map, Name, Timestamp, Time, ID) VALUES ('%s', '%s', '%s', '%.2f', @id);", pData->m_Map.ClrStr(), pData->m_aNames[i].ClrStr(), aTimestamp, pData->m_Time); + str_format(aBuf, sizeof(aBuf), "INSERT IGNORE INTO %%s_teamrace(Map, Name, Timestamp, Time, ID) VALUES ('%s', '%s', '%s', '%.2f', @id, '%s');", pData->m_Map.ClrStr(), pData->m_aNames[i].ClrStr(), aTimestamp, pData->m_Time, pData->m_GameUuid.ClrStr()); io_write(File, aBuf, str_length(aBuf)); io_write_newline(File); } @@ -703,7 +702,7 @@ bool CSqlScore::SaveTeamScoreThread(CSqlServer* pSqlServer, const CSqlData *pGam for(unsigned int i = 0; i < pData->m_Size; i++) { // if no entry found... create a new one - str_format(aBuf, sizeof(aBuf), "INSERT IGNORE INTO %s_teamrace(Map, Name, Timestamp, Time, ID) VALUES ('%s', '%s', CURRENT_TIMESTAMP(), '%.2f', @id);", pSqlServer->GetPrefix(), pData->m_Map.ClrStr(), pData->m_aNames[i].ClrStr(), pData->m_Time); + str_format(aBuf, sizeof(aBuf), "INSERT IGNORE INTO %s_teamrace(Map, Name, Timestamp, Time, ID) VALUES ('%s', '%s', CURRENT_TIMESTAMP(), '%.2f', @id, '%s');", pSqlServer->GetPrefix(), pData->m_Map.ClrStr(), pData->m_aNames[i].ClrStr(), pData->m_Time, pData->m_GameUuid.ClrStr()); dbg_msg("sql", "%s", aBuf); pSqlServer->executeSql(aBuf); } diff --git a/src/game/server/score/sql_score.h b/src/game/server/score/sql_score.h index 3dfc3709f..06ce554ad 100644 --- a/src/game/server/score/sql_score.h +++ b/src/game/server/score/sql_score.h @@ -24,7 +24,7 @@ public: // generic implementation to provide gameserver and server struct CSqlData { - CSqlData() : m_Map(ms_pMap) + CSqlData() : m_Map(ms_pMap), m_GameUuid(ms_pGameUuid) { m_Instance = ms_Instance; } @@ -41,6 +41,7 @@ struct CSqlData CPlayerData* PlayerData(int ID) const { return isGameContextVaild() ? &ms_pPlayerData[ID] : throw CGameContextError("[CSqlData]: PlayerData() unavailable."); } sqlstr::CSqlString<128> m_Map; + sqlstr::CSqlString m_GameUuid; // counter to keep track to which instance of GameServer this object belongs to. int m_Instance; @@ -49,6 +50,7 @@ struct CSqlData static IServer *ms_pServer; static CPlayerData *ms_pPlayerData; static const char *ms_pMap; + static const char *ms_pGameUuid; static bool ms_GameContextAvailable; // contains the instancecount of the current GameServer @@ -144,6 +146,7 @@ class CSqlScore: public IScore static bool Init(CSqlServer* pSqlServer, const CSqlData *pGameData, bool HandleFailure); char m_aMap[64]; + char m_aGameUuid[UUID_MAXSTRSIZE]; static LOCK ms_FailureFileLock;