Add /map (for votes) and /mapinfo (instead of /mappoints)

This commit is contained in:
def 2014-02-19 21:22:36 +01:00
parent 434b2bec52
commit a5f3de6827
9 changed files with 159 additions and 19 deletions

View file

@ -504,6 +504,37 @@ void CGameContext::ConDND(IConsole::IResult *pResult, void *pUserData)
} }
} }
void CGameContext::ConMap(IConsole::IResult *pResult, void *pUserData)
{
CGameContext *pSelf = (CGameContext *) pUserData;
if (!CheckClientID(pResult->m_ClientID))
return;
if (pResult->NumArguments() <= 0)
{
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "map", "Example: /map adr3 to call vote for Adrenaline 3");
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "map", "This means that the map name must start with 'a' and contain the characters 'd', 'r' and '3' in that order");
return;
}
#if defined(CONF_SQL)
if(pSelf->m_apPlayers[pResult->m_ClientID] && g_Config.m_SvUseSQL)
if(pSelf->m_apPlayers[pResult->m_ClientID]->m_LastSQLQuery + pSelf->Server()->TickSpeed() >= pSelf->Server()->Tick())
return;
#endif
CPlayer *pPlayer = pSelf->m_apPlayers[pResult->m_ClientID];
if (!pPlayer)
return;
pSelf->Score()->MapVote(pResult->m_ClientID, pResult->GetString(0));
#if defined(CONF_SQL)
if(pSelf->m_apPlayers[pResult->m_ClientID] && g_Config.m_SvUseSQL)
pSelf->m_apPlayers[pResult->m_ClientID]->m_LastSQLQuery = pSelf->Server()->Tick();
#endif
}
void CGameContext::ConMapPoints(IConsole::IResult *pResult, void *pUserData) void CGameContext::ConMapPoints(IConsole::IResult *pResult, void *pUserData)
{ {
CGameContext *pSelf = (CGameContext *) pUserData; CGameContext *pSelf = (CGameContext *) pUserData;

View file

@ -20,7 +20,8 @@ CHAT_COMMAND("converse", "r", CFGFLAG_CHAT|CFGFLAG_SERVER, ConConverse, this, "C
CHAT_COMMAND("pause", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConTogglePause, this, "Toggles pause (if not activated on the server, it toggles spec)") CHAT_COMMAND("pause", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConTogglePause, this, "Toggles pause (if not activated on the server, it toggles spec)")
CHAT_COMMAND("spec", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConToggleSpec, this, "Toggles spec") CHAT_COMMAND("spec", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConToggleSpec, this, "Toggles spec")
CHAT_COMMAND("dnd", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConDND, this, "Toggle Do Not Disturb (no chat and server messages)") CHAT_COMMAND("dnd", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConDND, this, "Toggle Do Not Disturb (no chat and server messages)")
CHAT_COMMAND("mappoints", "?r", CFGFLAG_CHAT|CFGFLAG_SERVER, ConMapPoints, this, "Show how man points the map with name r gives (current map by default)") CHAT_COMMAND("mapinfo", "?r", CFGFLAG_CHAT|CFGFLAG_SERVER, ConMapPoints, this, "Show info about the map with name r gives (current map by default)")
CHAT_COMMAND("map", "?r", CFGFLAG_CHAT|CFGFLAG_SERVER, ConMap, this, "Vote a map by name")
CHAT_COMMAND("rankteam", "?r", CFGFLAG_CHAT|CFGFLAG_SERVER, ConTeamRank, this, "Shows the team rank of player with name r (your team rank by default)") CHAT_COMMAND("rankteam", "?r", CFGFLAG_CHAT|CFGFLAG_SERVER, ConTeamRank, this, "Shows the team rank of player with name r (your team rank by default)")
CHAT_COMMAND("rank", "?r", CFGFLAG_CHAT|CFGFLAG_SERVER, ConRank, this, "Shows the rank of player with name r (your rank by default)") CHAT_COMMAND("rank", "?r", CFGFLAG_CHAT|CFGFLAG_SERVER, ConRank, this, "Shows the rank of player with name r (your rank by default)")
CHAT_COMMAND("rules", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConRules, this, "Shows the server rules") CHAT_COMMAND("rules", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConRules, this, "Shows the server rules")

View file

@ -245,6 +245,22 @@ void CGameContext::CreateSoundGlobal(int Sound, int Target)
} }
} }
void CGameContext::CallVote(int ClientID, const char *aDesc, const char *aCmd, const char *pReason, const char *aChatmsg)
{
// check if a vote is already running
if(m_VoteCloseTime)
return;
int64 Now = Server()->Tick();
CPlayer *pPlayer = m_apPlayers[ClientID];
SendChat(-1, CGameContext::CHAT_ALL, aChatmsg);
StartVote(aDesc, aCmd, pReason);
pPlayer->m_Vote = 1;
pPlayer->m_VotePos = m_VotePos = 1;
m_VoteCreator = ClientID;
pPlayer->m_LastVoteCall = Now;
}
void CGameContext::SendChatTarget(int To, const char *pText) void CGameContext::SendChatTarget(int To, const char *pText)
{ {
CNetMsg_Sv_Chat Msg; CNetMsg_Sv_Chat Msg;
@ -354,10 +370,6 @@ void CGameContext::SendBroadcast(const char *pText, int ClientID)
// //
void CGameContext::StartVote(const char *pDesc, const char *pCommand, const char *pReason) void CGameContext::StartVote(const char *pDesc, const char *pCommand, const char *pReason)
{ {
// check if a vote is already running
if(m_VoteCloseTime)
return;
// reset votes // reset votes
m_VoteEnforce = VOTE_ENFORCE_UNKNOWN; m_VoteEnforce = VOTE_ENFORCE_UNKNOWN;
m_VoteEnforcer = -1; m_VoteEnforcer = -1;
@ -1135,14 +1147,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID)
} }
if(aCmd[0] && str_comp(aCmd,"info")) if(aCmd[0] && str_comp(aCmd,"info"))
{ CallVote(ClientID, aDesc, aCmd, pReason, aChatmsg);
SendChat(-1, CGameContext::CHAT_ALL, aChatmsg);
StartVote(aDesc, aCmd, pReason);
pPlayer->m_Vote = 1;
pPlayer->m_VotePos = m_VotePos = 1;
m_VoteCreator = ClientID;
pPlayer->m_LastVoteCall = Now;
}
} }
else if(MsgID == NETMSGTYPE_CL_VOTE) else if(MsgID == NETMSGTYPE_CL_VOTE)
{ {

View file

@ -148,6 +148,7 @@ public:
}; };
// network // network
void CallVote(int ClientID, const char *aDesc, const char *aCmd, const char *pReason, const char *aChatmsg);
void SendChatTarget(int To, const char *pText); void SendChatTarget(int To, const char *pText);
void SendChat(int ClientID, int Team, const char *pText, int SpamProtectionClientID = -1); void SendChat(int ClientID, int Team, const char *pText, int SpamProtectionClientID = -1);
void SendEmoticon(int ClientID, int Emoticon); void SendEmoticon(int ClientID, int Emoticon);
@ -251,6 +252,7 @@ private:
static void ConUTF8(IConsole::IResult *pResult, void *pUserData); static void ConUTF8(IConsole::IResult *pResult, void *pUserData);
static void ConDND(IConsole::IResult *pResult, void *pUserData); static void ConDND(IConsole::IResult *pResult, void *pUserData);
static void ConMapPoints(IConsole::IResult *pResult, void *pUserData); static void ConMapPoints(IConsole::IResult *pResult, void *pUserData);
static void ConMap(IConsole::IResult *pResult, void *pUserData);
static void ConTeamRank(IConsole::IResult *pResult, void *pUserData); static void ConTeamRank(IConsole::IResult *pResult, void *pUserData);
static void ConRank(IConsole::IResult *pResult, void *pUserData); static void ConRank(IConsole::IResult *pResult, void *pUserData);
static void ConBroadTime(IConsole::IResult *pResult, void *pUserData); static void ConBroadTime(IConsole::IResult *pResult, void *pUserData);

