diff --git a/r5dev/core/init.cpp b/r5dev/core/init.cpp index da25a767..6bbc3f50 100644 --- a/r5dev/core/init.cpp +++ b/r5dev/core/init.cpp @@ -182,6 +182,8 @@ void Systems_Init() #endif // !DEDICATED && GAMEDLL_S3 NET_Attach(); + //NetChan_Attach(); + ConCommand_Attach(); IConVar_Attach(); CKeyValueSystem_Attach(); @@ -306,6 +308,8 @@ void Systems_Shutdown() #endif // !DEDICATED && GAMEDLL_S3 NET_Detach(); + //NetChan_Detach(); + ConCommand_Detach(); IConVar_Detach(); CKeyValueSystem_Detach(); diff --git a/r5dev/engine/host_state.cpp b/r5dev/engine/host_state.cpp index a1b8d7f8..44a0dc11 100644 --- a/r5dev/engine/host_state.cpp +++ b/r5dev/engine/host_state.cpp @@ -57,6 +57,7 @@ FORCEINLINE void CHostState::FrameUpdate(CHostState* pHostState, double flCurrentTime, float flFrameTime) { static bool bInitialized = false; + static bool bResetIdleName = false; if (!bInitialized) { g_pHostState->Setup(); @@ -106,15 +107,25 @@ FORCEINLINE void CHostState::FrameUpdate(CHostState* pHostState, double flCurren } case HostStates_t::HS_RUN: { + if (!g_pHostState->m_bActiveGame) + { + if (bResetIdleName) + { + g_pHostState->ResetLevelName(); + bResetIdleName = false; + } + } + else // Reset idle name the next non-active frame. + { + bResetIdleName = true; + } + CHostState_State_Run(&g_pHostState->m_iCurrentState, flCurrentTime, flFrameTime); break; } case HostStates_t::HS_GAME_SHUTDOWN: { DevMsg(eDLL_T::ENGINE, "%s - Shutdown host game\n", "CHostState::FrameUpdate"); - if (g_pHostState->m_bActiveGame) { - g_pHostState->ResetLevelName(); - } CHostState_State_GameShutDown(g_pHostState); break; } @@ -205,6 +216,7 @@ FORCEINLINE void CHostState::Think(void) const static bool bInitialized = false; static CFastTimer banListTimer; static CFastTimer pylonTimer; + static CFastTimer reloadTimer; static CFastTimer statsTimer; if (!bInitialized) // Initialize clocks. @@ -215,6 +227,7 @@ FORCEINLINE void CHostState::Think(void) const pylonTimer.Start(); #endif // DEDICATED statsTimer.Start(); + reloadTimer.Start(); #endif // !CLIENT_DLL bInitialized = true; } @@ -252,6 +265,14 @@ FORCEINLINE void CHostState::Think(void) const } #endif // DEDICATED #ifndef CLIENT_DLL + if (sv_autoReloadRate->GetBool()) + { + if (reloadTimer.GetDurationInProgress().GetSeconds() > sv_autoReloadRate->GetDouble()) + { + Cbuf_AddText(Cbuf_GetCurrentPlayer(), "reload\n", cmd_source_t::kCommandSrcCode); + reloadTimer.Start(); + } + } if (statsTimer.GetDurationInProgress().GetSeconds() > sv_statusRefreshInterval->GetDouble()) { string svCurrentPlaylist = KeyValues_GetCurrentPlaylist(); @@ -310,7 +331,6 @@ FORCEINLINE void CHostState::GameShutDown(void) g_pServerGameDLL->GameShutdown(); #endif // !CLIENT_DLL m_bActiveGame = 0; - ResetLevelName(); } } @@ -415,11 +435,11 @@ FORCEINLINE void CHostState::State_ChangeLevelMP(void) FORCEINLINE void CHostState::ResetLevelName(void) { #ifdef DEDICATED - const char* szNoMap = "server_idle"; + static const char* szNoMap = "server_idle"; #else // DEDICATED - const char* szNoMap = "main_menu"; + static const char* szNoMap = "main_menu"; #endif - snprintf(const_cast(m_levelName), sizeof(m_levelName), szNoMap); + Q_snprintf(const_cast(m_levelName), sizeof(m_levelName), szNoMap); } /////////////////////////////////////////////////////////////////////////////// diff --git a/r5dev/engine/net.cpp b/r5dev/engine/net.cpp index 624b5ced..2504e1a6 100644 --- a/r5dev/engine/net.cpp +++ b/r5dev/engine/net.cpp @@ -208,7 +208,7 @@ const char* NET_ErrorString(int iCode) case WSAENETDOWN : return "WSAENETDOWN"; case WSAENETUNREACH : return "WSAENETUNREACH"; case WSAENETRESET : return "WSAENETRESET"; - case WSAECONNABORTED : return "WSWSAECONNABORTEDAEINTR"; + case WSAECONNABORTED : return "WSAECONNABORTED"; case WSAECONNRESET : return "WSAECONNRESET"; case WSAENOBUFS : return "WSAENOBUFS"; case WSAEISCONN : return "WSAEISCONN"; diff --git a/r5dev/engine/net_chan.cpp b/r5dev/engine/net_chan.cpp index f283c880..d95fd30b 100644 --- a/r5dev/engine/net_chan.cpp +++ b/r5dev/engine/net_chan.cpp @@ -200,3 +200,18 @@ void CNetChan::Clear(bool bStopProcessing) { v_NetChan_Clear(this, bStopProcessing); } + +bool CNetChan::ProcessMessages(CNetChan* pChan, bf_read* pMsg) +{ + return v_NetChan_ProcessMessages(pChan, pMsg); +} + +/////////////////////////////////////////////////////////////////////////////// +void NetChan_Attach() +{ + DetourAttach((LPVOID*)&v_NetChan_ProcessMessages, &CNetChan::ProcessMessages); +} +void NetChan_Detach() +{ + DetourDetach((LPVOID*)&v_NetChan_ProcessMessages, &CNetChan::ProcessMessages); +} \ No newline at end of file diff --git a/r5dev/engine/net_chan.h b/r5dev/engine/net_chan.h index 9b774f59..4ca19ec4 100644 --- a/r5dev/engine/net_chan.h +++ b/r5dev/engine/net_chan.h @@ -101,6 +101,8 @@ public: bool IsOverflowed(void) const; void Clear(bool bStopProcessing); + + static bool ProcessMessages(CNetChan* pChan, bf_read* pMsg); //----------------------------------------------------------------------------- private: bool m_bProcessingMessages; @@ -175,18 +177,25 @@ static_assert(sizeof(CNetChan) == 0x1AC8); inline CMemory p_NetChan_Clear; inline auto v_NetChan_Clear = p_NetChan_Clear.RCast(); + +inline CMemory p_NetChan_ProcessMessages; +inline auto v_NetChan_ProcessMessages = p_NetChan_ProcessMessages.RCast(); /////////////////////////////////////////////////////////////////////////////// class VNetChannel : public IDetour { virtual void GetAdr(void) const { spdlog::debug("| FUN: CNetChan::Clear : {:#18x} |\n", p_NetChan_Clear.GetPtr()); + spdlog::debug("| FUN: CNetChan::ProcessMessages : {:#18x} |\n", p_NetChan_ProcessMessages.GetPtr()); spdlog::debug("+----------------------------------------------------------------+\n"); } virtual void GetFun(void) const { p_NetChan_Clear = g_GameDll.FindPatternSIMD(reinterpret_cast("\x88\x54\x24\x10\x53\x55\x57"), "xxxxxxx"); v_NetChan_Clear = p_NetChan_Clear.RCast(); /*88 54 24 10 53 55 57*/ + + p_NetChan_ProcessMessages = g_GameDll.FindPatternSIMD(reinterpret_cast("\x48\x89\x5C\x24\x00\x48\x89\x6C\x24\x00\x57\x48\x81\xEC\x00\x00\x00\x00\x48\x8B\xFA"), "xxxx?xxxx?xxxx????xxx"); + v_NetChan_ProcessMessages = p_NetChan_ProcessMessages.RCast();/*48 89 5C 24 ?? 48 89 6C 24 ?? 57 48 81 EC ?? ?? ?? ?? 48 8B FA*/ } virtual void GetVar(void) const { } virtual void GetCon(void) const { } @@ -196,4 +205,7 @@ class VNetChannel : public IDetour /////////////////////////////////////////////////////////////////////////////// REGISTER(VNetChannel); +void NetChan_Attach(); +void NetChan_Detach(); + #endif // NET_CHAN_H diff --git a/r5dev/engine/sys_dll2.cpp b/r5dev/engine/sys_dll2.cpp index e1114e2e..9a2a5973 100644 --- a/r5dev/engine/sys_dll2.cpp +++ b/r5dev/engine/sys_dll2.cpp @@ -55,9 +55,6 @@ bool CEngineAPI::ModInit(CEngineAPI* pEngineAPI, const char* pModName, const cha g_pEngineClient->SetRestrictServerCommands(true); // Restrict server commands. g_pEngineClient->SetRestrictClientCommands(true); // Restrict client commands. #endif // !DEDICATED - - ConCommandBase* disconnect = g_pCVar->FindCommandBase("disconnect"); - disconnect->AddFlags(FCVAR_SERVER_CAN_EXECUTE); // Make sure server is not restricted to this. } return results; } diff --git a/r5dev/networksystem/bansystem.cpp b/r5dev/networksystem/bansystem.cpp index 02a5dc95..53f7b656 100644 --- a/r5dev/networksystem/bansystem.cpp +++ b/r5dev/networksystem/bansystem.cpp @@ -12,20 +12,16 @@ #include "networksystem/bansystem.h" //----------------------------------------------------------------------------- -// Purpose: loads and parses the banlist +// Purpose: loads and parses the banned list //----------------------------------------------------------------------------- void CBanSystem::Load(void) { if (IsBanListValid()) - { m_vBanList.clear(); - } FileHandle_t pFile = FileSystem()->Open("banlist.json", "rt"); if (!pFile) - { return; - } uint32_t nLen = FileSystem()->Size(pFile); char* pBuf = MemAllocSingleton()->Alloc(nLen); @@ -43,9 +39,7 @@ void CBanSystem::Load(void) if (!jsIn.is_null()) { if (!jsIn["totalBans"].is_null()) - { nTotalBans = jsIn["totalBans"].get(); - } } for (size_t i = 0; i < nTotalBans; i++) @@ -243,7 +237,7 @@ void CBanSystem::BanListCheck(void) } //----------------------------------------------------------------------------- -// Purpose: checks if specified ip address or necleus id is banned +// Purpose: checks if specified ip address or nucleus id is banned // Input : &svIpAddress - // nNucleusID - // Output : true if banned, false if not banned @@ -272,7 +266,7 @@ bool CBanSystem::IsBanned(const string& svIpAddress, const uint64_t nNucleusID) } //----------------------------------------------------------------------------- -// Purpose: checks if refuselist is valid +// Purpose: checks if refused list is valid //----------------------------------------------------------------------------- bool CBanSystem::IsRefuseListValid(void) const { @@ -280,11 +274,227 @@ bool CBanSystem::IsRefuseListValid(void) const } //----------------------------------------------------------------------------- -// Purpose: checks if banlist is valid +// Purpose: checks if banned list is valid //----------------------------------------------------------------------------- bool CBanSystem::IsBanListValid(void) const { return !m_vBanList.empty(); } + +//----------------------------------------------------------------------------- +// Purpose: kicks a player by given name +// Input : &svPlayerName - +//----------------------------------------------------------------------------- +void CBanSystem::KickPlayerByName(const string& svPlayerName) +{ + if (svPlayerName.empty()) + return; + + for (int i = 0; i < MAX_PLAYERS; i++) + { + if (CClient* pClient = g_pClient->GetClient(i)) + { + if (CNetChan* pNetChan = pClient->GetNetChan()) + { + if (strlen(pNetChan->GetName()) > 0) + { + if (svPlayerName.compare(pNetChan->GetName()) == NULL) // Our wanted name? + NET_DisconnectClient(pClient, i, "Kicked from server", 0, true); + } + } + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: kicks a player by given handle or id +// Input : &svHandle - +//----------------------------------------------------------------------------- +void CBanSystem::KickPlayerById(const string& svHandle) +{ + if (svHandle.empty()) + return; + + try + { + bool bOnlyDigits = StringIsDigit(svHandle); + for (int i = 0; i < MAX_PLAYERS; i++) + { + CClient* pClient = g_pClient->GetClient(i); + if (!pClient) + continue; + + CNetChan* pNetChan = pClient->GetNetChan(); + if (!pNetChan) + continue; + + if (bOnlyDigits) + { + uint64_t nTargetID = static_cast(std::stoll(svHandle)); + if (nTargetID > MAX_PLAYERS) // Is it a possible nucleusID? + { + uint64_t nNucleusID = pClient->GetNucleusID(); + if (nNucleusID != nTargetID) + continue; + } + else // If its not try by handle. + { + uint64_t nClientID = static_cast(pClient->GetHandle()); + if (nClientID != nTargetID) + continue; + } + + NET_DisconnectClient(pClient, i, "Kicked from server", 0, true); + } + else + { + if (svHandle.compare(pNetChan->GetAddress()) != NULL) + continue; + + NET_DisconnectClient(pClient, i, "Kicked from server", 0, true); + } + } + } + catch (const std::exception& e) + { + Error(eDLL_T::SERVER, NO_ERROR, "%s - %s", __FUNCTION__, e.what()); + return; + } +} + +//----------------------------------------------------------------------------- +// Purpose: bans a player by given name +// Input : &svPlayerName - +//----------------------------------------------------------------------------- +void CBanSystem::BanPlayerByName(const string& svPlayerName) +{ + if (svPlayerName.empty()) + return; + + bool bSave = false; + + for (int i = 0; i < MAX_PLAYERS; i++) + { + if (CClient* pClient = g_pClient->GetClient(i)) + { + if (CNetChan* pNetChan = pClient->GetNetChan()) + { + if (strlen(pNetChan->GetName()) > 0) + { + if (svPlayerName.compare(pNetChan->GetName()) == NULL) // Our wanted name? + { + if (AddEntry(pNetChan->GetAddress(), pClient->GetNucleusID()) && !bSave) + bSave = true; + + NET_DisconnectClient(pClient, i, "Banned from server", 0, true); + } + } + } + } + } + + if (bSave) + Save(); +} + +//----------------------------------------------------------------------------- +// Purpose: bans a player by given handle or id +// Input : &svHandle - +//----------------------------------------------------------------------------- +void CBanSystem::BanPlayerById(const string& svHandle) +{ + if (svHandle.empty()) + return; + + try + { + bool bOnlyDigits = StringIsDigit(svHandle); + bool bSave = false; + + for (int i = 0; i < MAX_PLAYERS; i++) + { + CClient* pClient = g_pClient->GetClient(i); + if (!pClient) + continue; + + CNetChan* pNetChan = pClient->GetNetChan(); + if (!pNetChan) + continue; + + if (bOnlyDigits) + { + uint64_t nTargetID = static_cast(std::stoll(svHandle)); + if (nTargetID > static_cast(MAX_PLAYERS)) // Is it a possible nucleusID? + { + uint64_t nNucleusID = pClient->GetNucleusID(); + if (nNucleusID != nTargetID) + continue; + } + else // If its not try by handle. + { + uint64_t nClientID = static_cast(pClient->GetHandle()); + if (nClientID != nTargetID) + continue; + } + + if (AddEntry(pNetChan->GetAddress(), pClient->GetNucleusID()) && !bSave) + bSave = true; + + Save(); + NET_DisconnectClient(pClient, i, "Banned from server", 0, true); + } + else + { + if (svHandle.compare(pNetChan->GetAddress()) != NULL) + continue; + + if (AddEntry(pNetChan->GetAddress(), pClient->GetNucleusID()) && !bSave) + bSave = true; + + Save(); + NET_DisconnectClient(pClient, i, "Banned from server", 0, true); + } + } + + if (bSave) + Save(); + } + catch (const std::exception& e) + { + Error(eDLL_T::SERVER, NO_ERROR, "%s - %s", __FUNCTION__, e.what()); + return; + } +} + +//----------------------------------------------------------------------------- +// Purpose: unbans a player by given nucleus id or ip address +// Input : &svCriteria - +//----------------------------------------------------------------------------- +void CBanSystem::UnbanPlayer(const string& svCriteria) +{ + try + { + if (StringIsDigit(svCriteria)) // Check if we have an ip address or nucleus id. + { + if (DeleteEntry("<>", std::stoll(svCriteria))) // Delete ban entry. + { + Save(); // Save modified vector to file. + } + } + else + { + if (DeleteEntry(svCriteria, 0)) // Delete ban entry. + { + Save(); // Save modified vector to file. + } + } + } + catch (const std::exception& e) + { + Error(eDLL_T::SERVER, NO_ERROR, "%s - %s", __FUNCTION__, e.what()); + return; + } +} + /////////////////////////////////////////////////////////////////////////////// CBanSystem* g_pBanSystem = new CBanSystem(); diff --git a/r5dev/networksystem/bansystem.h b/r5dev/networksystem/bansystem.h index 2c8aafc1..0838a93e 100644 --- a/r5dev/networksystem/bansystem.h +++ b/r5dev/networksystem/bansystem.h @@ -18,6 +18,14 @@ public: bool IsRefuseListValid(void) const; bool IsBanListValid(void) const; + void KickPlayerByName(const string& svPlayerName); + void KickPlayerById(const string& svHandle); + + void BanPlayerByName(const string& svPlayerName); + void BanPlayerById(const string& svHandle); + + void UnbanPlayer(const string& svCriteria); + private: vector> m_vRefuseList = {}; vector> m_vBanList = {}; diff --git a/r5dev/public/iconvar.h b/r5dev/public/iconvar.h index e1b90f74..5d00d029 100644 --- a/r5dev/public/iconvar.h +++ b/r5dev/public/iconvar.h @@ -39,7 +39,7 @@ class CCommand; // If a change is requested it must come from the console (i.e., no remote client changes) // If a value is changed while a server is active, it's replicated to all connected clients #define FCVAR_REPLICATED (1<<13) // server setting enforced on clients, TODO rename to FCAR_SERVER at some time -#define FCVAR_CHEAT (1<<14) // Only useable in singleplayer / debug / multiplayer & sv_cheats +#define FCVAR_CHEAT (1<<14) // Only usable in singleplayer / debug / multiplayer & sv_cheats #define FCVAR_SS (1<<15) // causes varnameN where N == 2 through max splitscreen slots for mod to be autogenerated #define FCVAR_DEMO (1<<16) // record this cvar when starting a demo file #define FCVAR_DONTRECORD (1<<17) // don't record these command in demofiles diff --git a/r5dev/squirrel/sqinit.cpp b/r5dev/squirrel/sqinit.cpp index 505d6818..70f64530 100644 --- a/r5dev/squirrel/sqinit.cpp +++ b/r5dev/squirrel/sqinit.cpp @@ -22,6 +22,9 @@ #include "squirrel/sqapi.h" #include "squirrel/sqinit.h" #include "networksystem/pylon.h" +#ifndef CLIENT_DLL +#include "networksystem/bansystem.h" +#endif // !CLIENT_DLL #ifndef DEDICATED #include "networksystem/listmanager.h" #endif // !DEDICATED @@ -87,7 +90,62 @@ namespace VSquirrel return SQ_OK; } +#ifndef CLIENT_DLL + //----------------------------------------------------------------------------- + // Purpose: kicks a player by given name + //----------------------------------------------------------------------------- + SQRESULT KickPlayerByName(HSQUIRRELVM v) + { + SQChar* szName = sq_getstring(v, 1); + g_pBanSystem->KickPlayerByName(szName); + return SQ_OK; + } + + //----------------------------------------------------------------------------- + // Purpose: kicks a player by given handle or id + //----------------------------------------------------------------------------- + SQRESULT KickPlayerById(HSQUIRRELVM v) + { + SQChar* szHandle = sq_getstring(v, 1); + g_pBanSystem->KickPlayerById(szHandle); + + return SQ_OK; + } + + //----------------------------------------------------------------------------- + // Purpose: bans a player by given name + //----------------------------------------------------------------------------- + SQRESULT BanPlayerByName(HSQUIRRELVM v) + { + SQChar* szName = sq_getstring(v, 1); + g_pBanSystem->BanPlayerByName(szName); + + return SQ_OK; + } + + //----------------------------------------------------------------------------- + // Purpose: bans a player by given handle or id + //----------------------------------------------------------------------------- + SQRESULT BanPlayerById(HSQUIRRELVM v) + { + SQChar* szHandle = sq_getstring(v, 1); + g_pBanSystem->BanPlayerById(szHandle); + + return SQ_OK; + } + + //----------------------------------------------------------------------------- + // Purpose: unbans a player by given nucleus id or ip address + //----------------------------------------------------------------------------- + SQRESULT UnbanPlayer(HSQUIRRELVM v) + { + SQChar* szCriteria = sq_getstring(v, 1); + g_pBanSystem->UnbanPlayer(szCriteria); + + return SQ_OK; + } +#endif // !CLIENT_DLL //----------------------------------------------------------------------------- // Purpose: shutdown local game (host only) //----------------------------------------------------------------------------- diff --git a/r5dev/squirrel/sqinit.h b/r5dev/squirrel/sqinit.h index 7b5cc778..1b4a2a32 100644 --- a/r5dev/squirrel/sqinit.h +++ b/r5dev/squirrel/sqinit.h @@ -23,6 +23,13 @@ namespace VSquirrel SQRESULT GetAvailableMaps(HSQUIRRELVM v); SQRESULT GetAvailablePlaylists(HSQUIRRELVM v); SQRESULT ShutdownHostGame(HSQUIRRELVM v); +#ifndef CLIENT_DLL + SQRESULT KickPlayerByName(HSQUIRRELVM v); + SQRESULT KickPlayerById(HSQUIRRELVM v); + SQRESULT BanPlayerByName(HSQUIRRELVM v); + SQRESULT BanPlayerById(HSQUIRRELVM v); + SQRESULT UnbanPlayer(HSQUIRRELVM v); +#endif // !CLIENT_DLL } #ifndef CLIENT_DLL namespace SERVER diff --git a/r5dev/squirrel/sqscript.cpp b/r5dev/squirrel/sqscript.cpp index 6ba41a46..5a306853 100644 --- a/r5dev/squirrel/sqscript.cpp +++ b/r5dev/squirrel/sqscript.cpp @@ -53,7 +53,15 @@ void Script_RegisterServerFunctions(CSquirrelVM* pSquirrelVM) Script_RegisterFunction(pSquirrelVM, "GetAvailableMaps", "Script_GetAvailableMaps", "Gets an array of all available maps", "array< string >", "", &VSquirrel::SHARED::GetAvailableMaps); Script_RegisterFunction(pSquirrelVM, "GetAvailablePlaylists", "Script_GetAvailablePlaylists", "Gets an array of all available playlists", "array< string >", "", &VSquirrel::SHARED::GetAvailablePlaylists); - Script_RegisterFunction(pSquirrelVM, "ShutdownHostGame", "Script_ShutdownHostGame", "Shuts down the local host game", "void", "", &VSquirrel::SHARED::ShutdownHostGame); + Script_RegisterFunction(pSquirrelVM, "KickPlayerByName", "Script_KickPlayerByName", "Kicks a player from the server by name", "void", "string", &VSquirrel::SHARED::KickPlayerByName); + Script_RegisterFunction(pSquirrelVM, "KickPlayerById", "Script_KickPlayerById", "Kicks a player from the server by handle or nucleus id", "void", "string", &VSquirrel::SHARED::KickPlayerById); + + Script_RegisterFunction(pSquirrelVM, "BanPlayerByName", "Script_BanPlayerByName", "Bans a player from the server by name", "void", "string", &VSquirrel::SHARED::BanPlayerByName); + Script_RegisterFunction(pSquirrelVM, "BanPlayerById", "Script_BanPlayerById", "Bans a player from the server by handle or nucleus id", "void", "string", &VSquirrel::SHARED::BanPlayerById); + + Script_RegisterFunction(pSquirrelVM, "UnbanPlayer", "Script_UnbanPlayer", "Unbans a player from the server by nucleus id or ip address", "void", "string", &VSquirrel::SHARED::UnbanPlayer); + + Script_RegisterFunction(pSquirrelVM, "ShutdownHostGame", "Script_ShutdownHostGame", "Shuts the local host game down", "void", "", &VSquirrel::SHARED::ShutdownHostGame); } #endif // !CLIENT_DLL @@ -70,7 +78,7 @@ void Script_RegisterClientFunctions(CSquirrelVM* pSquirrelVM) Script_RegisterFunction(pSquirrelVM, "GetAvailableMaps", "Script_GetAvailableMaps", "Gets an array of all available maps", "array< string >", "", &VSquirrel::SHARED::GetAvailableMaps); Script_RegisterFunction(pSquirrelVM, "GetAvailablePlaylists", "Script_GetAvailablePlaylists", "Gets an array of all available playlists", "array< string >", "", &VSquirrel::SHARED::GetAvailablePlaylists); - Script_RegisterFunction(pSquirrelVM, "ShutdownHostGame", "Script_ShutdownHostGame", "Shuts down the local host game", "void", "", &VSquirrel::SHARED::ShutdownHostGame); + Script_RegisterFunction(pSquirrelVM, "ShutdownHostGame", "Script_ShutdownHostGame", "Shuts the local host game down", "void", "", &VSquirrel::SHARED::ShutdownHostGame); } //--------------------------------------------------------------------------------- @@ -105,8 +113,16 @@ void Script_RegisterUIFunctions(CSquirrelVM* pSquirrelVM) Script_RegisterFunction(pSquirrelVM, "GetAvailableMaps", "Script_GetAvailableMaps", "Gets an array of all available maps", "array< string >", "", &VSquirrel::SHARED::GetAvailableMaps); Script_RegisterFunction(pSquirrelVM, "GetAvailablePlaylists", "Script_GetAvailablePlaylists", "Gets an array of all available playlists", "array< string >", "", &VSquirrel::SHARED::GetAvailablePlaylists); +#ifndef CLIENT_DLL + Script_RegisterFunction(pSquirrelVM, "KickPlayerByName", "Script_KickPlayerByName", "Kicks a player from the server by name", "void", "string", &VSquirrel::SHARED::KickPlayerByName); + Script_RegisterFunction(pSquirrelVM, "KickPlayerById", "Script_KickPlayerById", "Kicks a player from the server by handle or nucleus id", "void", "string", &VSquirrel::SHARED::KickPlayerById); - Script_RegisterFunction(pSquirrelVM, "ShutdownHostGame", "Script_ShutdownHostGame", "Shuts down the local host game", "void", "", &VSquirrel::SHARED::ShutdownHostGame); + Script_RegisterFunction(pSquirrelVM, "BanPlayerByName", "Script_BanPlayerByName", "Bans a player from the server by name", "void", "string", &VSquirrel::SHARED::BanPlayerByName); + Script_RegisterFunction(pSquirrelVM, "BanPlayerById", "Script_BanPlayerById", "Bans a player from the server by handle or nucleus id", "void", "string", &VSquirrel::SHARED::BanPlayerById); + + Script_RegisterFunction(pSquirrelVM, "UnbanPlayer", "Script_UnbanPlayer", "Unbans a player from the server by nucleus id or ip address", "void", "string", &VSquirrel::SHARED::UnbanPlayer); +#endif // !CLIENT_DLL + Script_RegisterFunction(pSquirrelVM, "ShutdownHostGame", "Script_ShutdownHostGame", "Shuts the local host game down", "void", "", &VSquirrel::SHARED::ShutdownHostGame); } //--------------------------------------------------------------------------------- diff --git a/r5dev/tier1/IConVar.cpp b/r5dev/tier1/IConVar.cpp index 9b66648e..d5db9bc2 100644 --- a/r5dev/tier1/IConVar.cpp +++ b/r5dev/tier1/IConVar.cpp @@ -104,6 +104,8 @@ void ConVar::Init(void) const sv_pylonRefreshInterval = ConVar::Create("sv_pylonRefreshInterval" , "5.0", FCVAR_RELEASE, "Pylon server host request post update interval (seconds).", true, 2.f, true, 8.f, nullptr, nullptr); sv_banlistRefreshInterval = ConVar::Create("sv_banlistRefreshInterval", "1.0", FCVAR_RELEASE, "Banlist refresh interval (seconds).", true, 1.f, false, 0.f, nullptr, nullptr); sv_statusRefreshInterval = ConVar::Create("sv_statusRefreshInterval" , "0.5", FCVAR_RELEASE, "Server status bar update interval (seconds).", false, 0.f, false, 0.f, nullptr, nullptr); + + sv_autoReloadRate = ConVar::Create("sv_autoReloadRate" , "0", FCVAR_RELEASE, "Time in seconds between each server auto-reload (disabled if null). ", true, 0.f, false, 0.f, nullptr, nullptr); #ifdef DEDICATED sv_rcon_debug = ConVar::Create("sv_rcon_debug" , "0" , FCVAR_RELEASE, "Show rcon debug information ( !slower! ).", false, 0.f, false, 0.f, nullptr, nullptr); sv_rcon_sendlogs = ConVar::Create("sv_rcon_sendlogs" , "0" , FCVAR_RELEASE, "Network console logs to connected and authenticated sockets.", false, 0.f, false, 0.f, nullptr, nullptr); @@ -161,9 +163,9 @@ void ConVar::Init(void) const con_notify_native_client_clr = ConVar::Create("con_notify_native_client_clr", "70 70 70 255" , FCVAR_MATERIAL_SYSTEM_THREAD, "Native CLIENT RUI console overlay log color.", false, 1.f, false, 50.f, nullptr, nullptr); con_notify_native_ui_clr = ConVar::Create("con_notify_native_ui_clr" , "200 60 60 255" , FCVAR_MATERIAL_SYSTEM_THREAD, "Native UI RUI console overlay log color.", false, 1.f, false, 50.f, nullptr, nullptr); con_notify_native_engine_clr = ConVar::Create("con_notify_native_engine_clr", "255 255 255 255", FCVAR_MATERIAL_SYSTEM_THREAD, "Native engine RUI console overlay log color.", false, 1.f, false, 50.f, nullptr, nullptr); - con_notify_native_fs_clr = ConVar::Create("con_notify_native_fs_clr" , "0 100 225 255" , FCVAR_MATERIAL_SYSTEM_THREAD, "Native filesystem RUI console overlay log color.", false, 1.f, false, 50.f, nullptr, nullptr); - con_notify_native_rtech_clr = ConVar::Create("con_notify_native_rtech_clr" , "25 100 100 255" , FCVAR_MATERIAL_SYSTEM_THREAD, "Native rtech RUI console overlay log color.", false, 1.f, false, 50.f, nullptr, nullptr); - con_notify_native_ms_clr = ConVar::Create("con_notify_native_ms_clr" , "200 20 180 255" , FCVAR_MATERIAL_SYSTEM_THREAD, "Native materialsystem RUI console overlay log color.", false, 1.f, false, 50.f, nullptr, nullptr); + con_notify_native_fs_clr = ConVar::Create("con_notify_native_fs_clr" , "0 100 225 255" , FCVAR_MATERIAL_SYSTEM_THREAD, "Native FileSystem RUI console overlay log color.", false, 1.f, false, 50.f, nullptr, nullptr); + con_notify_native_rtech_clr = ConVar::Create("con_notify_native_rtech_clr" , "25 100 100 255" , FCVAR_MATERIAL_SYSTEM_THREAD, "Native RTech RUI console overlay log color.", false, 1.f, false, 50.f, nullptr, nullptr); + con_notify_native_ms_clr = ConVar::Create("con_notify_native_ms_clr" , "200 20 180 255" , FCVAR_MATERIAL_SYSTEM_THREAD, "Native MaterialSystem RUI console overlay log color.", false, 1.f, false, 50.f, nullptr, nullptr); con_notify_netcon_clr = ConVar::Create("con_notify_netcon_clr" , "255 255 255 255", FCVAR_MATERIAL_SYSTEM_THREAD, "Net console RUI console overlay log color.", false, 1.f, false, 50.f, nullptr, nullptr); con_notify_common_clr = ConVar::Create("con_notify_common_clr" , "255 140 80 255" , FCVAR_MATERIAL_SYSTEM_THREAD, "Common RUI console overlay log color.", false, 1.f, false, 50.f, nullptr, nullptr); @@ -180,9 +182,9 @@ void ConVar::Init(void) const #endif // !DEDICATED //------------------------------------------------------------------------- // FILESYSTEM | - fs_warning_level_sdk = ConVar::Create("fs_warning_level_sdk" , "0", FCVAR_DEVELOPMENTONLY, "Set the SDK filesystem warning level.", false, 0.f, false, 0.f, nullptr, nullptr); - fs_show_warning_output = ConVar::Create("fs_show_warning_output" , "0", FCVAR_DEVELOPMENTONLY, "Logs the filesystem warnings to the console, filtered by 'fs_warning_level_native' ( !slower! ).", false, 0.f, false, 0.f, nullptr, nullptr); - fs_packedstore_entryblock_stats = ConVar::Create("fs_packedstore_entryblock_stats" , "0", FCVAR_DEVELOPMENTONLY, "If set to 1, prints the stats of each file entry in the VPK during decompression ( !slower! ).", false, 0.f, false, 0.f, nullptr, nullptr); + fs_warning_level_sdk = ConVar::Create("fs_warning_level_sdk" , "0", FCVAR_DEVELOPMENTONLY, "Set the SDK FileSystem warning level.", false, 0.f, false, 0.f, nullptr, nullptr); + fs_show_warning_output = ConVar::Create("fs_show_warning_output" , "0", FCVAR_DEVELOPMENTONLY, "Logs the FileSystem warnings to the console, filtered by 'fs_warning_level_native' ( !slower! ).", false, 0.f, false, 0.f, nullptr, nullptr); + fs_packedstore_entryblock_stats = ConVar::Create("fs_packedstore_entryblock_stats" , "0", FCVAR_DEVELOPMENTONLY, "Logs the stats of each file entry in the VPK during decompression ( !slower! ).", false, 0.f, false, 0.f, nullptr, nullptr); fs_packedstore_workspace = ConVar::Create("fs_packedstore_workspace" , "platform/vpk/", FCVAR_DEVELOPMENTONLY, "Determines the current VPK workspace.", false, 0.f, false, 0.f, nullptr, nullptr); fs_packedstore_compression_level = ConVar::Create("fs_packedstore_compression_level", "default", FCVAR_DEVELOPMENTONLY, "Determines the VPK compression level.", false, 0.f, false, 0.f, nullptr, "fastest faster default better uber"); //------------------------------------------------------------------------- @@ -192,15 +194,15 @@ void ConVar::Init(void) const #endif // !DEDICATED //------------------------------------------------------------------------- // SQUIRREL | - sq_showrsonloading = ConVar::Create("sq_showrsonloading" , "0", FCVAR_DEVELOPMENTONLY, "Logs all 'rson' files loaded by the SQVM ( !slower! ).", false, 0.f, false, 0.f, nullptr, nullptr); + sq_showrsonloading = ConVar::Create("sq_showrsonloading" , "0", FCVAR_DEVELOPMENTONLY, "Logs all RSON files loaded by the SQVM ( !slower! ).", false, 0.f, false, 0.f, nullptr, nullptr); sq_showscriptloading = ConVar::Create("sq_showscriptloading", "0", FCVAR_DEVELOPMENTONLY, "Logs all scripts loaded by the SQVM to be pre-compiled ( !slower! ).", false, 0.f, false, 0.f, nullptr, nullptr); - sq_showvmoutput = ConVar::Create("sq_showvmoutput" , "0", FCVAR_RELEASE, "Prints the VM output to the console.", false, 0.f, false, 0.f, nullptr, "1 = Log to file. 2 = 1 + log to game console. 3 = 1 + 2 + log to overhead console."); - sq_showvmwarning = ConVar::Create("sq_showvmwarning" , "0", FCVAR_RELEASE, "Prints the VM warning output to the console.", false, 0.f, false, 0.f, nullptr, "1 = Log to file. 2 = 1 + log to game console and overhead console."); + sq_showvmoutput = ConVar::Create("sq_showvmoutput" , "0", FCVAR_RELEASE, "Prints the VM output to the console ( !slower! ).", false, 0.f, false, 0.f, nullptr, "1 = Log to file. 2 = 1 + log to game console. 3 = 1 + 2 + log to overhead console."); + sq_showvmwarning = ConVar::Create("sq_showvmwarning" , "0", FCVAR_RELEASE, "Prints the VM warning output to the console ( !slower! ).", false, 0.f, false, 0.f, nullptr, "1 = Log to file. 2 = 1 + log to game console and overhead console."); //------------------------------------------------------------------------- // NETCHANNEL | - net_tracePayload = ConVar::Create("net_tracePayload" , "0", FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT , "Log the payload of the send/recv datagram to a file on the disk.", false, 0.f, false, 0.f, nullptr, nullptr); - net_encryptionEnable = ConVar::Create("net_encryptionEnable" , "1", FCVAR_DEVELOPMENTONLY | FCVAR_REPLICATED , "Use AES encryption on game packets.", false, 0.f, false, 0.f, nullptr, nullptr); - net_useRandomKey = ConVar::Create("net_useRandomKey" , "1" , FCVAR_RELEASE , "Use random AES encryption key for game packets.", false, 0.f, false, 0.f, &NET_UseRandomKeyChanged_f, nullptr); + net_tracePayload = ConVar::Create("net_tracePayload" , "0", FCVAR_DEVELOPMENTONLY , "Log the payload of the send/recv datagram to a file on the disk.", false, 0.f, false, 0.f, nullptr, nullptr); + net_encryptionEnable = ConVar::Create("net_encryptionEnable" , "1", FCVAR_DEVELOPMENTONLY | FCVAR_REPLICATED , "Use AES encryption on game packets.", false, 0.f, false, 0.f, nullptr, nullptr); + net_useRandomKey = ConVar::Create("net_useRandomKey" , "1" , FCVAR_RELEASE , "Use random AES encryption key for game packets.", false, 0.f, false, 0.f, &NET_UseRandomKeyChanged_f, nullptr); //------------------------------------------------------------------------- // NETWORKSYSTEM | pylon_matchmaking_hostname = ConVar::Create("pylon_matchmaking_hostname", "ms.r5reloaded.com", FCVAR_RELEASE , "Holds the pylon matchmaking hostname.", false, 0.f, false, 0.f, &MP_HostName_Changed_f, nullptr); diff --git a/r5dev/tier1/cmd.cpp b/r5dev/tier1/cmd.cpp index 500ac32a..2b4d9c8a 100644 --- a/r5dev/tier1/cmd.cpp +++ b/r5dev/tier1/cmd.cpp @@ -247,7 +247,7 @@ int CCommand::MaxCommandLength(void) const //----------------------------------------------------------------------------- bool CCommand::HasOnlyDigits(int nIndex) const { - string svString = Arg(nIndex); + const string svString = Arg(nIndex); for (const char& character : svString) { if (std::isdigit(character) == 0) @@ -336,10 +336,10 @@ void ConCommand::Init(void) // SERVER DLL | #ifndef CLIENT_DLL ConCommand::Create("script", "Run input code as SERVER script on the VM.", FCVAR_GAMEDLL | FCVAR_CHEAT, SQVM_ServerScript_f, nullptr); - ConCommand::Create("sv_kick", "Kick a client from the server by user name. | Usage: sv_kick \"\".", FCVAR_GAMEDLL | FCVAR_RELEASE, Host_Kick_f, nullptr); - ConCommand::Create("sv_kickid", "Kick a client from the server by handle or nucleus id | Usage: sv_kickid \"\"/\"\".", FCVAR_GAMEDLL | FCVAR_RELEASE, Host_KickID_f, nullptr); - ConCommand::Create("sv_ban", "Bans a client from the server by user name. | Usage: sv_ban .", FCVAR_GAMEDLL | FCVAR_RELEASE, Host_Ban_f, nullptr); - ConCommand::Create("sv_banid", "Bans a client from the server by handle, nucleus id or ip address | Usage: sv_banid \"\"/\"/\".", FCVAR_GAMEDLL | FCVAR_RELEASE, Host_BanID_f, nullptr); + ConCommand::Create("sv_kick", "Kick a client from the server by user name. | Usage: sv_kick \"\".", FCVAR_RELEASE, Host_Kick_f, nullptr); + ConCommand::Create("sv_kickid", "Kick a client from the server by handle or nucleus id | Usage: sv_kickid \"\"/\"\".", FCVAR_RELEASE, Host_KickID_f, nullptr); + ConCommand::Create("sv_ban", "Bans a client from the server by user name. | Usage: sv_ban .", FCVAR_RELEASE, Host_Ban_f, nullptr); + ConCommand::Create("sv_banid", "Bans a client from the server by handle, nucleus id or ip address | Usage: sv_banid \"\"/\"/\".", FCVAR_RELEASE, Host_BanID_f, nullptr); ConCommand::Create("sv_unban", "Unbans a client from the server by nucleus id or ip address | Usage: sv_unban \"\"/\"\".", FCVAR_RELEASE, Host_Unban_f, nullptr); ConCommand::Create("sv_reloadbanlist", "Reloads the banned list.", FCVAR_RELEASE, Host_ReloadBanList_f, nullptr); #endif // !CLIENT_DLL @@ -382,6 +382,7 @@ void ConCommand::InitShipped(void) ///------------------------------------------------------ [ CALLBACK SWAP ] //------------------------------------------------------------------------- // ENGINE DLL | + ConCommand* migrateme = g_pCVar->FindCommand("migrateme"); ConCommand* help = g_pCVar->FindCommand("help"); ConCommand* changelevel = g_pCVar->FindCommand("changelevel"); ConCommand* convar_list = g_pCVar->FindCommand("convar_list"); @@ -421,6 +422,7 @@ void ConCommand::InitShipped(void) "launchplaylist", "quit", "exit", + "reload", "restart", "status", "version", @@ -434,6 +436,7 @@ void ConCommand::InitShipped(void) } } + migrateme->RemoveFlags(FCVAR_SERVER_CAN_EXECUTE); help->RemoveFlags(FCVAR_DEVELOPMENTONLY); changelevel->RemoveFlags(FCVAR_DEVELOPMENTONLY); convar_list->RemoveFlags(FCVAR_DEVELOPMENTONLY); diff --git a/r5dev/tier1/cvar.cpp b/r5dev/tier1/cvar.cpp index a6b0b0cb..9a0a19f2 100644 --- a/r5dev/tier1/cvar.cpp +++ b/r5dev/tier1/cvar.cpp @@ -67,6 +67,8 @@ ConVar* sv_pylonRefreshInterval = nullptr; ConVar* sv_banlistRefreshInterval = nullptr; ConVar* sv_statusRefreshInterval = nullptr; +ConVar* sv_autoReloadRate = nullptr; + #ifdef DEDICATED ConVar* sv_rcon_debug = nullptr; ConVar* sv_rcon_sendlogs = nullptr; diff --git a/r5dev/tier1/cvar.h b/r5dev/tier1/cvar.h index d1a97721..f585a45f 100644 --- a/r5dev/tier1/cvar.h +++ b/r5dev/tier1/cvar.h @@ -63,6 +63,8 @@ extern ConVar* sv_pylonRefreshInterval; extern ConVar* sv_banlistRefreshInterval; extern ConVar* sv_statusRefreshInterval; +extern ConVar* sv_autoReloadRate; + #ifdef DEDICATED extern ConVar* sv_rcon_debug; extern ConVar* sv_rcon_sendlogs; diff --git a/r5dev/vstdlib/callback.cpp b/r5dev/vstdlib/callback.cpp index 4aecba86..3464aee1 100644 --- a/r5dev/vstdlib/callback.cpp +++ b/r5dev/vstdlib/callback.cpp @@ -96,7 +96,7 @@ void ServerBrowser_Invoke_f(const CCommand& args) g_pBrowser->m_bActivate = !g_pBrowser->m_bActivate; } #endif // !DEDICATED - +#ifndef CLIENT_DLL /* ===================== Host_Kick_f @@ -109,24 +109,9 @@ void Host_Kick_f(const CCommand& args) return; } - for (int i = 0; i < MAX_PLAYERS; i++) - { - if (CClient* pClient = g_pClient->GetClient(i)) - { - if (CNetChan* pNetChan = pClient->GetNetChan()) - { - if (strlen(pNetChan->GetName()) > 0) - { - if (strcmp(args.Arg(1), pNetChan->GetName()) == NULL) // Our wanted name? - { - NET_DisconnectClient(pClient, i, "Kicked from server", 0, true); - } - } - } - } - } + g_pBanSystem->KickPlayerByName(args.Arg(1)); } -#ifndef CLIENT_DLL + /* ===================== Host_KickID_f @@ -139,57 +124,7 @@ void Host_KickID_f(const CCommand& args) return; } - try - { - bool bOnlyDigits = args.HasOnlyDigits(1); - for (int i = 0; i < MAX_PLAYERS; i++) - { - CClient* pClient = g_pClient->GetClient(i); - if (!pClient) - continue; - - CNetChan* pNetChan = pClient->GetNetChan(); - if (!pNetChan) - continue; - - if (bOnlyDigits) - { - uint64_t nTargetID = static_cast(std::stoll(args.Arg(1))); - if (nTargetID > MAX_PLAYERS) // Is it a possible nucleusID? - { - uint64_t nNucleusID = pClient->GetNucleusID(); - if (nNucleusID != nTargetID) - { - continue; - } - } - else // If its not try by handle. - { - uint64_t nClientID = static_cast(pClient->GetHandle()); - if (nClientID != nTargetID) - { - continue; - } - } - - NET_DisconnectClient(pClient, i, "Kicked from server", 0, true); - } - else - { - if (strcmp(args.Arg(1), pNetChan->GetAddress()) != NULL) - { - continue; - } - - NET_DisconnectClient(pClient, i, "Kicked from server", 0, true); - } - } - } - catch (const std::exception& e) - { - Error(eDLL_T::SERVER, NO_ERROR, "%s - %s", __FUNCTION__, e.what()); - return; - } + g_pBanSystem->KickPlayerById(args.Arg(1)); } /* @@ -204,33 +139,7 @@ void Host_Ban_f(const CCommand& args) return; } - bool bSave = false; - - for (int i = 0; i < MAX_PLAYERS; i++) - { - if (CClient* pClient = g_pClient->GetClient(i)) - { - if (CNetChan* pNetChan = pClient->GetNetChan()) - { - if (strlen(pNetChan->GetName()) > 0) - { - if (strcmp(args.Arg(1), pNetChan->GetName()) == NULL) // Our wanted name? - { - if (g_pBanSystem->AddEntry(pNetChan->GetAddress(), pClient->GetNucleusID()) && !bSave) - { - bSave = true; - } - NET_DisconnectClient(pClient, i, "Banned from server", 0, true); - } - } - } - } - } - - if (bSave) - { - g_pBanSystem->Save(); - } + g_pBanSystem->BanPlayerByName(args.Arg(1)); } /* @@ -243,64 +152,7 @@ void Host_BanID_f(const CCommand& args) if (args.ArgC() < 2) return; - try - { - bool bOnlyDigits = args.HasOnlyDigits(1); - bool bSave = false; - - for (int i = 0; i < MAX_PLAYERS; i++) - { - CClient* pClient = g_pClient->GetClient(i); - if (!pClient) - continue; - - CNetChan* pNetChan = pClient->GetNetChan(); - if (!pNetChan) - continue; - - if (bOnlyDigits) - { - uint64_t nTargetID = static_cast(std::stoll(args.Arg(1))); - if (nTargetID > static_cast(MAX_PLAYERS)) // Is it a possible nucleusID? - { - uint64_t nNucleusID = pClient->GetNucleusID(); - if (nNucleusID != nTargetID) - continue; - } - else // If its not try by handle. - { - uint64_t nClientID = static_cast(pClient->GetHandle()); - if (nClientID != nTargetID) - continue; - } - - if (g_pBanSystem->AddEntry(pNetChan->GetAddress(), pClient->GetNucleusID()) && !bSave) - bSave = true; - - g_pBanSystem->Save(); - NET_DisconnectClient(pClient, i, "Banned from server", 0, true); - } - else - { - if (strcmp(args.Arg(1), pNetChan->GetAddress()) != NULL) - continue; - - if (g_pBanSystem->AddEntry(pNetChan->GetAddress(), pClient->GetNucleusID()) && !bSave) - bSave = true; - - g_pBanSystem->Save(); - NET_DisconnectClient(pClient, i, "Banned from server", 0, true); - } - } - - if (bSave) - g_pBanSystem->Save(); - } - catch (const std::exception& e) - { - Error(eDLL_T::SERVER, NO_ERROR, "%s - %s", __FUNCTION__, e.what()); - return; - } + g_pBanSystem->BanPlayerById(args.Arg(1)); } /* @@ -315,47 +167,7 @@ void Host_Unban_f(const CCommand& args) return; } - try - { - if (args.HasOnlyDigits(1)) // Check if we have an ip address or nucleus id. - { - if (g_pBanSystem->DeleteEntry("noIP", std::stoll(args.Arg(1)))) // Delete ban entry. - { - g_pBanSystem->Save(); // Save modified vector to file. - } - } - else - { - if (g_pBanSystem->DeleteEntry(args.Arg(1), 0)) // Delete ban entry. - { - g_pBanSystem->Save(); // Save modified vector to file. - } - } - } - catch (const std::exception& e) - { - Error(eDLL_T::SERVER, NO_ERROR, "%s - %s", __FUNCTION__, e.what()); - return; - } -} - -/* -===================== -Host_Changelevel_f - - Goes to a new map, - taking all clients along -===================== -*/ -void Host_Changelevel_f(const CCommand& args) -{ - if (args.ArgC() >= 2 - && IsOriginInitialized() - && g_pServer->IsActive()) - { - v_SetLaunchOptions(args); - v_HostState_ChangeLevelMP(args[1], args[2]); - } + g_pBanSystem->UnbanPlayer(args.Arg(1)); } /* @@ -379,6 +191,25 @@ void Host_ReloadPlaylists_f(const CCommand& args) KeyValues::InitPlaylists(); // Re-Init playlist. } +/* +===================== +Host_Changelevel_f + + Goes to a new map, + taking all clients along +===================== +*/ +void Host_Changelevel_f(const CCommand& args) +{ + if (args.ArgC() >= 2 + && IsOriginInitialized() + && g_pServer->IsActive()) + { + v_SetLaunchOptions(args); + v_HostState_ChangeLevelMP(args[1], args[2]); + } +} + #endif // !CLIENT_DLL /* ===================== diff --git a/r5dev/vstdlib/callback.h b/r5dev/vstdlib/callback.h index 19d43611..a6b8016b 100644 --- a/r5dev/vstdlib/callback.h +++ b/r5dev/vstdlib/callback.h @@ -21,9 +21,9 @@ void Host_KickID_f(const CCommand& args); void Host_Ban_f(const CCommand& args); void Host_BanID_f(const CCommand& args); void Host_Unban_f(const CCommand& args); -void Host_Changelevel_f(const CCommand& args); void Host_ReloadBanList_f(const CCommand& args); void Host_ReloadPlaylists_f(const CCommand& args); +void Host_Changelevel_f(const CCommand& args); #endif // !CLIENT_DLL void Pak_ListPaks_f(const CCommand& args); void Pak_RequestUnload_f(const CCommand& args);