mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 10:08:18 +00:00
Thread safe /map
This commit is contained in:
parent
ea31171873
commit
7f4dc2bb4e
|
@ -518,6 +518,9 @@ void CGameContext::ConMap(IConsole::IResult *pResult, void *pUserData)
|
|||
if (!pPlayer)
|
||||
return;
|
||||
|
||||
if(pSelf->RateLimitPlayerVote(pResult->m_ClientID) || pSelf->RateLimitPlayerMapVote(pResult->m_ClientID))
|
||||
return;
|
||||
|
||||
#if defined(CONF_SQL)
|
||||
if(g_Config.m_SvUseSQL)
|
||||
if(pPlayer->m_LastSQLQuery + g_Config.m_SvSqlQueriesDelay * pSelf->Server()->TickSpeed() >= pSelf->Server()->Tick())
|
||||
|
|
|
@ -920,12 +920,6 @@ void CGameContext::OnTick()
|
|||
}
|
||||
|
||||
/*
|
||||
if(m_pRandomMapResult && m_pRandomMapResult->m_Done)
|
||||
{
|
||||
str_copy(g_Config.m_SvMap, m_pRandomMapResult->m_aMap, sizeof(g_Config.m_SvMap));
|
||||
m_pRandomMapResult = NULL;
|
||||
}
|
||||
|
||||
if(m_pMapVoteResult && m_pMapVoteResult->m_Done)
|
||||
{
|
||||
m_VoteKick = false;
|
||||
|
@ -939,8 +933,6 @@ void CGameContext::OnTick()
|
|||
str_format(aChatmsg, sizeof(aChatmsg), "'%s' called vote to change server option '%s' (%s)", Server()->ClientName(m_pMapVoteResult->m_ClientID), m_pMapVoteResult->m_aMap, "/map");
|
||||
|
||||
CallVote(m_pMapVoteResult->m_ClientID, m_pMapVoteResult->m_aMap, aCmd, "/map", aChatmsg);
|
||||
|
||||
m_pMapVoteResult = NULL;
|
||||
}
|
||||
*/
|
||||
|
||||
|
@ -1424,68 +1416,8 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID)
|
|||
}
|
||||
else if(MsgID == NETMSGTYPE_CL_CALLVOTE)
|
||||
{
|
||||
int64 Now = Server()->Tick();
|
||||
int64 TickSpeed = Server()->TickSpeed();
|
||||
|
||||
if(g_Config.m_SvRconVote && !Server()->GetAuthedState(ClientID))
|
||||
{
|
||||
SendChatTarget(ClientID, "You can only vote after logging in.");
|
||||
if(RateLimitPlayerVote(ClientID))
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_Config.m_SvDnsblVote && !m_pServer->DnsblWhite(ClientID) && Server()->DistinctClientCount() > 1)
|
||||
{
|
||||
// blacklisted by dnsbl
|
||||
SendChatTarget(ClientID, "You are not allowed to vote due to DNSBL.");
|
||||
return;
|
||||
}
|
||||
|
||||
if(g_Config.m_SvSpamprotection && pPlayer->m_LastVoteTry && pPlayer->m_LastVoteTry + TickSpeed * 3 > Now)
|
||||
return;
|
||||
|
||||
pPlayer->m_LastVoteTry = Now;
|
||||
if(g_Config.m_SvSpectatorVotes == 0 && pPlayer->GetTeam() == TEAM_SPECTATORS)
|
||||
{
|
||||
SendChatTarget(ClientID, "Spectators aren't allowed to start a vote.");
|
||||
return;
|
||||
}
|
||||
|
||||
if(m_VoteCloseTime)
|
||||
{
|
||||
SendChatTarget(ClientID, "Wait for current vote to end before calling a new one.");
|
||||
return;
|
||||
}
|
||||
|
||||
if(Now < pPlayer->m_FirstVoteTick)
|
||||
{
|
||||
char aBuf[64];
|
||||
str_format(aBuf, sizeof(aBuf), "You must wait %d seconds before making your first vote.", (int)((pPlayer->m_FirstVoteTick - Now) / TickSpeed) + 1);
|
||||
SendChatTarget(ClientID, aBuf);
|
||||
return;
|
||||
}
|
||||
|
||||
int TimeLeft = pPlayer->m_LastVoteCall + TickSpeed * g_Config.m_SvVoteDelay - Now;
|
||||
if(pPlayer->m_LastVoteCall && TimeLeft > 0)
|
||||
{
|
||||
char aChatmsg[64];
|
||||
str_format(aChatmsg, sizeof(aChatmsg), "You must wait %d seconds before making another vote.", (int)(TimeLeft / TickSpeed) + 1);
|
||||
SendChatTarget(ClientID, aChatmsg);
|
||||
return;
|
||||
}
|
||||
|
||||
NETADDR Addr;
|
||||
Server()->GetClientAddr(ClientID, &Addr);
|
||||
int VoteMuted = 0;
|
||||
for(int i = 0; i < m_NumVoteMutes && !VoteMuted; i++)
|
||||
if(!net_addr_comp_noport(&Addr, &m_aVoteMutes[i].m_Addr))
|
||||
VoteMuted = (m_aVoteMutes[i].m_Expire - Server()->Tick()) / Server()->TickSpeed();
|
||||
if(VoteMuted > 0)
|
||||
{
|
||||
char aChatmsg[64];
|
||||
str_format(aChatmsg, sizeof(aChatmsg), "You are not permitted to vote for the next %d seconds.", VoteMuted);
|
||||
SendChatTarget(ClientID, aChatmsg);
|
||||
return;
|
||||
}
|
||||
|
||||
char aChatmsg[512] = {0};
|
||||
char aDesc[VOTE_DESC_LENGTH] = {0};
|
||||
|
@ -1516,11 +1448,12 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID)
|
|||
SendChatTarget(ClientID, "Invalid option");
|
||||
return;
|
||||
}
|
||||
if(!Authed && (str_startswith(pOption->m_aCommand, "sv_map ") || str_startswith(pOption->m_aCommand, "change_map ") || str_startswith(pOption->m_aCommand, "random_map") || str_startswith(pOption->m_aCommand, "random_unfinished_map")) && time_get() < m_LastMapVote + (time_freq() * g_Config.m_SvVoteMapTimeDelay))
|
||||
if((str_startswith(pOption->m_aCommand, "sv_map ")
|
||||
|| str_startswith(pOption->m_aCommand, "change_map ")
|
||||
|| str_startswith(pOption->m_aCommand, "random_map")
|
||||
|| str_startswith(pOption->m_aCommand, "random_unfinished_map"))
|
||||
&& RateLimitPlayerMapVote(ClientID))
|
||||
{
|
||||
str_format(aChatmsg, sizeof(aChatmsg), "There's a %d second delay between map-votes, please wait %d seconds.", g_Config.m_SvVoteMapTimeDelay, (int)(((m_LastMapVote+(g_Config.m_SvVoteMapTimeDelay * time_freq()))/time_freq())-(time_get()/time_freq())));
|
||||
SendChatTarget(ClientID, aChatmsg);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3581,3 +3514,84 @@ void CGameContext::ForceVote(int EnforcerID, bool Success)
|
|||
str_format(aBuf, sizeof(aBuf), "forcing vote %s", pOption);
|
||||
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
|
||||
}
|
||||
|
||||
bool CGameContext::RateLimitPlayerVote(int ClientID)
|
||||
{
|
||||
int64 Now = Server()->Tick();
|
||||
int64 TickSpeed = Server()->TickSpeed();
|
||||
CPlayer *pPlayer = m_apPlayers[ClientID];
|
||||
|
||||
if(g_Config.m_SvRconVote && !Server()->GetAuthedState(ClientID))
|
||||
{
|
||||
SendChatTarget(ClientID, "You can only vote after logging in.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (g_Config.m_SvDnsblVote && !m_pServer->DnsblWhite(ClientID) && Server()->DistinctClientCount() > 1)
|
||||
{
|
||||
// blacklisted by dnsbl
|
||||
SendChatTarget(ClientID, "You are not allowed to vote due to DNSBL.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if(g_Config.m_SvSpamprotection && pPlayer->m_LastVoteTry && pPlayer->m_LastVoteTry + TickSpeed * 3 > Now)
|
||||
return true;
|
||||
|
||||
pPlayer->m_LastVoteTry = Now;
|
||||
if(g_Config.m_SvSpectatorVotes == 0 && pPlayer->GetTeam() == TEAM_SPECTATORS)
|
||||
{
|
||||
SendChatTarget(ClientID, "Spectators aren't allowed to start a vote.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if(m_VoteCloseTime)
|
||||
{
|
||||
SendChatTarget(ClientID, "Wait for current vote to end before calling a new one.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if(Now < pPlayer->m_FirstVoteTick)
|
||||
{
|
||||
char aBuf[64];
|
||||
str_format(aBuf, sizeof(aBuf), "You must wait %d seconds before making your first vote.", (int)((pPlayer->m_FirstVoteTick - Now) / TickSpeed) + 1);
|
||||
SendChatTarget(ClientID, aBuf);
|
||||
return true;
|
||||
}
|
||||
|
||||
int TimeLeft = pPlayer->m_LastVoteCall + TickSpeed * g_Config.m_SvVoteDelay - Now;
|
||||
if(pPlayer->m_LastVoteCall && TimeLeft > 0)
|
||||
{
|
||||
char aChatmsg[64];
|
||||
str_format(aChatmsg, sizeof(aChatmsg), "You must wait %d seconds before making another vote.", (int)(TimeLeft / TickSpeed) + 1);
|
||||
SendChatTarget(ClientID, aChatmsg);
|
||||
return true;
|
||||
}
|
||||
|
||||
NETADDR Addr;
|
||||
Server()->GetClientAddr(ClientID, &Addr);
|
||||
int VoteMuted = 0;
|
||||
for(int i = 0; i < m_NumVoteMutes && !VoteMuted; i++)
|
||||
if(!net_addr_comp_noport(&Addr, &m_aVoteMutes[i].m_Addr))
|
||||
VoteMuted = (m_aVoteMutes[i].m_Expire - Server()->Tick()) / Server()->TickSpeed();
|
||||
if(VoteMuted > 0)
|
||||
{
|
||||
char aChatmsg[64];
|
||||
str_format(aChatmsg, sizeof(aChatmsg), "You are not permitted to vote for the next %d seconds.", VoteMuted);
|
||||
SendChatTarget(ClientID, aChatmsg);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CGameContext::RateLimitPlayerMapVote(int ClientID)
|
||||
{
|
||||
if(!Server()->GetAuthedState(ClientID) && time_get() < m_LastMapVote + (time_freq() * g_Config.m_SvVoteMapTimeDelay))
|
||||
{
|
||||
char aChatmsg[512] = {0};
|
||||
str_format(aChatmsg, sizeof(aChatmsg), "There's a %d second delay between map-votes, please wait %d seconds.",
|
||||
g_Config.m_SvVoteMapTimeDelay, (int)((m_LastMapVote + g_Config.m_SvVoteMapTimeDelay * time_freq() - time_get())/time_freq()));
|
||||
SendChatTarget(ClientID, aChatmsg);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -259,6 +259,10 @@ public:
|
|||
bool PlayerModerating();
|
||||
void ForceVote(int EnforcerID, bool Success);
|
||||
|
||||
// Checks if player can vote and notify them about the reason
|
||||
bool RateLimitPlayerVote(int ClientID);
|
||||
bool RateLimitPlayerMapVote(int ClientID);
|
||||
|
||||
private:
|
||||
|
||||
bool m_VoteWillPass;
|
||||
|
|
|
@ -818,7 +818,20 @@ void CPlayer::ProcessSqlResult(CSqlPlayerResult &Result)
|
|||
GameServer()->SendBroadcast(Result.m_Data.m_Broadcast, -1);
|
||||
break;
|
||||
case CSqlPlayerResult::MAP_VOTE:
|
||||
// TODO: start vote
|
||||
GameServer()->m_VoteKick = false;
|
||||
GameServer()->m_VoteSpec = false;
|
||||
GameServer()->m_LastMapVote = time_get();
|
||||
|
||||
char aCmd[256];
|
||||
str_format(aCmd, sizeof(aCmd),
|
||||
"sv_reset_file types/%s/flexreset.cfg; change_map \"%s\"",
|
||||
Result.m_Data.m_MapVote.m_Server, Result.m_Data.m_MapVote.m_Map);
|
||||
|
||||
char aChatmsg[512];
|
||||
str_format(aChatmsg, sizeof(aChatmsg), "'%s' called vote to change server option '%s' (%s)",
|
||||
Server()->ClientName(m_ClientID), Result.m_Data.m_MapVote.m_Map, "/map");
|
||||
|
||||
GameServer()->CallVote(m_ClientID, Result.m_Data.m_MapVote.m_Map, aCmd, "/map", aChatmsg);
|
||||
break;
|
||||
case CSqlPlayerResult::PLAYER_INFO:
|
||||
GameServer()->Score()->PlayerData(m_ClientID)->Set(
|
||||
|
|
|
@ -43,6 +43,9 @@ void CSqlPlayerResult::SetVariant(Variant v)
|
|||
m_Data.m_Broadcast[0] = 0;
|
||||
break;
|
||||
case MAP_VOTE:
|
||||
m_Data.m_MapVote.m_Map[0] = '\0';
|
||||
m_Data.m_MapVote.m_Reason[0] = '\0';
|
||||
m_Data.m_MapVote.m_Server[0] = '\0';
|
||||
break;
|
||||
case PLAYER_INFO:
|
||||
m_Data.m_Info.m_Score = -9999;
|
||||
|
@ -373,13 +376,16 @@ bool CSqlScore::MapVoteThread(CSqlServer* pSqlServer, const CSqlData<CSqlPlayerR
|
|||
}
|
||||
else
|
||||
{
|
||||
pSqlServer->GetResults()->first();
|
||||
auto Server = pSqlServer->GetResults()->getString("Server");
|
||||
auto Map = pSqlServer->GetResults()->getString("Map");
|
||||
strcpy(paMessages[0], "/map"); // reason
|
||||
str_copy(paMessages[1], Server.c_str(), sizeof(paMessages[0]));
|
||||
str_copy(paMessages[2], Map.c_str(), sizeof(paMessages[0]));
|
||||
pData->m_pResult->SetVariant(CSqlPlayerResult::MAP_VOTE);
|
||||
auto MapVote = &pData->m_pResult->m_Data.m_MapVote;
|
||||
strcpy(MapVote->m_Reason, "/map");
|
||||
str_copy(MapVote->m_Server, Server.c_str(), sizeof(MapVote->m_Server));
|
||||
str_copy(MapVote->m_Map, Map.c_str(), sizeof(MapVote->m_Map));
|
||||
|
||||
for(char *p = paMessages[1]; *p; p++) // lower case server
|
||||
for(char *p = MapVote->m_Server; *p; p++) // lower case server
|
||||
*p = tolower(*p);
|
||||
}
|
||||
pData->m_pResult->m_Done = true;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <engine/server/sql_string_helpers.h>
|
||||
#include <game/prng.h>
|
||||
#include <game/voting.h>
|
||||
|
||||
#include "../score.h"
|
||||
|
||||
|
@ -34,6 +35,12 @@ struct CSqlPlayerResult
|
|||
int m_HasFinishScore;
|
||||
int m_Birthday; // 0 indicates no birthday
|
||||
} m_Info;
|
||||
struct
|
||||
{
|
||||
char m_Reason[VOTE_REASON_LENGTH];
|
||||
char m_Server[32+1];
|
||||
char m_Map[128+1];
|
||||
} m_MapVote;
|
||||
} m_Data; // PLAYER_INFO
|
||||
|
||||
void SetVariant(Variant v);
|
||||
|
|
Loading…
Reference in a new issue