View file

@ -44,6 +44,7 @@ public:
CPlayerData *PlayerData(int ID) { return &m_aPlayerData[ID]; } CPlayerData *PlayerData(int ID) { return &m_aPlayerData[ID]; }
virtual void MapPoints(int ClientID, const char* MapName) = 0; virtual void MapPoints(int ClientID, const char* MapName) = 0;
virtual void MapVote(int ClientID, const char* MapName) = 0;
virtual void LoadScore(int ClientID) = 0; virtual void LoadScore(int ClientID) = 0;
virtual void SaveScore(int ClientID, float Time, float CpTime[NUM_CHECKPOINTS]) = 0; virtual void SaveScore(int ClientID, float Time, float CpTime[NUM_CHECKPOINTS]) = 0;

View file

@ -59,6 +59,11 @@ void CFileScore::MapPoints(int ClientID, const char* MapName)
// TODO: implement // TODO: implement
} }
void CFileScore::MapVote(int ClientID, const char* MapName)
{
// TODO: implement
}
void CFileScore::SaveScoreThread(void *pUser) void CFileScore::SaveScoreThread(void *pUser)
{ {
CFileScore *pSelf = (CFileScore *) pUser; CFileScore *pSelf = (CFileScore *) pUser;

View file

@ -64,6 +64,7 @@ public:
virtual void LoadScore(int ClientID); virtual void LoadScore(int ClientID);
virtual void MapPoints(int ClientID, const char* MapName); virtual void MapPoints(int ClientID, const char* MapName);
virtual void MapVote(int ClientID, const char* MapName);
virtual void SaveScore(int ClientID, float Time, virtual void SaveScore(int ClientID, float Time,
float CpTime[NUM_CHECKPOINTS]); float CpTime[NUM_CHECKPOINTS]);
virtual void SaveTeamScore(int* ClientIDs, unsigned int Size, float Time); virtual void SaveTeamScore(int* ClientIDs, unsigned int Size, float Time);

View file

@ -394,6 +394,74 @@ void CSqlScore::SaveTeamScoreThread(void *pUser)
lock_release(gs_SqlLock); lock_release(gs_SqlLock);
} }
void CSqlScore::MapVote(int ClientID, const char* MapName)
{
CSqlMapData *Tmp = new CSqlMapData();
Tmp->m_ClientID = ClientID;
str_copy(Tmp->m_aMap, MapName, 128);
Tmp->m_pSqlData = this;
void *VoteThread = thread_create(MapVoteThread, Tmp);
#if defined(CONF_FAMILY_UNIX)
pthread_detach((pthread_t)VoteThread);
#endif
}
void CSqlScore::MapVoteThread(void *pUser)
{
lock_wait(gs_SqlLock);
CSqlMapData *pData = (CSqlMapData *)pUser;
// Connect to database
if(pData->m_pSqlData->Connect())
{
char originalMap[128];
strcpy(originalMap,pData->m_aMap);
pData->m_pSqlData->ClearString(pData->m_aMap);
pData->m_pSqlData->FuzzyString(pData->m_aMap);
try
{
char aBuf[768];
str_format(aBuf, sizeof(aBuf), "SELECT Map, Server FROM %s_maps WHERE Map LIKE '%s' COLLATE utf8_general_ci ORDER BY LENGTH(Map), Map LIMIT 1;", pData->m_pSqlData->m_pPrefix, pData->m_aMap);
pData->m_pSqlData->m_pResults = pData->m_pSqlData->m_pStatement->executeQuery(aBuf);
if(pData->m_pSqlData->m_pResults->rowsCount() != 1)
{
str_format(aBuf, sizeof(aBuf), "No map like \"%s\" found.", originalMap);
}
else
{
pData->m_pSqlData->m_pResults->next();
char aMap[128];
strcpy(aMap, pData->m_pSqlData->m_pResults->getString("Map").c_str());
char aServer[32];
strcpy(aServer, pData->m_pSqlData->m_pResults->getString("Server").c_str());
char aCmd[256];
str_format(aCmd, sizeof(aCmd), "sv_reset_file types/%s/flexreset.cfg; change_map %s", aServer, aMap);
char aChatmsg[512];
str_format(aChatmsg, sizeof(aChatmsg), "'%s' called vote to change server option '%s' (%s)", pData->m_pSqlData->GameServer()->Server()->ClientName(pData->m_ClientID), aMap, "/map");
pData->m_pSqlData->GameServer()->CallVote(pData->m_ClientID, aMap, aCmd, "/map", aChatmsg);
}
delete pData->m_pSqlData->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: Could not update time");
}
pData->m_pSqlData->Disconnect();
}
delete pData;
lock_release(gs_SqlLock);
}
void CSqlScore::MapPoints(int ClientID, const char* MapName) void CSqlScore::MapPoints(int ClientID, const char* MapName)
{ {
CSqlMapData *Tmp = new CSqlMapData(); CSqlMapData *Tmp = new CSqlMapData();
@ -401,9 +469,9 @@ void CSqlScore::MapPoints(int ClientID, const char* MapName)
str_copy(Tmp->m_aMap, MapName, 128); str_copy(Tmp->m_aMap, MapName, 128);
Tmp->m_pSqlData = this; Tmp->m_pSqlData = this;
void *PointsThread = thread_create(MapPointsThread, Tmp); void *InfoThread = thread_create(MapPointsThread, Tmp);
#if defined(CONF_FAMILY_UNIX) #if defined(CONF_FAMILY_UNIX)
pthread_detach((pthread_t)PointsThread); pthread_detach((pthread_t)InfoThread);
#endif #endif
} }
@ -419,22 +487,28 @@ void CSqlScore::MapPointsThread(void *pUser)
char originalMap[128]; char originalMap[128];
strcpy(originalMap,pData->m_aMap); strcpy(originalMap,pData->m_aMap);
pData->m_pSqlData->ClearString(pData->m_aMap); pData->m_pSqlData->ClearString(pData->m_aMap);
pData->m_pSqlData->FuzzyString(pData->m_aMap);
try try
{ {
char aBuf[768]; char aBuf[768];
str_format(aBuf, sizeof(aBuf), "SELECT Points FROM %s_maps WHERE Map ='%s'", pData->m_pSqlData->m_pPrefix, pData->m_aMap); str_format(aBuf, sizeof(aBuf), "SELECT Map, Server, Points FROM %s_maps WHERE Map LIKE '%s' COLLATE utf8_general_ci ORDER BY LENGTH(Map), Map LIMIT 1;", pData->m_pSqlData->m_pPrefix, pData->m_aMap);
pData->m_pSqlData->m_pResults = pData->m_pSqlData->m_pStatement->executeQuery(aBuf); pData->m_pSqlData->m_pResults = pData->m_pSqlData->m_pStatement->executeQuery(aBuf);
if(pData->m_pSqlData->m_pResults->rowsCount() != 1) if(pData->m_pSqlData->m_pResults->rowsCount() != 1)
{ {
str_format(aBuf, sizeof(aBuf), "No map called \"%s\" found.", originalMap); str_format(aBuf, sizeof(aBuf), "No map like \"%s\" found.", originalMap);
} }
else else
{ {
pData->m_pSqlData->m_pResults->next(); pData->m_pSqlData->m_pResults->next();
int points = (int)pData->m_pSqlData->m_pResults->getInt("Points"); int points = (int)pData->m_pSqlData->m_pResults->getInt("Points");
str_format(aBuf, sizeof(aBuf), "Finishing \"%s\" will give you %d points.", originalMap, points); char aMap[128];
strcpy(aMap, pData->m_pSqlData->m_pResults->getString("Map").c_str());
char aServer[32];
strcpy(aServer, pData->m_pSqlData->m_pResults->getString("Server").c_str());
aServer[0] = toupper(aServer[0]);
str_format(aBuf, sizeof(aBuf), "\"%s\" on %s (%d points)", aMap, aServer, points);
} }
pData->m_pSqlData->GameServer()->SendChatTarget(pData->m_ClientID, aBuf); pData->m_pSqlData->GameServer()->SendChatTarget(pData->m_ClientID, aBuf);
@ -1055,8 +1129,25 @@ void CSqlScore::ShowTimes(int ClientID, const char* pName, int Debut)
#endif #endif
} }
// anti SQL injection void CSqlScore::FuzzyString(char *pString)
{
char newString[32*4-1];
int pos = 0;
for(int i=0;i<64;i++)
{
if(!pString[i])
break;
newString[pos++] = pString[i];
newString[pos++] = '%';
}
newString[pos] = '\0';
strcpy(pString, newString);
}
// anti SQL injection
void CSqlScore::ClearString(char *pString) void CSqlScore::ClearString(char *pString)
{ {
char newString[32*2-1]; char newString[32*2-1];

View file

@ -41,6 +41,7 @@ class CSqlScore: public IScore
} }
static void MapPointsThread(void *pUser); static void MapPointsThread(void *pUser);
static void MapVoteThread(void *pUser);
static void LoadScoreThread(void *pUser); static void LoadScoreThread(void *pUser);
static void SaveScoreThread(void *pUser); static void SaveScoreThread(void *pUser);
static void SaveTeamScoreThread(void *pUser); static void SaveTeamScoreThread(void *pUser);
@ -57,6 +58,7 @@ class CSqlScore: public IScore
bool Connect(); bool Connect();
void Disconnect(); void Disconnect();
void FuzzyString(char *pString);
// anti SQL injection // anti SQL injection
void ClearString(char *pString); void ClearString(char *pString);
@ -69,6 +71,7 @@ public:
virtual void LoadScore(int ClientID); virtual void LoadScore(int ClientID);
virtual void MapPoints(int ClientID, const char* MapName); virtual void MapPoints(int ClientID, const char* MapName);
virtual void MapVote(int ClientID, const char* MapName);
virtual void SaveScore(int ClientID, float Time, virtual void SaveScore(int ClientID, float Time,
float CpTime[NUM_CHECKPOINTS]); float CpTime[NUM_CHECKPOINTS]);
virtual void SaveTeamScore(int* aClientIDs, unsigned int Size, float Time); virtual void SaveTeamScore(int* aClientIDs, unsigned int Size, float Time);