diff --git a/CMakeLists.txt b/CMakeLists.txt index 899ad43c6..663cea024 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -996,6 +996,7 @@ endif() ######################################################################## set(EXPECTED_DATA + announcement.txt arrow.png assets/entities/comfort/ddnet.png assets/entities/license.txt diff --git a/data/announcement.txt b/data/announcement.txt new file mode 100644 index 000000000..e69de29bb diff --git a/data/autoexec_server.cfg b/data/autoexec_server.cfg index e9d5b5aa8..edbc6ea0f 100644 --- a/data/autoexec_server.cfg +++ b/data/autoexec_server.cfg @@ -80,10 +80,10 @@ sv_rescue_delay 5 # Message on chat displayed when joining sv_welcome "Welcome to my server!" -# File which will have the announcements (each one in new line) +# File which contains the announcements (One on each line) sv_announcement_filename "announcement.txt" -# Number of minutes before next announcement will be displayed (from the announcement file) +# Number of minutes before the next announcement will be displayed (from the announcement file) sv_announcement_interval 120 # Whether announcements will be displayed in their order or chosen randomly diff --git a/src/engine/server.h b/src/engine/server.h index 462afbb97..42e246319 100644 --- a/src/engine/server.h +++ b/src/engine/server.h @@ -273,7 +273,8 @@ public: virtual bool DnsblWhite(int ClientId) = 0; virtual bool DnsblPending(int ClientId) = 0; virtual bool DnsblBlack(int ClientId) = 0; - virtual const char *GetAnnouncementLine(const char *pFileName) = 0; + virtual const char *GetAnnouncementLine() = 0; + virtual void ReadAnnouncementsFile(const char *pFileName) = 0; virtual bool ClientPrevIngame(int ClientId) = 0; virtual const char *GetNetErrorString(int ClientId) = 0; virtual void ResetNetErrorString(int ClientId) = 0; diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index c96a2bdd2..44a2f99b3 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -537,8 +537,7 @@ int CServer::Init() m_CurrentGameTick = MIN_TICK; - m_AnnouncementLastLine = 0; - m_aAnnouncementFile[0] = '\0'; + m_AnnouncementLastLine = -1; mem_zero(m_aPrevStates, sizeof(m_aPrevStates)); return 0; @@ -2783,6 +2782,8 @@ int CServer::Run() Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); } + ReadAnnouncementsFile(g_Config.m_SvAnnouncementFileName); + // process pending commands m_pConsole->StoreCommands(false); m_pRegister->OnConfigChange(); @@ -3809,6 +3810,17 @@ void CServer::ConchainStdoutOutputLevel(IConsole::IResult *pResult, void *pUserD } } +void CServer::ConchainAnnouncementFileName(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData) +{ + CServer *pSelf = (CServer *)pUserData; + bool Changed = pResult->NumArguments() && str_comp(pResult->GetString(0), g_Config.m_SvAnnouncementFileName); + pfnCallback(pResult, pCallbackUserData); + if(Changed) + { + pSelf->ReadAnnouncementsFile(g_Config.m_SvAnnouncementFileName); + } +} + #if defined(CONF_FAMILY_UNIX) void CServer::ConchainConnLoggingServerChange(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData) { @@ -3887,6 +3899,8 @@ void CServer::RegisterCommands() Console()->Chain("loglevel", ConchainLoglevel, this); Console()->Chain("stdout_output_level", ConchainStdoutOutputLevel, this); + Console()->Chain("sv_announcement_filename", ConchainAnnouncementFileName, this); + #if defined(CONF_FAMILY_UNIX) Console()->Chain("sv_conn_logging_server", ConchainConnLoggingServerChange, this); #endif @@ -3930,27 +3944,30 @@ void CServer::GetClientAddr(int ClientId, NETADDR *pAddr) const } } -const char *CServer::GetAnnouncementLine(const char *pFileName) +void CServer::ReadAnnouncementsFile(const char *pFileName) { - if(str_comp(pFileName, m_aAnnouncementFile) != 0) - { - str_copy(m_aAnnouncementFile, pFileName); - m_vAnnouncements.clear(); + m_vAnnouncements.clear(); - CLineReader LineReader; - if(!LineReader.OpenFile(m_pStorage->OpenFile(pFileName, IOFLAG_READ, IStorage::TYPE_ALL))) + if(pFileName[0] == '\0') + return; + + CLineReader LineReader; + if(!LineReader.OpenFile(m_pStorage->OpenFile(pFileName, IOFLAG_READ, IStorage::TYPE_ALL))) + { + dbg_msg("announcements", "failed to open '%s'", pFileName); + return; + } + while(const char *pLine = LineReader.Get()) + { + if(str_length(pLine) && pLine[0] != '#') { - return 0; - } - while(const char *pLine = LineReader.Get()) - { - if(str_length(pLine) && pLine[0] != '#') - { - m_vAnnouncements.emplace_back(pLine); - } + m_vAnnouncements.emplace_back(pLine); } } +} +const char *CServer::GetAnnouncementLine() +{ if(m_vAnnouncements.empty()) { return 0; @@ -3959,7 +3976,7 @@ const char *CServer::GetAnnouncementLine(const char *pFileName) { m_AnnouncementLastLine = 0; } - else if(!Config()->m_SvAnnouncementRandom) + else if(!g_Config.m_SvAnnouncementRandom) { if(++m_AnnouncementLastLine >= m_vAnnouncements.size()) m_AnnouncementLastLine %= m_vAnnouncements.size(); diff --git a/src/engine/server/server.h b/src/engine/server/server.h index 76f8730e5..7a54efe36 100644 --- a/src/engine/server/server.h +++ b/src/engine/server/server.h @@ -259,7 +259,6 @@ public: size_t m_AnnouncementLastLine; std::vector m_vAnnouncements; - char m_aAnnouncementFile[IO_MAX_PATH_LENGTH]; std::shared_ptr m_pFileLogger = nullptr; std::shared_ptr m_pStdoutLogger = nullptr; @@ -427,6 +426,7 @@ public: static void ConchainSixupUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); static void ConchainLoglevel(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); static void ConchainStdoutOutputLevel(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); + static void ConchainAnnouncementFileName(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); #if defined(CONF_FAMILY_UNIX) static void ConchainConnLoggingServerChange(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); @@ -443,7 +443,8 @@ public: void GetClientAddr(int ClientId, NETADDR *pAddr) const override; int m_aPrevStates[MAX_CLIENTS]; - const char *GetAnnouncementLine(const char *pFileName) override; + const char *GetAnnouncementLine() override; + void ReadAnnouncementsFile(const char *pFileName) override; int *GetIdMap(int ClientId) override; diff --git a/src/engine/shared/config_variables.h b/src/engine/shared/config_variables.h index ab2e7c34c..6ed8942a9 100644 --- a/src/engine/shared/config_variables.h +++ b/src/engine/shared/config_variables.h @@ -548,8 +548,8 @@ MACRO_CONFIG_INT(SvMinTeamSize, sv_min_team_size, 2, 1, MAX_CLIENTS, CFGFLAG_SER MACRO_CONFIG_INT(SvMaxTeamSize, sv_max_team_size, MAX_CLIENTS, 1, MAX_CLIENTS, CFGFLAG_SERVER | CFGFLAG_GAME, "Maximum team size") MACRO_CONFIG_INT(SvMapVote, sv_map_vote, 1, 0, 1, CFGFLAG_SERVER, "Whether to allow /map") -MACRO_CONFIG_STR(SvAnnouncementFileName, sv_announcement_filename, 24, "announcement.txt", CFGFLAG_SERVER, "file which will have the announcement, each one at a line") -MACRO_CONFIG_INT(SvAnnouncementInterval, sv_announcement_interval, 300, 1, 9999, CFGFLAG_SERVER, "time(minutes) in which the announcement will be displayed from the announcement file") +MACRO_CONFIG_STR(SvAnnouncementFileName, sv_announcement_filename, IO_MAX_PATH_LENGTH, "announcement.txt", CFGFLAG_SERVER, "File which contains the announcements, one on each line") +MACRO_CONFIG_INT(SvAnnouncementInterval, sv_announcement_interval, 120, 1, 9999, CFGFLAG_SERVER, "The time (minutes) for how often an announcement will be displayed from the announcement file") MACRO_CONFIG_INT(SvAnnouncementRandom, sv_announcement_random, 1, 0, 1, CFGFLAG_SERVER, "Whether announcements are sequential or random") MACRO_CONFIG_INT(SvOldLaser, sv_old_laser, 0, 0, 1, CFGFLAG_SERVER | CFGFLAG_GAME, "Whether lasers can hit you if you shot them and that they pull you towards the bounce origin (0 for all new maps) or lasers can't hit you if you shot them, and they pull others towards the shooter") diff --git a/src/game/server/ddracecommands.cpp b/src/game/server/ddracecommands.cpp index 961d99224..e65cad482 100644 --- a/src/game/server/ddracecommands.cpp +++ b/src/game/server/ddracecommands.cpp @@ -893,6 +893,12 @@ void CGameContext::ConReloadCensorlist(IConsole::IResult *pResult, void *pUserDa pSelf->ReadCensorList(); } +void CGameContext::ConReloadAnnouncement(IConsole::IResult *pResult, void *pUserData) +{ + CGameContext *pSelf = (CGameContext *)pUserData; + pSelf->Server()->ReadAnnouncementsFile(g_Config.m_SvAnnouncementFileName); +} + void CGameContext::ConDumpAntibot(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index 1315906ca..3b0356a8e 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -1253,7 +1253,7 @@ void CGameContext::OnTick() if(Server()->Tick() % (g_Config.m_SvAnnouncementInterval * Server()->TickSpeed() * 60) == 0) { - const char *pLine = Server()->GetAnnouncementLine(g_Config.m_SvAnnouncementFileName); + const char *pLine = Server()->GetAnnouncementLine(); if(pLine) SendChat(-1, TEAM_ALL, pLine); } @@ -3643,6 +3643,7 @@ void CGameContext::OnConsoleInit() Console()->Register("set_team_all", "i[team-id]", CFGFLAG_SERVER, ConSetTeamAll, this, "Set team of all players to team"); Console()->Register("hot_reload", "", CFGFLAG_SERVER | CMDFLAG_TEST, ConHotReload, this, "Reload the map while preserving the state of tees and teams"); Console()->Register("reload_censorlist", "", CFGFLAG_SERVER, ConReloadCensorlist, this, "Reload the censorlist"); + Console()->Register("reload_announcement", "", CFGFLAG_SERVER, ConReloadAnnouncement, this, "Reload the announcements"); Console()->Register("add_vote", "s[name] r[command]", CFGFLAG_SERVER, ConAddVote, this, "Add a voting option"); Console()->Register("remove_vote", "r[name]", CFGFLAG_SERVER, ConRemoveVote, this, "remove a voting option"); diff --git a/src/game/server/gamecontext.h b/src/game/server/gamecontext.h index 164829cdf..d25758c53 100644 --- a/src/game/server/gamecontext.h +++ b/src/game/server/gamecontext.h @@ -516,6 +516,7 @@ private: static void ConUnFreezeHammer(IConsole::IResult *pResult, void *pUserData); static void ConReloadCensorlist(IConsole::IResult *pResult, void *pUserData); + static void ConReloadAnnouncement(IConsole::IResult *pResult, void *pUserData); CCharacter *GetPracticeCharacter(IConsole::IResult *pResult);