To the last DDRace. Need a lot fix

This commit is contained in:
btd 2010-07-29 23:55:33 +04:00
parent 070927384a
commit 7f42b6225b
9 changed files with 357 additions and 60 deletions

View file

@ -542,7 +542,8 @@ int CServer::NewClientCallback(int ClientId, void *pUser)
pThis->m_aClients[ClientId].m_aClan[0] = 0;
pThis->m_aClients[ClientId].m_Authed = 0;
pThis->m_aClients[ClientId].m_PwTries = 0; // init pw tries
memset(&pThis->m_aClients[ClientId].m_Addr, 0, sizeof(NETADDR)); // init that too
memset(&pThis->m_aClients[ClientId].m_Addr, 0, sizeof(NETADDR)); // init that too
pThis->m_aClients[ClientId].m_CommandTriesTimer= 0;
pThis->m_aClients[ClientId].m_CmdTries = 0; //Floff init cmd tries
pThis->m_aClients[ClientId].m_Resistent = 0;
pThis->m_aClients[ClientId].Reset();
@ -562,7 +563,8 @@ int CServer::DelClientCallback(int ClientId, void *pUser)
pThis->m_aClients[ClientId].m_aClan[0] = 0;
pThis->m_aClients[ClientId].m_Authed = 0;
pThis->m_aClients[ClientId].m_PwTries = 0; // init pw tries
memset(&pThis->m_aClients[ClientId].m_Addr, 0, sizeof(NETADDR)); // init that too
memset(&pThis->m_aClients[ClientId].m_Addr, 0, sizeof(NETADDR)); // init that too
pThis->m_aClients[ClientId].m_CommandTriesTimer= 0;
pThis->m_aClients[ClientId].m_CmdTries = 0; //Floff init cmd tries
pThis->m_aClients[ClientId].m_Resistent = 0;
pThis->m_aClients[ClientId].m_Snapshots.PurgeAll();
@ -702,10 +704,52 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket)
SendMap(ClientId);
}
}
else
{
else {
if(m_aClients[ClientId].m_Authed == 0 && Msg != NETMSG_INPUT && Msg != NETMSG_REQUEST_MAP_DATA)
{
if(time_get() > m_aClients[ClientId].m_CommandTriesTimer + time_freq())
{
m_aClients[ClientId].m_CmdTries = 0;
m_aClients[ClientId].m_CommandTriesTimer = time_get();
}
m_aClients[ClientId].m_CmdTries++;
//dbg_msg("server","client_counter: %d", clients[cid].command_tries);
if(m_aClients[ClientId].m_CmdTries > g_Config.m_SvNetmsgLimit && g_Config.m_SvNetmsgLimit != 0)
{
dbg_msg("server", "client sending too many messages to server (DDoS?), banned. cid=%x ip=%d.%d.%d.%d",
ClientId,
m_aClients[ClientId].m_Addr.ip[0], m_aClients[ClientId].m_Addr.ip[1], m_aClients[ClientId].m_Addr.ip[2], m_aClients[ClientId].m_Addr.ip[3]
);
BanAdd(m_aClients[ClientId].m_Addr, g_Config.m_SvNetmsgBanTime, "exceeding netmsg_limit, Bye"); // bye
return;
}
}
}
if(Sys)
{
if(Msg != NETMSG_INPUT && Msg != NETMSG_REQUEST_MAP_DATA)
{
m_aClients[ClientId].m_CmdTries++;
if(time_get() < m_aClients[ClientId].m_LastCommand + time_freq()/* * 1*/)
{
if(m_aClients[ClientId].m_CmdTries > g_Config.m_SvRconCmdTries)
{
dbg_msg("server", "client trying to flood the server (%d tries), ban. cid=%x ip=%d.%d.%d.%d", m_aClients[ClientId].m_CmdTries,
ClientId,
m_aClients[ClientId].m_Addr.ip[0], m_aClients[ClientId].m_Addr.ip[1], m_aClients[ClientId].m_Addr.ip[2], m_aClients[ClientId].m_Addr.ip[3]
);
BanAdd(m_aClients[ClientId].m_Addr, g_Config.m_SvRconBanTime); // bye
return;
}
}
else
{
m_aClients[ClientId].m_CmdTries = 0;
}
m_aClients[ClientId].m_LastCommand = time_get();
}
// system message
if(Msg == NETMSG_REQUEST_MAP_DATA)
{
@ -740,10 +784,14 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket)
{
if(m_aClients[ClientId].m_State == CClient::STATE_CONNECTING)
{
Addr = m_NetServer.ClientAddr(ClientId);
//Addr = m_NetServer.ClientAddr(ClientId);
dbg_msg("server", "player is ready. ClientId=%x ip=%d.%d.%d.%d",
ClientId, Addr.ip[0], Addr.ip[1], Addr.ip[2], Addr.ip[3]);
ClientId,
m_aClients[ClientId].m_Addr.ip[0],
m_aClients[ClientId].m_Addr.ip[1],
m_aClients[ClientId].m_Addr.ip[2],
m_aClients[ClientId].m_Addr.ip[3]);
m_aClients[ClientId].m_State = CClient::STATE_READY;
GameServer()->OnClientConnected(ClientId);
GameServer()->OnSetAuthed(ClientId, (void*)m_aClients[ClientId].m_Authed);
@ -754,10 +802,14 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket)
{
if(m_aClients[ClientId].m_State == CClient::STATE_READY)
{
Addr = m_NetServer.ClientAddr(ClientId);
//Addr = m_NetServer.ClientAddr(ClientId);
dbg_msg("server", "player has entered the game. ClientId=%x ip=%d.%d.%d.%d",
ClientId, Addr.ip[0], Addr.ip[1], Addr.ip[2], Addr.ip[3]);
ClientId,
m_aClients[ClientId].m_Addr.ip[0],
m_aClients[ClientId].m_Addr.ip[1],
m_aClients[ClientId].m_Addr.ip[2],
m_aClients[ClientId].m_Addr.ip[3]);
m_aClients[ClientId].m_State = CClient::STATE_INGAME;
GameServer()->OnClientEnter(ClientId);
}
@ -820,20 +872,22 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket)
if(Unpacker.Error() == 0/* && m_aClients[ClientId].m_Authed*/)
{
dbg_msg("server", "ClientId=%d Level=%d rcon='%s'", ClientId, m_aClients[ClientId].m_Authed, pCmd);
Addr = m_NetServer.ClientAddr(ClientId);
if(m_aClients[ClientId].m_Authed == 0)
dbg_msg("server", "ClientId=%d Level=%d Rcon='%s'", ClientId, m_aClients[ClientId].m_Authed, pCmd);
//Addr = m_NetServer.ClientAddr(ClientId);
if(m_aClients[ClientId].m_Authed > 0)
{
if(++m_aClients[ClientId].m_CmdTries > g_Config.m_SvRconTries)
{
dbg_msg("server", "client tried rcon command without permissions, ban. cid=%x ip=%d.%d.%d.%d",
ClientId,
m_aClients[ClientId].m_Addr.ip[0], m_aClients[ClientId].m_Addr.ip[1], m_aClients[ClientId].m_Addr.ip[2], m_aClients[ClientId].m_Addr.ip[3]);
BanAdd(m_aClients[ClientId].m_Addr, g_Config.m_SvRconTriesBantime); // bye
}
}
else
Console()->ExecuteLine(pCmd, m_aClients[ClientId].m_Authed, ClientId);
} else {
dbg_msg("server", "client tried rcon command without permissions. Cid=%x ip=%d.%d.%d.%d",
ClientId,
m_aClients[ClientId].m_Addr.ip[0],
m_aClients[ClientId].m_Addr.ip[1],
m_aClients[ClientId].m_Addr.ip[2],
m_aClients[ClientId].m_Addr.ip[3]);
//BanAdd(m_aClients[ClientId].m_Addr, g_Config.m_SvRconTriesBantime); // bye
}
}
}
else if(Msg == NETMSG_RCON_AUTH)
@ -1021,9 +1075,9 @@ void CServer::UpdateServerInfo()
}
}
int CServer::BanAdd(NETADDR Addr, int Seconds)
int CServer::BanAdd(NETADDR Addr, int Seconds, const char *Reason)
{
return m_NetServer.BanAdd(Addr, Seconds);
return m_NetServer.BanAdd(Addr, Seconds, Reason);
}
int CServer::BanRemove(NETADDR Addr)
@ -1185,6 +1239,11 @@ int CServer::Run()
// load map
if(LoadMap(g_Config.m_SvMap))
{
Console()->ExecuteLine("tune_reset", 4, -1);
Console()->ExecuteLine("sv_hit 1",4,-1);
Console()->ExecuteLine("sv_npc 0",4,-1);
Console()->ExecuteLine("sv_phook 1",4,-1);
Console()->ExecuteLine("sv_endless_drag 0",4,-1); //TODO: Such string executed where autoexec executed. No need??
// new map loaded
GameServer()->OnShutdown();
@ -1305,15 +1364,28 @@ void CServer::ConKick(IConsole::IResult *pResult, void *pUser, int ClientId)
void CServer::ConBan(IConsole::IResult *pResult, void *pUser, int ClientId1)
{
NETADDR Addr;
char aAddrStr[128];
char aAddrStr[128], Bufz[100];
const char *pStr = pResult->GetString(0);
int Minutes = 30;
int Minutes = 30, jkl;//????
str_format(Bufz, sizeof(Bufz), "");
if(pResult->NumArguments() > 1)
Minutes = pResult->GetInteger(1);
if(pResult->NumArguments() > 2)
{
for (jkl = 2;jkl <= pResult->NumArguments();jkl++)
{
strcat(Bufz, pResult->GetString(jkl));
strcat(Bufz," ");
}
}
else
str_format(Bufz, sizeof(Bufz), "no reason given");
if(net_addr_from_str(&Addr, pStr) == 0)
((CServer *)pUser)->BanAdd(Addr, Minutes*60);
((CServer *)pUser)->BanAdd(Addr, Minutes*60, Bufz);
else if(StrAllnum(pStr))
{
int ClientId = str_toint(pStr);
@ -1327,7 +1399,7 @@ void CServer::ConBan(IConsole::IResult *pResult, void *pUser, int ClientId1)
}
NETADDR Addr = ((CServer *)pUser)->m_NetServer.ClientAddr(ClientId);
((CServer *)pUser)->BanAdd(Addr, Minutes*60);
((CServer *)pUser)->BanAdd(Addr, Minutes*60, Bufz);
}
Addr.port = 0;
@ -1457,7 +1529,8 @@ void CServer::RegisterCommands()
m_pConsole = Kernel()->RequestInterface<IConsole>();
Console()->Register("kick", "i", CFGFLAG_SERVER, ConKick, this, "", 2);
Console()->Register("ban", "s?i", CFGFLAG_SERVER, ConBan, this, "", 2);
Console()->Register("ban", "s?i?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s?s", CFGFLAG_SERVER, ConBan, 0, "",2); //horrible long string
Console()->Register("unban", "s", CFGFLAG_SERVER, ConUnban, this, "", 3);
Console()->Register("bans", "", CFGFLAG_SERVER, ConBans, this, "", 2);
Console()->Register("status", "", CFGFLAG_SERVER, ConStatus, this, "", 1);
@ -1555,6 +1628,12 @@ int main(int argc, const char **argv) // ignore_convention
pServer->RegisterCommands();
pGameServer->OnConsoleInit();
pConsole->ExecuteLine("tune_reset", 4, -1);
pConsole->ExecuteLine("sv_hit 1", 4, -1);
pConsole->ExecuteLine("sv_npc 0", 4, -1);
pConsole->ExecuteLine("sv_phook 1", 4, -1);
pConsole->ExecuteLine("sv_endless_drag 0",4,-1);
//TODO it is in 2 places (and in one file O_o)
// execute autoexec file
pConsole->ExecuteFile("autoexec.cfg");

View file

@ -103,6 +103,7 @@ public:
NETADDR m_Addr; // for storing address
int m_PwTries; // a players rcon pw tries
int m_CmdTries; //Floff players rcon command tries, to prevent command flood server crash
int64 m_CommandTriesTimer; // time
void Reset();
};
@ -178,7 +179,7 @@ public:
void SendServerInfo(NETADDR *pAddr, int Token);
void UpdateServerInfo();
int BanAdd(NETADDR Addr, int Seconds);
int BanAdd(NETADDR Addr, int Seconds, const char *Reason);
int BanRemove(NETADDR Addr);

