diff options
Diffstat (limited to 'src/engine/server/server.cpp')
| -rw-r--r-- | src/engine/server/server.cpp | 186 |
1 files changed, 178 insertions, 8 deletions
diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index 65affc64..8958a405 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -361,6 +361,8 @@ CServer::CServer() : m_DemoRecorder(&m_SnapshotDelta) m_numLoggedInAdmins = 0; m_Votebans = NULL; + m_InfoTexts = NULL; + m_InfoTextInterval = -1; Init(); } @@ -374,9 +376,34 @@ CServer::~CServer() delete m_Votebans; m_Votebans = tmp; } + + // delte info texts + while(m_InfoTexts != NULL) + { + CInfoText *tmp = m_InfoTexts->m_Next; + delete m_InfoTexts; + m_InfoTexts = tmp; + } } +void CServer::UpdateLoggedInAdmins() +{ + bool gotAny = (m_numLoggedInAdmins > 0); + m_numLoggedInAdmins = 0; + for(int i = 0; i < MAX_CLIENTS; ++i) + { + if(m_aClients[i].m_State == CClient::STATE_INGAME && m_aClients[i].m_Authed >= AUTHED_SUBADMIN) + { + ++m_numLoggedInAdmins; + } + } + if(gotAny != (m_numLoggedInAdmins > 0)) + { + UpdateServerInfo(); + } +} + int CServer::TrySetClientName(int ClientID, const char *pName) { char aTrimmedName[64]; @@ -794,11 +821,6 @@ int CServer::DelClientCallback(int ClientID, const char *pReason, void *pUser) // notify the mod about the drop if(pThis->m_aClients[ClientID].m_State >= CClient::STATE_READY) pThis->GameServer()->OnClientDrop(ClientID, pReason); - - // check if dropped player is admin - if (pThis->IsAuthed(ClientID)) { - pThis->DecreaseLoggedInAdmins(); - } pThis->m_aClients[ClientID].m_State = CClient::STATE_EMPTY; pThis->m_aClients[ClientID].m_aName[0] = 0; @@ -808,6 +830,10 @@ int CServer::DelClientCallback(int ClientID, const char *pReason, void *pUser) pThis->m_aClients[ClientID].m_AuthTries = 0; pThis->m_aClients[ClientID].m_pRconCmdToSend = 0; pThis->m_aClients[ClientID].m_Snapshots.PurgeAll(); + + // could have been an admin + pThis->UpdateLoggedInAdmins(); + return 0; } @@ -1125,7 +1151,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) char aBuf[256]; str_format(aBuf, sizeof(aBuf), "ClientID=%d authed (admin)", ClientID); Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); - IncreaseLoggedInAdmins(); + UpdateLoggedInAdmins(); } else if(g_Config.m_SvRconModPassword[0] && str_comp(pPw, g_Config.m_SvRconModPassword) == 0) { @@ -1165,7 +1191,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) char aBuf[256]; str_format(aBuf, sizeof(aBuf), "ClientID=%d authed (subadmin:%s)", ClientID, loginit->first.c_str()); Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); - IncreaseLoggedInAdmins(); + UpdateLoggedInAdmins(); } else if(g_Config.m_SvRconMaxTries) { @@ -1820,6 +1846,145 @@ void CServer::ConRemoveLogin(IConsole::IResult *pResult, void *pUser) } } +void CServer::ConAddInfo(IConsole::IResult *pResult, void *pUser) +{ + CServer* pThis = static_cast<CServer *>(pUser); + int interval = pResult->GetInteger(0); + if(interval < 1 || interval > 1440) + { + pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", "Interval must be between 1 and 1440."); + return; + } + + // add info text + CInfoText *t = new CInfoText; + t->m_Interval = interval; + t->m_Text = std::string(pResult->GetString(1)); + // insert front + t->m_Next = pThis->m_InfoTexts; + pThis->m_InfoTexts = t; + + pThis->UpdateInfoTexts(); + + // message to console + char aBuf[128]; + str_format(aBuf, sizeof(aBuf), "Added the following info text: %s", t->m_Text.c_str()); + pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", aBuf); +} + +void CServer::ConRemoveInfo(IConsole::IResult *pResult, void *pUser) +{ + CServer* pThis = static_cast<CServer *>(pUser); + int i = pResult->GetInteger(0); + int count = 0; + bool removed = false; + + CInfoText **t = &(pThis->m_InfoTexts); + while(*t != NULL) + { + if(count++ == i) + { + // remove + CInfoText *next = (*t)->m_Next; + delete *t; + *t = next; + removed = true; + break; + } + t = &((*t)->m_Next); + } + + pThis->UpdateInfoTexts(); + + if(removed) + pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", "Info text removed"); + else + pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", "Info text not found"); +} + +void CServer::ConListInfo(IConsole::IResult *pResult, void *pUser) +{ + CServer* pThis = static_cast<CServer *>(pUser); + char aBuf[128]; + int count = 0; + + CInfoText *t = pThis->m_InfoTexts; + while(t != NULL) + { + str_format(aBuf, sizeof(aBuf), "#%d interval=%d min text='%s'", count++, t->m_Interval, t->m_Text.c_str()); + pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", aBuf); + t = t->m_Next; + } + + str_format(aBuf, sizeof(aBuf), "%d info text(s)", count); + pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", aBuf); +} + +void CServer::UpdateInfoTexts() +{ + // in case that there are no info texts + if(m_InfoTexts == NULL) + { + m_InfoTextInterval = -1; // no interval + return; + } + + // need some random numbers later + init_rand(); + + // update interval, set it to LCM(all text intervals) + m_InfoTextInterval = 1; // lowest possible interval + CInfoText *t = m_InfoTexts; + while(t != NULL) + { + m_InfoTextInterval = lcm(m_InfoTextInterval, t->m_Interval); + t->m_IntervalTicks = TickSpeed() * 60 * t->m_Interval; // min to ticks + t->m_NextTick = rand() % t->m_IntervalTicks; // variance + t = t->m_Next; + } + m_InfoTextInterval *= TickSpeed() * 60; // min to ticks + + // count total number of messages per interval + int numMsg = 0; + t = m_InfoTexts; + while(t != NULL) + { + numMsg += m_InfoTextInterval / t->m_IntervalTicks; + t = t->m_Next; + } + + // interval between messages + m_InfoTextMsgInterval = m_InfoTextInterval / numMsg; + // additional pause to sync interval and msg interval + m_InfoTextIntervalPause = m_InfoTextInterval % numMsg; +} + +std::string CServer::GetNextInfoText() +{ + CInfoText *selectedText = NULL, + *t = m_InfoTexts; + // the counter r keeps track of how many equally due texts there are and actually helps so that every text has the same chance even though there are r-1 random decisions + int r = 1; + while(t != NULL) + { + // use this text if none is selected or this one is more due than the previously selected + // in the case that both are equally due, select one random + if(selectedText == NULL + || t->m_NextTick < selectedText->m_NextTick + || (t->m_NextTick == selectedText->m_NextTick && (rand() % ++r) == 0)) + selectedText = t; + t = t->m_Next; + } + + // return empty string if no text applies + if(selectedText == NULL) + return std::string(); + + // update tick and return string + selectedText->m_NextTick += selectedText->m_IntervalTicks; + return selectedText->m_Text; +} + void CServer::ConKick(IConsole::IResult *pResult, void *pUser) { if(pResult->NumArguments() > 1) @@ -1859,6 +2024,7 @@ void CServer::ConStatus(IConsole::IResult *pResult, void *pUser) pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", aBuf); } } + pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", "Quick help: kick <id> <reason=''> | ban <id> <min=5> <reason=''> | voteban <id> <sec=300> | kill <id>"); } void CServer::ConShutdown(IConsole::IResult *pResult, void *pUser) @@ -1943,7 +2109,7 @@ void CServer::rconLogClientOut(int ClientID, const char *msg) char aBuf[32]; str_format(aBuf, sizeof(aBuf), "ClientID=%d logged out", ClientID); Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); - DecreaseLoggedInAdmins(); + UpdateLoggedInAdmins(); } } @@ -2033,6 +2199,10 @@ void CServer::RegisterCommands() Console()->Register("add_login", "ss", CFGFLAG_SERVER, ConAddLogin, this, "Add a subadmin login. The rcon password will be user:pass with no additional spaces.", IConsole::ACCESS_LEVEL_ADMIN); Console()->Register("remove_login", "s", CFGFLAG_SERVER, ConRemoveLogin, this, "Remove a subadmin login", IConsole::ACCESS_LEVEL_ADMIN); + + Console()->Register("add_info", "is", CFGFLAG_SERVER, ConAddInfo, this, "Add a info text that is printed in the chat repeatedly in the given interval of minutes."); + Console()->Register("remove_info", "i", CFGFLAG_SERVER, ConRemoveInfo, this, "Remove a info text"); + Console()->Register("list_info", "", CFGFLAG_SERVER, ConListInfo, this, "Show all info texts"); // register console commands in sub parts m_ServerBan.InitServerBan(Console(), Storage(), this); |