View file

@ -101,11 +101,11 @@ void CNetBase::SendPacketConnless(NETSOCKET Socket, NETADDR *pAddr, const void *
net_udp_send(Socket, pAddr, aBuffer, 6+DataSize);
}
void CNetBase::SendPacket(NETSOCKET Socket, NETADDR *pAddr, CNetPacketConstruct *pPacket)
int32_t CNetBase::SendPacket(NETSOCKET Socket, NETADDR *pAddr, CNetPacketConstruct *pPacket)
{
unsigned char aBuffer[NET_MAX_PACKETSIZE];
int CompressedSize = -1;
int FinalSize = -1;
int32_t CompressedSize = -1;
int32_t FinalSize = -1;
// log the data
if(ms_DataLogSent)
@ -141,7 +141,8 @@ void CNetBase::SendPacket(NETSOCKET Socket, NETADDR *pAddr, CNetPacketConstruct
aBuffer[0] = ((pPacket->m_Flags<<4)&0xf0)|((pPacket->m_Ack>>8)&0xf);
aBuffer[1] = pPacket->m_Ack&0xff;
aBuffer[2] = pPacket->m_NumChunks;
net_udp_send(Socket, pAddr, aBuffer, FinalSize);
int32_t ResultVal;
ResultVal = net_udp_send(Socket, pAddr, aBuffer, FinalSize);
// log raw socket data
if(ms_DataLogSent)
@ -152,7 +153,9 @@ void CNetBase::SendPacket(NETSOCKET Socket, NETADDR *pAddr, CNetPacketConstruct
io_write(ms_DataLogSent, aBuffer, FinalSize);
io_flush(ms_DataLogSent);
}
return ResultVal;
}
return 0;
}
// TODO: rename this function

View file

@ -172,7 +172,7 @@ public:
void Disconnect(const char *pReason);
int Update();
int Flush();
int32_t Flush();
int Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr);
int QueueChunk(int Flags, int DataSize, const void *pData);
@ -217,6 +217,7 @@ public:
{
NETADDR m_Addr;
int m_Expires;
char m_Reason[100];
};
private:
@ -275,7 +276,8 @@ public:
int Drop(int ClientID, const char *Reason);
// banning
int BanAdd(NETADDR Addr, int Seconds);
int BanAdd(NETADDR Addr, int Seconds, const char *Reason);
int BanAddNoDrop(NETADDR Addr, int Seconds, const char *Reason);
int BanRemove(NETADDR Addr);
int BanNum(); // caution, slow
int BanGet(int Index, CBanInfo *pInfo); // caution, slow
@ -339,7 +341,7 @@ public:
static void SendControlMsg(NETSOCKET Socket, NETADDR *pAddr, int Ack, int ControlMsg, const void *pExtra, int ExtraSize);
static void SendPacketConnless(NETSOCKET Socket, NETADDR *pAddr, const void *pData, int DataSize);
static void SendPacket(NETSOCKET Socket, NETADDR *pAddr, CNetPacketConstruct *pPacket);
static int32_t SendPacket(NETSOCKET Socket, NETADDR *pAddr, CNetPacketConstruct *pPacket);
static int UnpackPacket(unsigned char *pBuffer, int Size, CNetPacketConstruct *pPacket);
// The backroom is ack-NET_MAX_SEQUENCE/2. Used for knowing if we acked a packet or not

View file

@ -64,15 +64,18 @@ void CNetConnection::SignalResend()
m_Construct.m_Flags |= NET_PACKETFLAG_RESEND;
}
int CNetConnection::Flush()
int32_t CNetConnection::Flush()
{
int NumChunks = m_Construct.m_NumChunks;
int32_t NumChunks = m_Construct.m_NumChunks;
if(!NumChunks && !m_Construct.m_Flags)
return 0;
// send of the packets
m_Construct.m_Ack = m_Ack;
CNetBase::SendPacket(m_Socket, &m_PeerAddr, &m_Construct);
if(CNetBase::SendPacket(m_Socket, &m_PeerAddr, &m_Construct) < 0) {
m_State = NET_CONNSTATE_ERROR;
SetError("send error" );
}
// update send times
m_LastSendTime = time_get();

View file

@ -1,4 +1,5 @@
#include <base/system.h>
#include "config.h"
#include "network.h"
#define MACRO_LIST_LINK_FIRST(Object, First, Prev, Next) \
@ -78,7 +79,8 @@ int CNetServer::Drop(int ClientID, const char *pReason)
{
// TODO: insert lots of checks here
NETADDR Addr = ClientAddr(ClientID);
char Bufz[100];
str_format( Bufz, sizeof(Bufz),"trying to connect so soon");
dbg_msg("net_server", "client dropped. cid=%d ip=%d.%d.%d.%d reason=\"%s\"",
ClientID,
Addr.ip[0], Addr.ip[1], Addr.ip[2], Addr.ip[3],
@ -89,6 +91,7 @@ int CNetServer::Drop(int ClientID, const char *pReason)
if(m_pfnDelClient)
m_pfnDelClient(ClientID, m_UserPtr);
m_aSlots[ClientID].m_Connection.Disconnect(pReason);
BanAddNoDrop(Addr, g_Config.m_SvReconnectTime, Bufz);
return 0;
}
@ -139,7 +142,7 @@ int CNetServer::BanRemove(NETADDR Addr)
return -1;
}
int CNetServer::BanAdd(NETADDR Addr, int Seconds)
int CNetServer::BanAdd(NETADDR Addr, int Seconds, const char * Reason)
{
int IpHash = (Addr.ip[0]+Addr.ip[1]+Addr.ip[2]+Addr.ip[3])&0xff;
int Stamp = -1;
@ -157,7 +160,11 @@ int CNetServer::BanAdd(NETADDR Addr, int Seconds)
if(pBan)
{
// adjust the ban
if (pBan->m_Info.m_Expires > Seconds)
return 0;
pBan->m_Info.m_Expires = Stamp;
strcpy(pBan->m_Info.m_Reason, m_Reason);
return 0;
}
@ -212,10 +219,13 @@ int CNetServer::BanAdd(NETADDR Addr, int Seconds)
char Buf[128];
NETADDR BanAddr;
if(Seconds)
if(Seconds) {
str_format(Buf, sizeof(Buf), "you have been banned for %d minutes", Seconds/60);
else
strcat(Buf, Reason);
} else {
str_format(Buf, sizeof(Buf), "you have been banned for life");
strcat(Buf, Reason);
}
for(int i = 0; i < MaxClients(); i++)
{
@ -229,6 +239,83 @@ int CNetServer::BanAdd(NETADDR Addr, int Seconds)
return 0;
}
int CNetServer::BanAddNoDrop(NETADDR Addr, int Seconds, const char *Reason)
{
int IpHash = (Addr.ip[0]+Addr.ip[1]+Addr.ip[2]+Addr.ip[3])&0xff;
int Stamp = -1;
CBan *pBan;
// remove the port
Addr.port = 0;
if(Seconds)
Stamp = time_timestamp() + Seconds;
// search to see if it already exists
pBan = m_aBans[IpHash];
MACRO_LIST_FIND(pBan, m_pHashNext, net_addr_comp(&pBan->m_Info.m_Addr, &Addr) == 0);
if(pBan)
{
// adjust the ban
if (pBan->m_Info.m_Expires > Seconds)
return 0;
pBan->m_Info.m_Expires = Stamp;
strcpy(pBan->m_Info.m_Reason, m_Reason);
return 0;
}
if(!m_BanPool_FirstFree)
return -1;
// fetch and clear the new ban
pBan = m_BanPool_FirstFree;
MACRO_LIST_UNLINK(pBan, m_BanPool_FirstFree, m_pPrev, m_pNext);
// setup the ban info
pBan->m_Info.m_Expires = Stamp;
pBan->m_Info.m_Addr = Addr;
strcpy(pBan->m_Info.m_Reason, m_Reason);
// add it to the ban hash
MACRO_LIST_LINK_FIRST(pBan, m_aBans[IpHash], m_pHashPrev, m_pHashNext);
// insert it into the used list
{
if(m_BanPool_FirstUsed)
{
CBan *pInsertAfter = m_BanPool_FirstUsed;
MACRO_LIST_FIND(pInsertAfter, m_pNext, Stamp < pInsertAfter->m_Info.m_Expires);
if(pInsertAfter)
pInsertAfter = pInsertAfter->m_pPrev;
else
{
// add to last
pInsertAfter = m_BanPool_FirstUsed;
while(pInsertAfter->m_pNext)
pInsertAfter = pInsertAfter->m_pNext;
}
if(pInsertAfter)
{
MACRO_LIST_LINK_AFTER(pBan, pInsertAfter, m_pPrev, m_pNext);
}
else
{
MACRO_LIST_LINK_FIRST(pBan, m_BanPool_FirstUsed, m_pPrev, m_pNext);
}
}
else
{
MACRO_LIST_LINK_FIRST(pBan, m_BanPool_FirstUsed, m_pPrev, m_pNext);
}
}
return 0;
}
int CNetServer::Update()
{
int Now = time_timestamp();
@ -293,14 +380,14 @@ int CNetServer::Recv(CNetChunk *pChunk)
char BanStr[128];
if(pBan->m_Info.m_Expires)
{
int Mins = ((pBan->m_Info.m_Expires - Now)+59)/60;
if(Mins == 1)
str_format(BanStr, sizeof(BanStr), "banned for %d minute", Mins);
int Mins = ((pBan->m_Info.m_Expires - Now))/60;
if(Mins > 1)
str_format(BanStr, sizeof(BanStr), "Banned for %d minute(s) for %s", Mins, pBan->m_Info.m_Reason);
else
str_format(BanStr, sizeof(BanStr), "banned for %d minutes", Mins);
str_format(BanStr, sizeof(BanStr), "Banned for %d minute(s) for %s", (pBan->m_Info.m_Expires - Now), pBan->m_Info.m_Reason);
}
else
str_format(BanStr, sizeof(BanStr), "banned for life");
str_format(BanStr, sizeof(BanStr), "banned for life. %s", pBan->m_Info.m_Reason);
CNetBase::SendControlMsg(m_Socket, &Addr, 0, NET_CTRLMSG_CLOSE, BanStr, str_length(BanStr)+1);
continue;
}

View file

@ -451,10 +451,23 @@ void CGameContext::OnTick()
if(m_VoteEnforce == VOTE_ENFORCE_YES)
{
Console()->ExecuteLine(m_aVoteCommand, 4, -1);
EndVote();
SendChat(-1, CGameContext::CHAT_ALL, "Vote passed");
//Console()->ExecuteLine(m_aVoteCommand, 4, -1);
//EndVote();
//SendChat(-1, CGameContext::CHAT_ALL, "Vote passed");
if(vote_enforce == VOTE_ENFORCE_YES)
{
Console()->ExecuteLine(m_aVoteCommand, 3,-1);
SendChat(-1, CGameContext::CHAT_ALL, "Vote passed (enforced by Admin)");
dbg_msg("Vote","Due to vote enforcing, vote level has been set to 3");
EndVote();
}
else
{
Console()->ExecuteLine(m_aVoteCommand, 4,-1);
dbg_msg("Vote","vote level is set to 4");
EndVote();
SendChat(-1, CGameContext::CHAT_ALL, "Vote passed");
}
if(m_apPlayers[m_VoteCreator])
m_apPlayers[m_VoteCreator]->m_Last_VoteCall = 0;
}
@ -523,7 +536,19 @@ bool compare_players(CPlayer *pl1, CPlayer *pl2)
}
void CGameContext::OnSetAuthed(int client_id, void* status)
{
{
if(m_apPlayers[client_id])
{
m_apPlayers[client_id]->m_Authed = (int)status;
char buf[11];
str_format(buf, sizeof(buf), "ban %d %d", client_id, g_Config.m_SvVoteKickBanTime);
//dbg_msg("hooks","%d", m_aVoteCommand == buf);//???
if ( !strcmp(m_aVoteCommand,buf))
{
m_VoteEnforce = CGameContext::VOTE_ENFORCE_NO;
dbg_msg("hooks","Aborting vote");
}
}
if(m_apPlayers[client_id])
m_apPlayers[client_id]->m_Authed = (int)status;
}
@ -747,13 +772,23 @@ void CGameContext::OnMessage(int MsgId, CUnpacker *pUnpacker, int ClientId)
if(str_comp_nocase(pMsg->m_Type, "option") == 0)
{
CVoteOption *pOption = m_pVoteOptionFirst;
static int64 last_mapvote = 0; //floff
while(pOption)
{
if(str_comp_nocase(pMsg->m_Value, pOption->m_aCommand) == 0)
{
if(m_apPlayers[ClientId]->m_Authed == 0 && strncmp(pOption->m_aCommand, "sv_map ", 7) == 0 && time_get() < last_mapvote + (time_freq() * g_Config.m_SvVoteMapDelay))
{
char chatmsg[512] = {0};
str_format(chatmsg, sizeof(chatmsg), "There's a %d second delay between map-votes,Please wait %d Second(s)", g_Config.m_SvVoteMapDelay,((last_mapvote+(g_Config.m_SvVoteMapDelay * time_freq()))/time_freq())-(time_get()/time_freq()));
SendChatTarget(ClientId, chatmsg);
return;
}
str_format(aChatmsg, sizeof(aChatmsg), "%s called vote to change server option '%s'", Server()->ClientName(ClientId), pOption->m_aCommand);
str_format(aDesc, sizeof(aDesc), "%s", pOption->m_aCommand);
str_format(aCmd, sizeof(aCmd), "%s", pOption->m_aCommand);
last_mapvote = time_get();
break;
}
@ -766,10 +801,24 @@ void CGameContext::OnMessage(int MsgId, CUnpacker *pUnpacker, int ClientId)
SendChatTarget(ClientId, aChatmsg);
return;
}
last_mapvote = time_get();
}
else if(str_comp_nocase(pMsg->m_Type, "kick") == 0)
{
if(!g_Config.m_SvVoteKick)
if(m_apPlayers[ClientId]->m_Authed == 0 && time_get() < m_apPlayers[ClientId]->m_LastKickVote + (time_freq() * 5))
return;
else if(m_apPlayers[ClientId]->m_Authed == 0 && time_get() < m_apPlayers[ClientId]->m_LastKickVote + (time_freq() * g_Config.m_SvVoteKickDelay))
{
char chatmsg[512] = {0};
str_format(chatmsg, sizeof(chatmsg), "There's a %d second waittime between kickvotes for each player please wait %d second(s)",
g_Config.m_SvVoteKickDelay,
((m_apPlayers[ClientId]->m_LastKickVote + (m_apPlayers[ClientId]->m_LastKickVote*time_freq()))/time_freq())-(time_get()/time_freq())
);
SendChatTarget(client_id, chatmsg);
m_apPlayers[ClientId]->m_LastKickVote = time_get();
return;
}
else if(!g_Config.m_SvVoteKick)
{
SendChatTarget(ClientId, "Server does not allow voting to kick players");
return;

View file

@ -21,6 +21,12 @@ CPlayer::CPlayer(CGameContext *pGameServer, int CID, int Team)
m_Muted = 0;
this->m_ClientID = CID;
m_Team = GameServer()->m_pController->ClampTeam(Team);
m_LastPlaytime = time_get();
m_LastTarget_x = 0;
m_LastTarget_y = 0;
m_SentAfkWarning = 0; // afk timer's 1st warning after 50% of sv_max_afk_time
m_SentAfkWarning2 = 0;
}
CPlayer::~CPlayer()
@ -142,6 +148,7 @@ void CPlayer::OnDirectInput(CNetObj_PlayerInput *NewInput)
if(!Character && m_Team == -1)
m_ViewPos = vec2(NewInput->m_TargetX, NewInput->m_TargetY);
AfkTimer(NewInput->m_TargetX, NewInput->m_TargetY);
}
CCharacter *CPlayer::GetCharacter()
@ -207,3 +214,56 @@ void CPlayer::TryRespawn()
GameServer()->CreatePlayerSpawn(SpawnPos);
}
}
void CPlayer::AfkTimer(int new_target_x, int new_target_y)
{
/*
afk timer (x, y = mouse coordinates)
Since a player has to move the mouse to play, this is a better method than checking
the player's position in the game world, because it can easily be bypassed by just locking a key.
Frozen players could be kicked as well, because they can't move.
It also works for spectators.
*/
if(m_Authed) return; // don't kick admins
if(g_Config.m_SvMaxAfkTime == 0) return; // 0 = disabled
if(new_target_x != last_target_x || new_target_y != last_target_y)
{
m_LastPlaytime = time_get();
m_LastTarget_x = new_target_x;
m_LastTarget_y = new_target_y;
m_SentAfkWarning = 0; // afk timer's 1st warning after 50% of sv_max_afk_time
m_SentAfkWarning2 = 0;
}
else
{
// not playing, check how long
if(m_SentAfkWarning == 0 && m_LastPlaytime < time_get()-time_freq()*(int)(g_Config.m_SvMaxAfkTime*0.5))
{
sprintf(
m_pAfkMsg,
"You have been afk for %d seconds now. Please note that you get kicked after not playing for %d seconds.",
(int)(g_Config.m_SvMaxAfkTime*0.5),
g_Config.m_SvMaxAfkTime
);
m_pGameServer->SendChatTarget(client_id, m_pAfkMsg);
m_SentAfkWarning = 1;
} else if(m_SentAfkWarning2 == 0 && m_LastPlaytime < time_get()-time_freq()*(int)(g_Config.m_SvMaxAfkTime*0.9))
{
sprintf(
m_pAfkMsg,
"You have been afk for %d seconds now. Please note that you get kicked after not playing for %d seconds.",
(int)(g_Config.m_SvMaxAfkTime*0.9),
g_Config.m_SvMaxAfkTime
);
m_pGameServer->SendChatTarget(client_id, m_pAfkMsg);
m_SentAfkWarning = 1;
} else if(last_playtime < time_get()-time_freq()*g_Config.m_SvMaxAfkTime)
{
m_pGameServer->Server()->Kick(client_id,"Away from keyboard");
}
}
}

View file

@ -40,13 +40,15 @@ public:
int m_Vote;
int m_VotePos;
//
int m_Last_VoteCall;
int m_Last_VoteTry;
int m_Last_Chat;
int m_Last_SetTeam;
int m_Last_ChangeInfo;
int m_Last_Emote;
int m_Last_Kill;
int64 m_Last_KickVote;
int64 m_Last_VoteCall;
int64 m_Last_VoteTry;
int64 m_Last_Chat;
int64 m_Last_SetTeam;
int64 m_Last_ChangeInfo;
int64 m_Last_Emote;
int64 m_Last_Kill;
//DDRace
int m_Muted;
@ -81,6 +83,15 @@ public:
int m_ScoreStartTick;
bool m_ForceBalanced;
// afk timer
void AfkTimer(int new_target_x, int new_target_y);
int64 m_LastPlaytime;
int m_LastTarget_x;
int m_LastTarget_y;
int m_SentAfkWarning; // afk timer's 1st warning after 50% of sv_max_afk_time
int m_SentAfkWarning2; // afk timer's 2nd warning after 90% of sv_max_afk_time
char m_pAfkMsg[160];
private:
CCharacter *Character;
CGameContext *m_pGameServer;
@ -88,6 +99,8 @@ private:
CGameContext *GameServer() const { return m_pGameServer; }
IServer *Server() const;
//
bool m_Spawning;
int m_ClientID;