diff --git a/src/common/callback.cpp b/src/common/callback.cpp index efb08a01..d353307f 100644 --- a/src/common/callback.cpp +++ b/src/common/callback.cpp @@ -94,154 +94,7 @@ void MP_HostName_Changed_f(IConVar* pConVar, const char* pOldString, float flOld #endif // !DEDICATED } -#ifndef DEDICATED -/* -===================== -ToggleConsole_f -===================== -*/ -void ToggleConsole_f(const CCommand& args) -{ - g_Console.m_bActivate ^= true; - ResetInput(); // Disable input to game when console is drawn. -} - -/* -===================== -ToggleBrowser_f -===================== -*/ -void ToggleBrowser_f(const CCommand& args) -{ - g_Browser.m_bActivate ^= true; - ResetInput(); // Disable input to game when browser is drawn. -} -#endif // !DEDICATED #ifndef CLIENT_DLL -/* -===================== -Host_Kick_f - - helper function for - bansystem -===================== -*/ -void _Author_Client_f(const CCommand& args, EKickType type) -{ - if (args.ArgC() < 2) - { - return; - } - - const char* szReason = args.ArgC() > 2 ? args.Arg(2) : nullptr; - - switch(type) - { - case KICK_NAME: - { - g_BanSystem.KickPlayerByName(args.Arg(1), szReason); - break; - } - case KICK_ID: - { - g_BanSystem.KickPlayerById(args.Arg(1), szReason); - break; - } - case BAN_NAME: - { - g_BanSystem.BanPlayerByName(args.Arg(1), szReason); - break; - } - case BAN_ID: - { - g_BanSystem.BanPlayerById(args.Arg(1), szReason); - break; - } - default: - { - // Code bug. - Assert(0); - } - } -} - - -/* -===================== -Host_Kick_f -===================== -*/ -void Host_Kick_f(const CCommand& args) -{ - _Author_Client_f(args, EKickType::KICK_NAME); -} - -/* -===================== -Host_KickID_f -===================== -*/ -void Host_KickID_f(const CCommand& args) -{ - _Author_Client_f(args, EKickType::KICK_ID); -} - -/* -===================== -Host_Ban_f -===================== -*/ -void Host_Ban_f(const CCommand& args) -{ - _Author_Client_f(args, EKickType::BAN_NAME); -} - -/* -===================== -Host_BanID_f -===================== -*/ -void Host_BanID_f(const CCommand& args) -{ - _Author_Client_f(args, EKickType::BAN_ID); -} - -/* -===================== -Host_Unban_f -===================== -*/ -void Host_Unban_f(const CCommand& args) -{ - if (args.ArgC() < 2) - { - return; - } - - g_BanSystem.UnbanPlayer(args.Arg(1)); -} - -/* -===================== -Host_ReloadBanList_f -===================== -*/ -void Host_ReloadBanList_f(const CCommand& args) -{ - g_BanSystem.LoadList(); // Reload banned list. -} - -/* -===================== -Host_ReloadPlaylists_f -===================== -*/ -void Host_ReloadPlaylists_f(const CCommand& args) -{ - v__DownloadPlaylists_f(); - Playlists_SDKInit(); // Re-Init playlist. -} - /* ===================== Host_Changelevel_f @@ -265,267 +118,7 @@ void Host_Changelevel_f(const CCommand& args) v_HostState_ChangeLevelMP(levelName, landMarkName); } } - -/* -===================== -Detour_HotSwap_f - - Hot swaps the NavMesh - while the game is running -===================== -*/ -void Detour_HotSwap_f(const CCommand& args) -{ - if (!g_pServer->IsActive()) - return; // Only execute if server is initialized and active. - - Msg(eDLL_T::SERVER, "Executing NavMesh hot swap for level '%s'\n", - g_ServerGlobalVariables->m_pszMapName); - - CFastTimer timer; - - timer.Start(); - Detour_HotSwap(); - - timer.End(); - Msg(eDLL_T::SERVER, "Hot swap took '%lf' seconds\n", timer.GetDuration().GetSeconds()); -} #endif // !CLIENT_DLL -/* -===================== -Pak_ListPaks_f -===================== -*/ -void Pak_ListPaks_f(const CCommand& args) -{ - Msg(eDLL_T::RTECH, "| id | name | status | asset count |\n"); - Msg(eDLL_T::RTECH, "|------|----------------------------------------------------|--------------------------------------|-------------|\n"); - - uint32_t nTotalLoaded = 0; - - for (int16_t i = 0, n = g_pakGlobals->loadedPakCount; i < n; ++i) - { - const PakLoadedInfo_t& info = g_pakGlobals->loadedPaks[i]; - - if (info.status == EPakStatus::PAK_STATUS_FREED) - continue; - - const char* szRpakStatus = Pak_StatusToString(info.status); - - // todo: make status into a string from an array/vector - Msg(eDLL_T::RTECH, "| %04i | %-50s | %-36s | %11i |\n", info.handle, info.fileName, szRpakStatus, info.assetCount); - nTotalLoaded++; - } - Msg(eDLL_T::RTECH, "|------|----------------------------------------------------|--------------------------------------|-------------|\n"); - Msg(eDLL_T::RTECH, "| %18i loaded paks. |\n", nTotalLoaded); - Msg(eDLL_T::RTECH, "|------|----------------------------------------------------|--------------------------------------|-------------|\n"); -} - -/* -===================== -Pak_ListTypes_f -===================== -*/ -void Pak_ListTypes_f(const CCommand& args) -{ - Msg(eDLL_T::RTECH, "| ext | description | version | header size | native size |\n"); - Msg(eDLL_T::RTECH, "|------|---------------------------|---------|-------------|-------------|\n"); - - uint32_t nRegistered = 0; - - for (int8_t i = 0; i < PAK_MAX_TYPES; ++i) - { - PakAssetBinding_t* type = &g_pakGlobals->assetBindings[i]; - - if (!type->description) - continue; - - FourCCString_t assetExtension; - FourCCToString(assetExtension, type->extension); - - Msg(eDLL_T::RTECH, "| %-4s | %-25s | %7i | %11i | %11i |\n", assetExtension, type->description, type->version, type->headerSize, type->nativeClassSize); - nRegistered++; - } - Msg(eDLL_T::RTECH, "|------|---------------------------|---------|-------------|-------------|\n"); - Msg(eDLL_T::RTECH, "| %18i registered types. |\n", nRegistered); - Msg(eDLL_T::RTECH, "|------|---------------------------|---------|-------------|-------------|\n"); -} - -/* -===================== -Pak_RequestUnload_f -===================== -*/ -void Pak_RequestUnload_f(const CCommand& args) -{ - if (args.ArgC() < 2) - { - return; - } - - if (args.HasOnlyDigits(1)) - { - const PakHandle_t pakHandle = atoi(args.Arg(1)); - const PakLoadedInfo_t* const pakInfo = Pak_GetPakInfo(pakHandle); - - if (!pakInfo) - { - Warning(eDLL_T::RTECH, "Found no pak entry for specified handle.\n"); - return; - } - - Msg(eDLL_T::RTECH, "Requested pak unload for handle '%d'\n", pakHandle); - g_pakLoadApi->UnloadAsync(pakHandle); - } - else - { - const PakLoadedInfo_t* const pakInfo = Pak_GetPakInfo(args.Arg(1)); - if (!pakInfo) - { - Warning(eDLL_T::RTECH, "Found no pak entry for specified name.\n"); - return; - } - - Msg(eDLL_T::RTECH, "Requested pak unload for file '%s'\n", args.Arg(1)); - g_pakLoadApi->UnloadAsync(pakInfo->handle); - } -} - -/* -===================== -Pak_RequestLoad_f -===================== -*/ -void Pak_RequestLoad_f(const CCommand& args) -{ - g_pakLoadApi->LoadAsync(args.Arg(1), AlignedMemAlloc(), NULL, 0); -} - - -/* -===================== -Pak_Swap_f -===================== -*/ -void Pak_Swap_f(const CCommand& args) -{ - if (args.ArgC() < 2) - { - return; - } - - const char* pakName = nullptr; - - PakHandle_t pakHandle = INVALID_PAK_HANDLE; - const PakLoadedInfo_t* pakInfo = nullptr; - - if (args.HasOnlyDigits(1)) - { - pakHandle = atoi(args.Arg(1)); - pakInfo = Pak_GetPakInfo(pakHandle); - - if (!pakInfo) - { - Warning(eDLL_T::RTECH, "Found no pak entry for specified handle.\n"); - return; - } - - pakName = pakInfo->fileName; - } - else - { - pakName = args.Arg(1); - pakInfo = Pak_GetPakInfo(pakName); - - if (!pakInfo) - { - Warning(eDLL_T::RTECH, "Found no pak entry for specified name.\n"); - return; - } - - pakHandle = pakInfo->handle; - } - - Msg(eDLL_T::RTECH, "Requested pak swap for handle '%d'\n", pakHandle); - g_pakLoadApi->UnloadAsync(pakHandle); - - while (pakInfo->status != EPakStatus::PAK_STATUS_FREED) // Wait till this slot gets free'd. - std::this_thread::sleep_for(std::chrono::seconds(1)); - - g_pakLoadApi->LoadAsync(pakName, AlignedMemAlloc(), NULL, 0); -} - -/* -===================== -RTech_StringToGUID_f -===================== -*/ -void Pak_StringToGUID_f(const CCommand& args) -{ - if (args.ArgC() < 2) - { - return; - } - - unsigned long long guid = Pak_StringToGuid(args.Arg(1)); - - Msg(eDLL_T::RTECH, "______________________________________________________________\n"); - Msg(eDLL_T::RTECH, "] RTECH_HASH ]------------------------------------------------\n"); - Msg(eDLL_T::RTECH, "] GUID: '0x%llX'\n", guid); -} - -/* -===================== -RTech_Decompress_f - - Decompresses input RPak file and - dumps results to override path -===================== -*/ -void Pak_Decompress_f(const CCommand& args) -{ - if (args.ArgC() < 2) - { - return; - } - - CFmtStr1024 inPakFile(PLATFORM_PAK_PATH "%s", args.Arg(1)); - CFmtStr1024 outPakFile(PLATFORM_PAK_OVERRIDE_PATH "%s", args.Arg(1)); - - if (!Pak_DecodePakFile(inPakFile.String(), outPakFile.String())) - { - Error(eDLL_T::RTECH, NO_ERROR, "%s - decompression failed for '%s'!\n", - __FUNCTION__, inPakFile.String()); - } -} - -/* -===================== -RTech_Compress_f - - Compresses input RPak file and - dumps results to base path -===================== -*/ -void Pak_Compress_f(const CCommand& args) -{ - if (args.ArgC() < 2) - { - return; - } - - CFmtStr1024 inPakFile(PLATFORM_PAK_OVERRIDE_PATH "%s", args.Arg(1)); - CFmtStr1024 outPakFile(PLATFORM_PAK_PATH "%s", args.Arg(1)); - - // NULL means default compress level - const int compressLevel = args.ArgC() > 2 ? atoi(args.Arg(2)) : NULL; - - if (!Pak_EncodePakFile(inPakFile.String(), outPakFile.String(), compressLevel)) - { - Error(eDLL_T::RTECH, NO_ERROR, "%s - compression failed for '%s'!\n", - __FUNCTION__, inPakFile.String()); - } -} /* ===================== @@ -641,35 +234,6 @@ void VPK_Unmount_f(const CCommand& args) FileSystem()->UnmountVPKFile(args.Arg(1)); } -/* -===================== -NET_SetKey_f - - Sets the input netchannel encryption key -===================== -*/ -void NET_SetKey_f(const CCommand& args) -{ - if (args.ArgC() < 2) - { - return; - } - - NET_SetKey(args.Arg(1)); -} - -/* -===================== -NET_GenerateKey_f - - Sets a random netchannel encryption key -===================== -*/ -void NET_GenerateKey_f(const CCommand& args) -{ - NET_GenerateKey(); -} - /* ===================== NET_UseRandomKeyChanged_f @@ -719,206 +283,7 @@ void NET_UseSocketsForLoopbackChanged_f(IConVar* pConVar, const char* pOldString } } -/* -===================== -SIG_GetAdr_f - - Logs the sigscan - results to the console. -===================== -*/ -void SIG_GetAdr_f(const CCommand& args) -{ - if (!IsCert() && !IsRetail()) - DetourAddress(); -} - -/* -===================== -CON_Help_f - - Shows the colors and - description of each - context. -===================== -*/ -void CON_Help_f(const CCommand& args) -{ - Msg(eDLL_T::COMMON, "Contexts:\n"); - SQVM_PrintFunc(reinterpret_cast(SQCONTEXT::SERVER), (SQChar*)(" = Server DLL (Script)\n")); - SQVM_PrintFunc(reinterpret_cast(SQCONTEXT::CLIENT), (SQChar*)(" = Client DLL (Script)\n")); - SQVM_PrintFunc(reinterpret_cast(SQCONTEXT::UI), (SQChar*)(" = UI DLL (Script)\n")); - - Msg(eDLL_T::SERVER, " = Server DLL (Code)\n"); - Msg(eDLL_T::CLIENT, " = Client DLL (Code)\n"); - Msg(eDLL_T::UI, " = UI DLL (Code)\n"); - Msg(eDLL_T::ENGINE, " = Engine DLL (Code)\n"); - Msg(eDLL_T::FS, " = FileSystem (Code)\n"); - Msg(eDLL_T::RTECH, " = PakLoad API (Code)\n"); - Msg(eDLL_T::MS, " = MaterialSystem (Code)\n"); - Msg(eDLL_T::AUDIO, " = Audio DLL (Code)\n"); - Msg(eDLL_T::VIDEO, " = Video DLL (Code)\n"); - Msg(eDLL_T::NETCON, " = NetConsole (Code)\n"); -} - #ifndef DEDICATED -/* -===================== -CON_LogHistory_f - - Shows the game console - submission history. -===================== -*/ -void CON_LogHistory_f(const CCommand& args) -{ - const vector vHistory = g_Console.GetHistory(); - for (size_t i = 0, nh = vHistory.size(); i < nh; i++) - { - Msg(eDLL_T::COMMON, "%3d: %s\n", i, vHistory[i].c_str()); - } -} - -/* -===================== -CON_RemoveLine_f - - Removes a range of lines - from the console. -===================== -*/ -void CON_RemoveLine_f(const CCommand& args) -{ - if (args.ArgC() < 3) - { - Msg(eDLL_T::CLIENT, "Usage 'con_removeline': start(int) end(int)\n"); - return; - } - - int start = atoi(args[1]); - int end = atoi(args[2]); - - g_Console.RemoveLog(start, end); -} - -/* -===================== -CON_ClearLines_f - - Clears all lines from - the developer console. -===================== -*/ -void CON_ClearLines_f(const CCommand& args) -{ - g_Console.ClearLog(); -} - -/* -===================== -CON_ClearHistory_f - - Clears all submissions from the - developer console history. -===================== -*/ -void CON_ClearHistory_f(const CCommand& args) -{ - g_Console.ClearHistory(); -} - -/* -===================== -RCON_CmdQuery_f - - Issues an RCON command to the - RCON server. -===================== -*/ -void RCON_CmdQuery_f(const CCommand& args) -{ - const int64_t argCount = args.ArgC(); - - if (argCount < 2) - { - const char* pszAddress = rcon_address->GetString(); - - if (RCONClient()->IsInitialized() - && !RCONClient()->IsConnected() - && pszAddress[0]) - { - RCONClient()->Connect(pszAddress); - } - } - else - { - if (!RCONClient()->IsInitialized()) - { - Warning(eDLL_T::CLIENT, "Failed to issue command to RCON server: %s\n", "uninitialized"); - return; - } - else if (RCONClient()->IsConnected()) - { - vector vecMsg; - bool bSuccess = false; - const SocketHandle_t hSocket = RCONClient()->GetSocket(); - - if (strcmp(args.Arg(1), "PASS") == 0) // Auth with RCON server using rcon_password ConVar value. - { - if (argCount > 2) - { - bSuccess = RCONClient()->Serialize(vecMsg, args.Arg(2), "", cl_rcon::request_t::SERVERDATA_REQUEST_AUTH); - } - else // Use 'rcon_password' ConVar as password. - { - bSuccess = RCONClient()->Serialize(vecMsg, rcon_password->GetString(), "", cl_rcon::request_t::SERVERDATA_REQUEST_AUTH); - } - - if (bSuccess) - { - RCONClient()->Send(hSocket, vecMsg.data(), int(vecMsg.size())); - } - - return; - } - else if (strcmp(args.Arg(1), "disconnect") == 0) // Disconnect from RCON server. - { - RCONClient()->Disconnect("issued by user"); - return; - } - - bSuccess = RCONClient()->Serialize(vecMsg, args.Arg(1), args.ArgS(), cl_rcon::request_t::SERVERDATA_REQUEST_EXECCOMMAND); - if (bSuccess) - { - RCONClient()->Send(hSocket, vecMsg.data(), int(vecMsg.size())); - } - return; - } - else - { - Warning(eDLL_T::CLIENT, "Failed to issue command to RCON server: %s\n", "unconnected"); - return; - } - } -} - -/* -===================== -RCON_Disconnect_f - - Disconnect from RCON server -===================== -*/ -void RCON_Disconnect_f(const CCommand& args) -{ - const bool bIsConnected = RCONClient()->IsConnected(); - RCONClient()->Disconnect("issued by user"); - - if (bIsConnected) // Log if client was indeed connected. - { - Msg(eDLL_T::CLIENT, "User closed RCON connection\n"); - } -} /* ===================== @@ -1065,55 +430,7 @@ void RCON_ConnectionCountChanged_f(IConVar* pConVar, const char* pOldString, flo } #endif // !CLIENT_DLL -/* -===================== -SQVM_ServerScript_f - - Executes input on the - VM in SERVER context. -===================== -*/ -void SQVM_ServerScript_f(const CCommand& args) -{ - if (args.ArgC() >= 2) - { - Script_Execute(args.ArgS(), SQCONTEXT::SERVER); - } -} - #ifndef DEDICATED -/* -===================== -SQVM_ClientScript_f - - Executes input on the - VM in CLIENT context. -===================== -*/ -void SQVM_ClientScript_f(const CCommand& args) -{ - if (args.ArgC() >= 2) - { - Script_Execute(args.ArgS(), SQCONTEXT::CLIENT); - } -} - -/* -===================== -SQVM_UIScript_f - - Executes input on the - VM in UI context. -===================== -*/ -void SQVM_UIScript_f(const CCommand& args) -{ - if (args.ArgC() >= 2) - { - Script_Execute(args.ArgS(), SQCONTEXT::UI); - } -} - /* ===================== Mat_CrossHair_f @@ -1369,52 +686,6 @@ void CVFlag_f(const CCommand& args) cv->CvarFindFlags_f(args); } -/* -===================== -CC_CreateFakePlayer_f - - Creates a fake player - on the server -===================== -*/ -#ifndef CLIENT_DLL -void CC_CreateFakePlayer_f(const CCommand& args) -{ - if (!g_pServer->IsActive()) - return; - - if (args.ArgC() < 3) - { - Msg(eDLL_T::SERVER, "usage 'sv_addbot': name(string) teamid(int)\n"); - return; - } - - const int numPlayers = g_pServer->GetNumClients(); - - // Already at max, don't create. - if (numPlayers >= g_ServerGlobalVariables->m_nMaxClients) - return; - - const char* playerName = args.Arg(1); - - int teamNum = atoi(args.Arg(2)); - const int maxTeams = int(g_pServer->GetMaxTeams()) + 1; - - // Clamp team count, going above the limit will - // cause a crash. Going below 0 means that the - // engine will assign the bot to the last team. - if (teamNum > maxTeams) - teamNum = maxTeams; - - g_pEngineServer->LockNetworkStringTables(true); - - const edict_t nHandle = g_pEngineServer->CreateFakeClient(playerName, teamNum); - g_pServerGameClients->ClientFullyConnect(nHandle, false); - - g_pEngineServer->LockNetworkStringTables(false); -} -#endif // !CLIENT_DLL - #ifndef DEDICATED static double s_flScriptExecTimeBase = 0.0f; static int s_nScriptExecCount = 0; diff --git a/src/common/callback.h b/src/common/callback.h index eb4493e9..9f57a51c 100644 --- a/src/common/callback.h +++ b/src/common/callback.h @@ -3,35 +3,14 @@ inline bool(*v_SetupGamemode)(const char* pszPlayList); /* ==== CONCOMMANDCALLBACK ============================================================================================================================================== */ -inline void(*v__DownloadPlaylists_f)(void); inline void(*v__Cmd_Exec_f)(const CCommand& args); /////////////////////////////////////////////////////////////////////////////// void MP_GameMode_Changed_f(IConVar* pConVar, const char* pOldString, float flOldValue); void MP_HostName_Changed_f(IConVar* pConVar, const char* pOldString, float flOldValue); -#ifndef DEDICATED -void ToggleConsole_f(const CCommand& args); -void ToggleBrowser_f(const CCommand& args); -#endif // !DEDICATED #ifndef CLIENT_DLL -void Host_Kick_f(const CCommand& args); -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_ReloadBanList_f(const CCommand& args); -void Host_ReloadPlaylists_f(const CCommand& args); void Host_Changelevel_f(const CCommand& args); -void Detour_HotSwap_f(const CCommand& args); #endif // !CLIENT_DLL -void Pak_ListPaks_f(const CCommand& args); -void Pak_ListTypes_f(const CCommand& args); -void Pak_RequestUnload_f(const CCommand& args); -void Pak_RequestLoad_f(const CCommand& args); -void Pak_Swap_f(const CCommand& args); -void Pak_StringToGUID_f(const CCommand& args); -void Pak_Decompress_f(const CCommand& args); -void Pak_Compress_f(const CCommand& args); void VPK_Pack_f(const CCommand& args); void VPK_Unpack_f(const CCommand& args); void VPK_Mount_f(const CCommand& args); @@ -40,16 +19,8 @@ void NET_SetKey_f(const CCommand& args); void NET_GenerateKey_f(const CCommand& args); void NET_UseRandomKeyChanged_f(IConVar* pConVar, const char* pOldString, float flOldValue); void NET_UseSocketsForLoopbackChanged_f(IConVar* pConVar, const char* pOldString, float flOldValue); -void SIG_GetAdr_f(const CCommand& args); -void CON_Help_f(const CCommand& args); #ifndef DEDICATED -void CON_LogHistory_f(const CCommand& args); -void CON_RemoveLine_f(const CCommand& args); -void CON_ClearLines_f(const CCommand& args); -void CON_ClearHistory_f(const CCommand& args); -void RCON_CmdQuery_f(const CCommand& args); -void RCON_Disconnect_f(const CCommand& args); void RCON_InputOnlyChanged_f(IConVar* pConVar, const char* pOldString, float flOldValue); void GFX_NVN_Changed_f(IConVar* pConVar, const char* pOldString, float flOldValue); @@ -84,13 +55,11 @@ class VCallback : public IDetour virtual void GetAdr(void) const { LogFunAdr("SetupGamemode", v_SetupGamemode); - LogFunAdr("DownloadPlaylist_f", v__DownloadPlaylists_f); LogFunAdr("Cmd_Exec_f", v__Cmd_Exec_f); } virtual void GetFun(void) const { g_GameDll.FindPatternSIMD("40 53 48 83 EC 20 48 8B D9 48 C7 C0 ?? ?? ?? ??").GetPtr(v_SetupGamemode); - g_GameDll.FindPatternSIMD("33 C9 C6 05 ?? ?? ?? ?? ?? E9 ?? ?? ?? ??").GetPtr(v__DownloadPlaylists_f); g_GameDll.FindPatternSIMD("40 55 53 48 8D AC 24 ?? ?? ?? ?? B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 2B E0 48 8B D9").GetPtr(v__Cmd_Exec_f); } virtual void GetVar(void) const { } diff --git a/src/common/global.cpp b/src/common/global.cpp index 28fcb7bb..831a8869 100644 --- a/src/common/global.cpp +++ b/src/common/global.cpp @@ -719,79 +719,19 @@ void ConVar_PurgeHostNames(void) } } -//----------------------------------------------------------------------------- -// Purpose: ConCommand registration -//----------------------------------------------------------------------------- -void ConCommand_StaticInit(void) -{ - //------------------------------------------------------------------------- - // ENGINE DLL | - ConCommand::StaticCreate("bhit", "Bullet-hit trajectory debug.", nullptr, FCVAR_DEVELOPMENTONLY | FCVAR_GAMEDLL, BHit_f, nullptr); +static ConCommand bhit("bhit", BHit_f, "Bullet-hit trajectory debug", FCVAR_DEVELOPMENTONLY | FCVAR_GAMEDLL); + #ifndef DEDICATED - ConCommand::StaticCreate("line", "Draw a debug line.", nullptr, FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT, Line_f, nullptr); - ConCommand::StaticCreate("sphere", "Draw a debug sphere.", nullptr, FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT, Sphere_f, nullptr); - ConCommand::StaticCreate("capsule", "Draw a debug capsule.", nullptr, FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT, Capsule_f, nullptr); +static ConCommand line("line", Line_f, "Draw a debug line", FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT); +static ConCommand sphere("sphere", Sphere_f, "Draw a debug sphere", FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT); +static ConCommand capsule("capsule", Capsule_f, "Draw a debug capsule", FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT); #endif //!DEDICATED - ConCommand::StaticCreate("con_help", "Shows the colors and description of each context.", nullptr, FCVAR_RELEASE, CON_Help_f, nullptr); -#ifndef CLIENT_DLL - ConCommand::StaticCreate("reload_playlists", "Reloads the playlists file.", nullptr, FCVAR_RELEASE, Host_ReloadPlaylists_f, nullptr); -#endif // !CLIENT_DLL - //------------------------------------------------------------------------- - // SERVER DLL | -#ifndef CLIENT_DLL - ConCommand::StaticCreate("script", "Run input code as SERVER script on the VM.", nullptr, FCVAR_DEVELOPMENTONLY | FCVAR_GAMEDLL | FCVAR_CHEAT, SQVM_ServerScript_f, nullptr); - ConCommand::StaticCreate("kick", "Kick a client from the server by user name.", "kick \"\"", FCVAR_RELEASE, Host_Kick_f, nullptr); - ConCommand::StaticCreate("kickid", "Kick a client from the server by handle, nucleus id or ip address.", "kickid \"\"/\"/\"", FCVAR_RELEASE, Host_KickID_f, nullptr); - ConCommand::StaticCreate("ban", "Bans a client from the server by user name.", "ban ", FCVAR_RELEASE, Host_Ban_f, nullptr); - ConCommand::StaticCreate("banid", "Bans a client from the server by handle, nucleus id or ip address.", "banid \"\"/\"/\"", FCVAR_RELEASE, Host_BanID_f, nullptr); - ConCommand::StaticCreate("unban", "Unbans a client from the server by nucleus id or ip address.", "unban \"\"/\"\"", FCVAR_RELEASE, Host_Unban_f, nullptr); - ConCommand::StaticCreate("sv_reloadbanlist", "Reloads the banned list.", nullptr, FCVAR_RELEASE, Host_ReloadBanList_f, nullptr); - ConCommand::StaticCreate("sv_addbot", "Creates a bot on the server.", nullptr, FCVAR_RELEASE, CC_CreateFakePlayer_f, nullptr); - ConCommand::StaticCreate("navmesh_hotswap", "Hot swap the NavMesh for all hulls.", nullptr, FCVAR_DEVELOPMENTONLY, Detour_HotSwap_f, nullptr); -#endif // !CLIENT_DLL -#ifndef DEDICATED - //------------------------------------------------------------------------- - // CLIENT DLL | - ConCommand::StaticCreate("script_client", "Run input code as CLIENT script on the VM.", nullptr, FCVAR_DEVELOPMENTONLY| FCVAR_CLIENTDLL | FCVAR_CHEAT, SQVM_ClientScript_f, nullptr); - ConCommand::StaticCreate("rcon", "Forward RCON query to remote server.", "rcon \"\"", FCVAR_CLIENTDLL | FCVAR_RELEASE, RCON_CmdQuery_f, nullptr); - ConCommand::StaticCreate("rcon_disconnect", "Disconnect from RCON server.", nullptr, FCVAR_CLIENTDLL | FCVAR_RELEASE, RCON_Disconnect_f, nullptr); - ConCommand::StaticCreate("con_history", "Shows the developer console submission history.", nullptr, FCVAR_CLIENTDLL | FCVAR_RELEASE, CON_LogHistory_f, nullptr); - ConCommand::StaticCreate("con_removeline", "Removes a range of lines from the developer console.", nullptr, FCVAR_CLIENTDLL | FCVAR_RELEASE, CON_RemoveLine_f, nullptr); - ConCommand::StaticCreate("con_clearlines", "Clears all lines from the developer console.", nullptr, FCVAR_CLIENTDLL | FCVAR_RELEASE, CON_ClearLines_f, nullptr); - ConCommand::StaticCreate("con_clearhistory", "Clears all submissions from the developer console history.", nullptr, FCVAR_CLIENTDLL | FCVAR_RELEASE, CON_ClearHistory_f, nullptr); - - ConCommand::StaticCreate("toggleconsole", "Show/hide the developer console.", nullptr, FCVAR_CLIENTDLL | FCVAR_RELEASE, ToggleConsole_f, nullptr); - ConCommand::StaticCreate("togglebrowser", "Show/hide the server browser.", nullptr, FCVAR_CLIENTDLL | FCVAR_RELEASE, ToggleBrowser_f, nullptr); - //------------------------------------------------------------------------- - // UI DLL | - ConCommand::StaticCreate("script_ui", "Run input code as UI script on the VM.", nullptr, FCVAR_DEVELOPMENTONLY | FCVAR_CLIENTDLL | FCVAR_CHEAT, SQVM_UIScript_f, nullptr); -#endif // !DEDICATED - //------------------------------------------------------------------------- - // FILESYSTEM API | - ConCommand::StaticCreate("fs_vpk_mount", "Mount a VPK file for FileSystem usage.", nullptr, FCVAR_DEVELOPMENTONLY, VPK_Mount_f, nullptr); - ConCommand::StaticCreate("fs_vpk_unmount", "Unmount a VPK file and clear its cache.", nullptr, FCVAR_DEVELOPMENTONLY, VPK_Unmount_f, nullptr); - ConCommand::StaticCreate("fs_vpk_pack", "Pack a VPK file from current workspace.", nullptr, FCVAR_DEVELOPMENTONLY, VPK_Pack_f, nullptr); - ConCommand::StaticCreate("fs_vpk_unpack", "Unpack all files from a VPK file.", nullptr, FCVAR_DEVELOPMENTONLY, VPK_Unpack_f, nullptr); - //------------------------------------------------------------------------- - // RTECH API | - ConCommand::StaticCreate("pak_strtoguid", "Calculates the GUID from input data.", nullptr, FCVAR_DEVELOPMENTONLY, Pak_StringToGUID_f, nullptr); - ConCommand::StaticCreate("pak_compress", "Compresses specified RPAK file.", nullptr, FCVAR_DEVELOPMENTONLY, Pak_Compress_f, RTech_PakCompress_f_CompletionFunc); - ConCommand::StaticCreate("pak_decompress", "Decompresses specified RPAK file.", nullptr, FCVAR_DEVELOPMENTONLY, Pak_Decompress_f, RTech_PakDecompress_f_CompletionFunc); - ConCommand::StaticCreate("pak_requestload", "Requests asynchronous load for specified RPAK file.", nullptr, FCVAR_DEVELOPMENTONLY, Pak_RequestLoad_f, RTech_PakLoad_f_CompletionFunc); - ConCommand::StaticCreate("pak_requestunload", "Requests unload for specified RPAK file or ID.", nullptr, FCVAR_DEVELOPMENTONLY, Pak_RequestUnload_f, RTech_PakUnload_f_CompletionFunc); - ConCommand::StaticCreate("pak_swap", "Requests swap for specified RPAK file or ID", nullptr, FCVAR_DEVELOPMENTONLY, Pak_Swap_f, nullptr); - ConCommand::StaticCreate("pak_listpaks", "Display a list of the loaded Pak files.", nullptr, FCVAR_RELEASE, Pak_ListPaks_f, nullptr); - ConCommand::StaticCreate("pak_listtypes", "Display a list of the registered asset types.", nullptr, FCVAR_RELEASE, Pak_ListTypes_f, nullptr); - //------------------------------------------------------------------------- - // NETCHANNEL | - ConCommand::StaticCreate("net_setkey", "Sets user specified base64 net key.", nullptr, FCVAR_RELEASE, NET_SetKey_f, nullptr); - ConCommand::StaticCreate("net_generatekey", "Generates and sets a random base64 net key.", nullptr, FCVAR_RELEASE, NET_GenerateKey_f, nullptr); - //------------------------------------------------------------------------- - // TIER0 | - if (!IsCert() && !IsRetail()) - ConCommand::StaticCreate("sig_getadr", "Logs the sigscan results to the console.", nullptr, FCVAR_DEVELOPMENTONLY | FCVAR_HIDDEN, SIG_GetAdr_f, nullptr); -} +// TODO: move VPK building code to separate file and place this in 'packedstore.cpp' +static ConCommand fs_vpk_mount("fs_vpk_mount", VPK_Mount_f, "Mount a VPK file for FileSystem usage", FCVAR_DEVELOPMENTONLY); +static ConCommand fs_vpk_unmount("fs_vpk_unmount", VPK_Unmount_f, "Unmount a VPK file and clear its cache", FCVAR_DEVELOPMENTONLY); +static ConCommand fs_vpk_pack("fs_vpk_pack", VPK_Pack_f, "Pack a VPK file from current workspace", FCVAR_DEVELOPMENTONLY); +static ConCommand fs_vpk_unpack("fs_vpk_unpack", VPK_Unpack_f, "Unpack all files from a VPK file", FCVAR_DEVELOPMENTONLY); //----------------------------------------------------------------------------- // Purpose: shipped ConCommand initialization diff --git a/src/common/global.h b/src/common/global.h index 118e241d..ee0b3da0 100644 --- a/src/common/global.h +++ b/src/common/global.h @@ -299,7 +299,6 @@ void ConVar_StaticInit(void); void ConVar_InitShipped(void); void ConVar_PurgeShipped(void); void ConVar_PurgeHostNames(void); -void ConCommand_StaticInit(void); void ConCommand_InitShipped(void); void ConCommand_PurgeShipped(void); diff --git a/src/core/dllmain.cpp b/src/core/dllmain.cpp index 75d4ebb0..b4a772e8 100644 --- a/src/core/dllmain.cpp +++ b/src/core/dllmain.cpp @@ -62,8 +62,6 @@ void Tier0_Init() g_RadAudioDecoderDll.InitFromName("binkawin64.dll"); g_RadAudioSystemDll.InitFromName("mileswin64.dll"); #endif // !DEDICATED - - g_pCmdLine = g_GameDll.GetExportedSymbol("g_pCmdLine").RCast(); g_CoreMsgVCallback = &EngineLoggerSink; // Setup logger callback sink. g_pCmdLine->CreateCmdLine(GetCommandLineA()); diff --git a/src/engine/client/cl_rcon.cpp b/src/engine/client/cl_rcon.cpp index f1f2873d..218fb598 100644 --- a/src/engine/client/cl_rcon.cpp +++ b/src/engine/client/cl_rcon.cpp @@ -229,3 +229,99 @@ CRConClient* RCONClient() // Singleton RCON Client. { return &s_RCONClient; } + +/* +===================== +RCON_CmdQuery_f + + Issues an RCON command to the + RCON server. +===================== +*/ +static void RCON_CmdQuery_f(const CCommand& args) +{ + const int64_t argCount = args.ArgC(); + + if (argCount < 2) + { + const char* pszAddress = rcon_address->GetString(); + + if (RCONClient()->IsInitialized() + && !RCONClient()->IsConnected() + && pszAddress[0]) + { + RCONClient()->Connect(pszAddress); + } + } + else + { + if (!RCONClient()->IsInitialized()) + { + Warning(eDLL_T::CLIENT, "Failed to issue command to RCON server: %s\n", "uninitialized"); + return; + } + else if (RCONClient()->IsConnected()) + { + vector vecMsg; + bool bSuccess = false; + const SocketHandle_t hSocket = RCONClient()->GetSocket(); + + if (strcmp(args.Arg(1), "PASS") == 0) // Auth with RCON server using rcon_password ConVar value. + { + if (argCount > 2) + { + bSuccess = RCONClient()->Serialize(vecMsg, args.Arg(2), "", cl_rcon::request_t::SERVERDATA_REQUEST_AUTH); + } + else // Use 'rcon_password' ConVar as password. + { + bSuccess = RCONClient()->Serialize(vecMsg, rcon_password->GetString(), "", cl_rcon::request_t::SERVERDATA_REQUEST_AUTH); + } + + if (bSuccess) + { + RCONClient()->Send(hSocket, vecMsg.data(), int(vecMsg.size())); + } + + return; + } + else if (strcmp(args.Arg(1), "disconnect") == 0) // Disconnect from RCON server. + { + RCONClient()->Disconnect("issued by user"); + return; + } + + bSuccess = RCONClient()->Serialize(vecMsg, args.Arg(1), args.ArgS(), cl_rcon::request_t::SERVERDATA_REQUEST_EXECCOMMAND); + if (bSuccess) + { + RCONClient()->Send(hSocket, vecMsg.data(), int(vecMsg.size())); + } + return; + } + else + { + Warning(eDLL_T::CLIENT, "Failed to issue command to RCON server: %s\n", "unconnected"); + return; + } + } +} + +/* +===================== +RCON_Disconnect_f + + Disconnect from RCON server +===================== +*/ +static void RCON_Disconnect_f() +{ + const bool bIsConnected = RCONClient()->IsConnected(); + RCONClient()->Disconnect("issued by user"); + + if (bIsConnected) // Log if client was indeed connected. + { + Msg(eDLL_T::CLIENT, "User closed RCON connection\n"); + } +} + +static ConCommand rcon("rcon", RCON_CmdQuery_f, "Forward RCON query to remote server", FCVAR_CLIENTDLL | FCVAR_RELEASE, nullptr, "rcon \"\""); +static ConCommand rcon_disconnect("rcon_disconnect", RCON_Disconnect_f, "Disconnect from RCON server", FCVAR_CLIENTDLL | FCVAR_RELEASE); diff --git a/src/engine/client/clientstate.cpp b/src/engine/client/clientstate.cpp index b3a2c644..00041fd2 100644 --- a/src/engine/client/clientstate.cpp +++ b/src/engine/client/clientstate.cpp @@ -139,7 +139,7 @@ void CClientState::VConnectionClosing(CClientState* thisptr, const char* szReaso { // Reload the local playlist to override the cached // one from the server we got disconnected from. - v__DownloadPlaylists_f(); + v_Playlists_Download_f(); Playlists_SDKInit(); }, 0); } diff --git a/src/engine/net.cpp b/src/engine/net.cpp index 0bce7f2e..6496fb2b 100644 --- a/src/engine/net.cpp +++ b/src/engine/net.cpp @@ -18,6 +18,23 @@ #endif // !_TOOLS #ifndef _TOOLS +static void NET_SetKey_f(const CCommand& args) +{ + if (args.ArgC() < 2) + { + return; + } + + NET_SetKey(args.Arg(1)); +} +static void NET_GenerateKey_f() +{ + NET_GenerateKey(); +} + +static ConCommand net_setkey("net_setkey", NET_SetKey_f, "Sets user specified base64 net key", FCVAR_RELEASE); +static ConCommand net_generatekey("net_generatekey", NET_GenerateKey_f, "Generates and sets a random base64 net key", FCVAR_RELEASE); + //----------------------------------------------------------------------------- // Purpose: hook and log the receive datagram // Input : iSocket - diff --git a/src/engine/sys_dll.cpp b/src/engine/sys_dll.cpp index 70f1635e..4365946b 100644 --- a/src/engine/sys_dll.cpp +++ b/src/engine/sys_dll.cpp @@ -40,19 +40,9 @@ //----------------------------------------------------------------------------- bool CSourceAppSystemGroup::StaticPreInit(CSourceAppSystemGroup* pSourceAppSystemGroup) { - if (pSourceAppSystemGroup->GetCurrentStage() == CSourceAppSystemGroup::CREATION) - { - ConVar_InitShipped(); - ConVar_PurgeShipped(); - ConCommand_StaticInit(); - ConCommand_InitShipped(); - ConCommand_PurgeShipped(); - } - return CSourceAppSystemGroup__PreInit(pSourceAppSystemGroup); } - //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- diff --git a/src/game/client/vscript_client.cpp b/src/game/client/vscript_client.cpp index fe6db959..edffbc3d 100644 --- a/src/game/client/vscript_client.cpp +++ b/src/game/client/vscript_client.cpp @@ -16,10 +16,47 @@ #include "networksystem/pylon.h" #include "networksystem/listmanager.h" #include "game/shared/vscript_shared.h" + +#include "vscript/vscript.h" #include "vscript/languages/squirrel_re/include/sqvm.h" #include "vscript_client.h" +/* +===================== +SQVM_ClientScript_f + + Executes input on the + VM in CLIENT context. +===================== +*/ +static void SQVM_ClientScript_f(const CCommand& args) +{ + if (args.ArgC() >= 2) + { + Script_Execute(args.ArgS(), SQCONTEXT::CLIENT); + } +} + +/* +===================== +SQVM_UIScript_f + + Executes input on the + VM in UI context. +===================== +*/ +static void SQVM_UIScript_f(const CCommand& args) +{ + if (args.ArgC() >= 2) + { + Script_Execute(args.ArgS(), SQCONTEXT::UI); + } +} + +static ConCommand script_client("script_client", SQVM_ClientScript_f, "Run input code as CLIENT script on the VM", FCVAR_DEVELOPMENTONLY | FCVAR_CLIENTDLL | FCVAR_CHEAT); +static ConCommand script_ui("script_ui", SQVM_UIScript_f, "Run input code as UI script on the VM", FCVAR_DEVELOPMENTONLY | FCVAR_CLIENTDLL | FCVAR_CHEAT); + //----------------------------------------------------------------------------- // Purpose: checks if the server index is valid, raises an error if not //----------------------------------------------------------------------------- diff --git a/src/game/server/ai_utility.cpp b/src/game/server/ai_utility.cpp index 7cfdd427..ea2fe0ad 100644 --- a/src/game/server/ai_utility.cpp +++ b/src/game/server/ai_utility.cpp @@ -5,7 +5,9 @@ //=============================================================================// #include "core/stdafx.h" +#include "tier0/fasttimer.h" #include "tier1/cvar.h" +#include "engine/server/server.h" #include "public/edict.h" #include "game/server/detour_impl.h" #include "game/server/ai_networkmanager.h" @@ -132,6 +134,33 @@ void Detour_HotSwap() Error(eDLL_T::SERVER, NOERROR, "%s - Failed to hot swap NavMesh\n", __FUNCTION__); } +/* +===================== +Detour_HotSwap_f + + Hot swaps the NavMesh + while the game is running +===================== +*/ +static void Detour_HotSwap_f() +{ + if (!g_pServer->IsActive()) + return; // Only execute if server is initialized and active. + + Msg(eDLL_T::SERVER, "Executing NavMesh hot swap for level '%s'\n", + g_ServerGlobalVariables->m_pszMapName); + + CFastTimer timer; + + timer.Start(); + Detour_HotSwap(); + + timer.End(); + Msg(eDLL_T::SERVER, "Hot swap took '%lf' seconds\n", timer.GetDuration().GetSeconds()); +} + +static ConCommand navmesh_hotswap("navmesh_hotswap", Detour_HotSwap_f, "Hot swap the NavMesh for all hulls", FCVAR_DEVELOPMENTONLY); + /////////////////////////////////////////////////////////////////////////////// void VRecast::Detour(const bool bAttach) const { diff --git a/src/game/server/player.cpp b/src/game/server/player.cpp index c7365536..2a90ab76 100644 --- a/src/game/server/player.cpp +++ b/src/game/server/player.cpp @@ -234,4 +234,50 @@ void CPlayer::PlayerRunCommand(CUserCmd* pUserCmd, IMoveHelper* pMover) void CPlayer::SetLastUserCommand(CUserCmd* pUserCmd) { m_LastCmd.Copy(pUserCmd); -} \ No newline at end of file +} + +/* +===================== +CC_CreateFakePlayer_f + + Creates a fake player + on the server +===================== +*/ +static void CC_CreateFakePlayer_f(const CCommand& args) +{ + if (!g_pServer->IsActive()) + return; + + if (args.ArgC() < 3) + { + Msg(eDLL_T::SERVER, "usage 'sv_addbot': name(string) teamid(int)\n"); + return; + } + + const int numPlayers = g_pServer->GetNumClients(); + + // Already at max, don't create. + if (numPlayers >= g_ServerGlobalVariables->m_nMaxClients) + return; + + const char* playerName = args.Arg(1); + + int teamNum = atoi(args.Arg(2)); + const int maxTeams = int(g_pServer->GetMaxTeams()) + 1; + + // Clamp team count, going above the limit will + // cause a crash. Going below 0 means that the + // engine will assign the bot to the last team. + if (teamNum > maxTeams) + teamNum = maxTeams; + + g_pEngineServer->LockNetworkStringTables(true); + + const edict_t nHandle = g_pEngineServer->CreateFakeClient(playerName, teamNum); + g_pServerGameClients->ClientFullyConnect(nHandle, false); + + g_pEngineServer->LockNetworkStringTables(false); +} + +static ConCommand sv_addbot("sv_addbot", CC_CreateFakePlayer_f, "Creates a bot on the server", FCVAR_RELEASE); diff --git a/src/game/server/vscript_server.cpp b/src/game/server/vscript_server.cpp index c6fc6fc0..e82d815b 100644 --- a/src/game/server/vscript_server.cpp +++ b/src/game/server/vscript_server.cpp @@ -11,12 +11,30 @@ #include "core/stdafx.h" #include "engine/server/server.h" #include "game/shared/vscript_shared.h" +#include "vscript/vscript.h" #include "vscript/languages/squirrel_re/include/sqvm.h" #include "vscript_server.h" #include #include +/* +===================== +SQVM_ServerScript_f + + Executes input on the + VM in SERVER context. +===================== +*/ +static void SQVM_ServerScript_f(const CCommand& args) +{ + if (args.ArgC() >= 2) + { + Script_Execute(args.ArgS(), SQCONTEXT::SERVER); + } +} +static ConCommand script("script", SQVM_ServerScript_f, "Run input code as SERVER script on the VM", FCVAR_DEVELOPMENTONLY | FCVAR_GAMEDLL | FCVAR_CHEAT); + namespace VScriptCode { namespace Server diff --git a/src/gameui/IBrowser.cpp b/src/gameui/IBrowser.cpp index 4ed71f5a..a622854f 100644 --- a/src/gameui/IBrowser.cpp +++ b/src/gameui/IBrowser.cpp @@ -37,6 +37,8 @@ History: #include "public/edict.h" #include "game/shared/vscript_shared.h" +static ConCommand togglebrowser("togglebrowser", CBrowser::ToggleBrowser_f, "Show/hide the server browser", FCVAR_CLIENTDLL | FCVAR_RELEASE); + //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- @@ -602,7 +604,7 @@ void CBrowser::HostPanel(void) { g_TaskScheduler->Dispatch([]() { - v__DownloadPlaylists_f(); + v_Playlists_Download_f(); Playlists_SDKInit(); // Re-Init playlist. }, 0); } @@ -869,4 +871,13 @@ void CBrowser::SetStyleVar(void) ImGui::SetWindowPos(ImVec2(-500.f, 50.f), ImGuiCond_FirstUseEver); } +//----------------------------------------------------------------------------- +// Purpose: toggles the server browser +//----------------------------------------------------------------------------- +void CBrowser::ToggleBrowser_f() +{ + g_Browser.m_bActivate ^= true; + ResetInput(); // Disable input to game when browser is drawn. +} + CBrowser g_Browser; \ No newline at end of file diff --git a/src/gameui/IBrowser.h b/src/gameui/IBrowser.h index b01eb17d..2a9d40f0 100644 --- a/src/gameui/IBrowser.h +++ b/src/gameui/IBrowser.h @@ -38,6 +38,10 @@ public: inline bool IsVisible() { return m_flFadeAlpha > 0.0f; } +public: + // Command callbacks + static void ToggleBrowser_f(); + const char* m_pszBrowserLabel; bool m_bActivate; diff --git a/src/gameui/IConsole.cpp b/src/gameui/IConsole.cpp index 7d5f9b12..052bd0e7 100644 --- a/src/gameui/IConsole.cpp +++ b/src/gameui/IConsole.cpp @@ -23,6 +23,13 @@ History: #include "engine/cmd.h" #include "gameui/IConsole.h" +static ConCommand toggleconsole("toggleconsole", CConsole::ToggleConsole_f, "Show/hide the developer console.", FCVAR_CLIENTDLL | FCVAR_RELEASE); + +static ConCommand con_history("con_history", CConsole::LogHistory_f, "Shows the developer console submission history", FCVAR_CLIENTDLL | FCVAR_RELEASE); +static ConCommand con_removeline("con_removeline", CConsole::RemoveLine_f, "Removes a range of lines from the developer console", FCVAR_CLIENTDLL | FCVAR_RELEASE); +static ConCommand con_clearlines("con_clearlines", CConsole::ClearLines_f, "Clears all lines from the developer console", FCVAR_CLIENTDLL | FCVAR_RELEASE); +static ConCommand con_clearhistory("con_clearhistory", CConsole::ClearHistory_f, "Clears all submissions from the developer console history", FCVAR_CLIENTDLL | FCVAR_RELEASE); + //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- @@ -524,18 +531,24 @@ bool CConsole::AutoComplete(void) else if (m_bCanAutoComplete) // Command completion callback. { ResetAutoComplete(); - string svCommand; - for (size_t i = 0; i < sizeof(m_szInputBuf); i++) + char szCommand[sizeof(m_szInputBuf)]; + size_t i = 0; + + // Truncate everything past (and including) the space to get the + // command string. + for (; i < sizeof(m_szInputBuf); i++) { if (isspace(m_szInputBuf[i])) { break; } - svCommand += m_szInputBuf[i]; + + szCommand[i] = m_szInputBuf[i]; } - ConCommand* pCommand = g_pCVar->FindCommand(svCommand.c_str()); + szCommand[i] = '\0'; + ConCommand* pCommand = g_pCVar->FindCommand(szCommand); if (pCommand && pCommand->CanAutoComplete()) { @@ -547,9 +560,9 @@ bool CConsole::AutoComplete(void) return false; } - for (int i = 0; i < iret; ++i) + for (int j = 0; j < iret; ++j) { - m_vSuggest.push_back(CSuggest(commands[i].String(), COMMAND_COMPLETION_MARKER)); + m_vSuggest.push_back(CSuggest(commands[j].String(), COMMAND_COMPLETION_MARKER)); } } else @@ -1152,4 +1165,58 @@ void CConsole::SetStyleVar(void) ImGui::SetWindowPos(ImVec2(-1000, 50), ImGuiCond_FirstUseEver); } +//----------------------------------------------------------------------------- +// Purpose: toggles the console +//----------------------------------------------------------------------------- +void CConsole::ToggleConsole_f() +{ + g_Console.m_bActivate ^= true; + ResetInput(); // Disable input to game when console is drawn. +} + +//----------------------------------------------------------------------------- +// Purpose: shows the game console submission history. +//----------------------------------------------------------------------------- +void CConsole::LogHistory_f() +{ + const vector vHistory = g_Console.GetHistory(); + for (size_t i = 0, nh = vHistory.size(); i < nh; i++) + { + Msg(eDLL_T::COMMON, "%3d: %s\n", i, vHistory[i].c_str()); + } +} + +//----------------------------------------------------------------------------- +// Purpose: removes a range of lines from the console. +//----------------------------------------------------------------------------- +void CConsole::RemoveLine_f(const CCommand& args) +{ + if (args.ArgC() < 3) + { + Msg(eDLL_T::CLIENT, "Usage 'con_removeline': start(int) end(int)\n"); + return; + } + + int start = atoi(args[1]); + int end = atoi(args[2]); + + g_Console.RemoveLog(start, end); +} + +//----------------------------------------------------------------------------- +// Purpose: clears all lines from the developer console. +//----------------------------------------------------------------------------- +void CConsole::ClearLines_f() +{ + g_Console.ClearLog(); +} + +//----------------------------------------------------------------------------- +// Purpose: clears all submissions from the developer console history. +//----------------------------------------------------------------------------- +void CConsole::ClearHistory_f() +{ + g_Console.ClearHistory(); +} + CConsole g_Console; diff --git a/src/gameui/IConsole.h b/src/gameui/IConsole.h index ac100fc6..bb974da9 100644 --- a/src/gameui/IConsole.h +++ b/src/gameui/IConsole.h @@ -62,6 +62,14 @@ public: inline bool IsVisible() { return m_flFadeAlpha > 0.0f; } +public: + // Console command callbacks + static void ToggleConsole_f(); + static void LogHistory_f(); + static void RemoveLine_f(const CCommand& args); + static void ClearLines_f(); + static void ClearHistory_f(); + private: // Internal only. void AddLog(const ImVec4& color, const char* fmt, ...) /*IM_FMTARGS(2)*/; diff --git a/src/materialsystem/cmaterialsystem.cpp b/src/materialsystem/cmaterialsystem.cpp index 138fc051..edb9c694 100644 --- a/src/materialsystem/cmaterialsystem.cpp +++ b/src/materialsystem/cmaterialsystem.cpp @@ -8,7 +8,7 @@ #include "tier0/commandline.h" #include "tier1/cvar.h" #include "tier1/keyvalues.h" -#include "rtech/pak/pakparse.h" +#include "rtech/pak/pakstate.h" #include "engine/cmodel_bsp.h" #include "engine/sys_engine.h" #include "geforce/reflex.h" diff --git a/src/networksystem/bansystem.cpp b/src/networksystem/bansystem.cpp index d6dbf24a..2714dd77 100644 --- a/src/networksystem/bansystem.cpp +++ b/src/networksystem/bansystem.cpp @@ -412,5 +412,84 @@ void CBanSystem::AuthorPlayerById(const char* playerHandle, const bool shouldBan } } +/////////////////////////////////////////////////////////////////////////////// +// Console command handlers +/////////////////////////////////////////////////////////////////////////////// + +static void _Author_Client_f(const CCommand& args, EKickType type) +{ + if (args.ArgC() < 2) + { + return; + } + + const char* szReason = args.ArgC() > 2 ? args.Arg(2) : nullptr; + + switch (type) + { + case KICK_NAME: + { + g_BanSystem.KickPlayerByName(args.Arg(1), szReason); + break; + } + case KICK_ID: + { + g_BanSystem.KickPlayerById(args.Arg(1), szReason); + break; + } + case BAN_NAME: + { + g_BanSystem.BanPlayerByName(args.Arg(1), szReason); + break; + } + case BAN_ID: + { + g_BanSystem.BanPlayerById(args.Arg(1), szReason); + break; + } + default: + { + // Code bug. + Assert(0); + } + } +} +static void Host_Kick_f(const CCommand& args) +{ + _Author_Client_f(args, EKickType::KICK_NAME); +} +static void Host_KickID_f(const CCommand& args) +{ + _Author_Client_f(args, EKickType::KICK_ID); +} +static void Host_Ban_f(const CCommand& args) +{ + _Author_Client_f(args, EKickType::BAN_NAME); +} +static void Host_BanID_f(const CCommand& args) +{ + _Author_Client_f(args, EKickType::BAN_ID); +} +static void Host_Unban_f(const CCommand& args) +{ + if (args.ArgC() < 2) + { + return; + } + + g_BanSystem.UnbanPlayer(args.Arg(1)); +} +static void Host_ReloadBanList_f() +{ + g_BanSystem.LoadList(); // Reload banned list. +} + +static ConCommand kick("kick", Host_Kick_f, "Kick a client from the server by user name", FCVAR_RELEASE, nullptr, "kick \"\""); +static ConCommand kickid("kickid", Host_KickID_f, "Kick a client from the server by handle, nucleus id or ip address", FCVAR_RELEASE, nullptr, "kickid \"\"/\"/\""); +static ConCommand ban("ban", Host_Ban_f, "Bans a client from the server by user name", FCVAR_RELEASE, nullptr, "ban "); +static ConCommand banid("banid", Host_BanID_f, "Bans a client from the server by handle, nucleus id or ip address", FCVAR_RELEASE, nullptr, "banid \"\"/\"/\""); +static ConCommand unban("unban", Host_Unban_f, "Unbans a client from the server by nucleus id or ip address", FCVAR_RELEASE, nullptr, "unban \"\"/\"\""); +static ConCommand reload_banlist("banlist_reload", Host_ReloadBanList_f, "Reloads the banned list", FCVAR_RELEASE); + /////////////////////////////////////////////////////////////////////////////// CBanSystem g_BanSystem; diff --git a/src/public/coordsize.h b/src/public/coordsize.h index 8666768f..b21d9eee 100644 --- a/src/public/coordsize.h +++ b/src/public/coordsize.h @@ -29,7 +29,7 @@ #define NORMAL_RESOLUTION (1.0f/(NORMAL_DENOMINATOR)) // this is limited by the network fractional bits used for coords -// because net coords will be only be accurate to 5 bits fractional +// because net coords will only be accurate to 5 bits fractional // Standard collision test epsilon // 1/32nd inch collision epsilon #define DIST_EPSILON (0.03125) diff --git a/src/public/iconcommand.h b/src/public/iconcommand.h index af3bcb78..03805d4a 100644 --- a/src/public/iconcommand.h +++ b/src/public/iconcommand.h @@ -17,37 +17,7 @@ abstract_class IConCommandBaseAccessor public: // Flags is a combination of FCVAR flags in cvar.h. // hOut is filled in with a handle to the variable. - virtual bool RegisterConCommandBase(ConCommandBase* pVar) = 0; + virtual bool RegisterConCommandBase(ConCommandBase* const pVar) = 0; }; -//----------------------------------------------------------------------------- -// Abstract interface for ConVars -//----------------------------------------------------------------------------- -abstract_class IConCommandBase -{ -public: - virtual ~IConCommandBase(void) = 0; - - virtual bool IsCommand(void) const = 0; - - virtual bool IsFlagSet(int flag) const = 0; // Check flag - virtual void AddFlags(int flags) = 0; // Set flag - virtual void RemoveFlags(int flags) = 0; // Clear flag - virtual int GetFlags() const = 0; // Get flag - - virtual const char* GetName(void) const = 0; // Return name of cvar - virtual const char* GetHelpText(void) const = 0; // Return help text for cvar - virtual const char* GetUsageText(void) const = 0; // Return usage text for cvar - virtual void SetAccessor(char* bAccessors) const = 0; - - virtual bool IsRegistered(void) const = 0; - virtual CVarDLLIdentifier_t GetDLLIdentifier() const = 0; // Returns the DLL identifier - -protected: - virtual void Create(const char* pName, const char* pHelpString = 0, - int flags = 0) = 0; - virtual void Init() = 0; // Used internally by OneTimeInit to initialize/shutdown -}; - - -#endif // ICONCOMMAND_H \ No newline at end of file +#endif // ICONCOMMAND_H diff --git a/src/public/tier1/convar.h b/src/public/tier1/convar.h index adc4ad91..df145af2 100644 --- a/src/public/tier1/convar.h +++ b/src/public/tier1/convar.h @@ -26,38 +26,57 @@ class ConCommandBase public: virtual ~ConCommandBase(void) { }; - virtual bool IsCommand(void) const = 0; - virtual bool IsFlagSet(int nFlags) const = 0; + virtual bool IsCommand(void) const; + virtual bool IsFlagSet(const int nFlags) const; - virtual void AddFlags(int nFlags) = 0; - virtual void RemoveFlags(int nFlags) = 0; + virtual void AddFlags(const int nFlags); + virtual void RemoveFlags(const int nFlags); - virtual int GetFlags(void) const = 0; - virtual const char* GetName(void) const = 0; - virtual const char* GetHelpText(void) const = 0; - virtual const char* GetUsageText(void) const = 0; + virtual int GetFlags(void) const; + virtual const char* GetName(void) const; + virtual const char* GetHelpText(void) const; + virtual const char* GetUsageText(void) const; - virtual void SetAccessor(IConCommandBaseAccessor* pAccessor) = 0; - virtual bool IsRegistered(void) const = 0; + virtual void SetAccessor(IConCommandBaseAccessor* const pAccessor); + virtual bool IsRegistered(void) const; - virtual int GetDLLIdentifier() const = 0; + virtual int GetDLLIdentifier() const; virtual ConCommandBase* Create(const char* szName, const char* szHelpString, - int nFlags, const char* pszUsageString) = 0; + int nFlags, const char* pszUsageString); - virtual void Init() = 0; - - bool HasFlags(int nFlags) const; + virtual void Init(); + void Shutdown(); ConCommandBase* GetNext(void) const; char* CopyString(const char* szFrom) const; +//private: + // Next ConVar in chain + // Prior to register, it points to the next convar in the DLL. + // Once registered, though, m_pNext is reset to point to the next + // convar in the global list ConCommandBase* m_pNext; //0x0008 + + // Has the cvar been added to the global list? bool m_bRegistered; //0x0010 + + // Static data. const char* m_pszName; //0x0018 const char* m_pszHelpString; //0x0020 const char* m_pszUsageString; //0x0028 - IConCommandBaseAccessor* s_pAccessor; //0x0030 <-- unused since executable is monolithic. + + IConCommandBaseAccessor* m_pAccessor; //0x0030 <-- unused since executable is monolithic. + + // ConVar flags int m_nFlags; //0x0038 + + // ConVars add themselves to this list for the executable. + // Then ConVar_Register runs through all the console variables + // and registers them into a global list stored in vstdlib.dll + static ConCommandBase* s_pConCommandBases; + + // ConVars in this executable use this 'global' to access values. + static IConCommandBaseAccessor* s_pAccessor; }; static_assert(sizeof(ConCommandBase) == 0x40); @@ -70,16 +89,37 @@ class ConCommand : public ConCommandBase { friend class CCvar; public: - ConCommand(void); + typedef ConCommandBase BaseClass; - static ConCommand* StaticCreate(const char* szName, const char* szHelpString, const char* pszUsageString, - int nFlags, FnCommandCallback_t pCallback, FnCommandCompletionCallback pCommandCompletionCallback); + ConCommand(const char* pName, FnCommandCallbackV1_t callback, + const char* pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0, const char* pszUsageString = 0); + ConCommand(const char* pName, FnCommandCallback_t callback, + const char* pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0, const char* pszUsageString = 0); + ConCommand(const char* pName, ICommandCallback* pCallback, + const char* pHelpString = 0, int flags = 0, ICommandCompletionCallback* pCommandCompletionCallback = 0, const char* pszUsageString = 0); - virtual int AutoCompleteSuggest(const char* partial, CUtlVector< CUtlString >& commands) = 0; - virtual bool CanAutoComplete(void) const = 0; + virtual ~ConCommand(void); + virtual bool IsCommand(void) const; + + virtual int AutoCompleteSuggest(const char* partial, CUtlVector< CUtlString >& commands); + virtual bool CanAutoComplete(void) const; + + // Invoke the function + virtual void Dispatch(const CCommand& command); + +//private: void* m_nNullCallBack; //0x0040 void* m_pSubCallback; //0x0048 + + // NOTE: To maintain backward compatibility, we have to be very careful: + // All public virtual methods must appear in the same order always + // since engine code will be calling into this code, which *does not match* + // in the mod code; it's using slightly different, but compatible versions + // of this class. Also: Be very careful about adding new fields to this class. + // Those fields will not exist in the version of this class that is instanced + // in mod code. + // Call this function when executing the command union { @@ -233,6 +273,12 @@ FORCEINLINE const char* ConVar::GetString(void) const return str ? str : ""; } +//----------------------------------------------------------------------------- +// Called by the framework to register ConCommands with the ICVar +//----------------------------------------------------------------------------- +void ConVar_Register(int nCVarFlag = 0, IConCommandBaseAccessor* pAccessor = NULL); +void ConVar_Unregister(); + /* ==== CONVAR ========================================================================================================================================================== */ inline void*(*ConVar__Register)(ConVar* thisptr, const char* szName, const char* szDefaultValue, int nFlags, const char* szHelpString, bool bMin, float fMin, bool bMax, float fMax, FnChangeCallback_t pCallback, const char* pszUsageString); inline void(*ConVar__Unregister)(ConVar* thisptr); diff --git a/src/public/tier1/cvar.h b/src/public/tier1/cvar.h index af1f37c4..d422470e 100644 --- a/src/public/tier1/cvar.h +++ b/src/public/tier1/cvar.h @@ -162,6 +162,9 @@ extern ConVarFlags g_ConVarFlags; bool ConVar_ParseFlagString(const char* pszFlags, int& nFlags, const char* pszConVarName = "<>"); void ConVar_PrintDescription(ConCommandBase* pVar); +inline bool (*CCvar__Connect)(CCvar* thisptr, CreateInterfaceFn factory); +inline void (*CCvar__Disconnect)(CCvar* thisptr); + inline void (*v_ConVar_PrintDescription)(ConCommandBase* pVar); /////////////////////////////////////////////////////////////////////////////// @@ -169,18 +172,20 @@ class VCVar : public IDetour { virtual void GetAdr(void) const { + LogFunAdr("CCvar::Connect", CCvar__Connect); + LogFunAdr("CCvar::Disconnect", CCvar__Disconnect); LogFunAdr("ConVar_PrintDescription", v_ConVar_PrintDescription); LogVarAdr("g_pCVar", g_pCVar); } virtual void GetFun(void) const { + g_GameDll.FindPatternSIMD("48 83 EC 28 48 8B 05 ?? ?? ?? ?? 48 8D 0D ?? ?? ?? ?? 48 85 C0 48 0F 45 C8 FF 05 ?? ?? ?? ?? 48 89 0D ?? ?? ?? ??").GetPtr(CCvar__Connect); + g_GameDll.FindPatternSIMD("48 83 EC 28 48 8B 0D ?? ?? ?? ?? 48 85 C9 74 26 80 3D ?? ?? ?? ?? ?? 74 1D 48 8B 01 8B 15 ?? " + "?? ?? ?? FF 50 58 C7 05 ?? ?? ?? ?? ?? ?? ?? ?? C6 05 ?? ?? ?? ?? ?? 48 C7 05 ?? ?? ?? ?? ?? ?? ?? ??").GetPtr(CCvar__Disconnect); + g_GameDll.FindPatternSIMD("B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 2B E0 48 8B 01 48 89 9C 24 ?? ?? ?? ??").GetPtr(v_ConVar_PrintDescription); } - virtual void GetVar(void) const - { - g_GameDll.FindPatternSIMD("48 83 EC 28 48 8B 05 ?? ?? ?? ?? 48 8D 0D ?? ?? ?? ?? 48 85 C0 48 0F 45 C8 FF 05 ?? ?? ?? ?? 48 89 0D ?? ?? ?? ??") - .FindPatternSelf("48 8D 0D").ResolveRelativeAddressSelf(3, 7).GetPtr(g_pCVar); - } + virtual void GetVar(void) const { } virtual void GetCon(void) const { } virtual void Detour(const bool bAttach) const; }; diff --git a/src/rtech/pak/pakparse.cpp b/src/rtech/pak/pakparse.cpp index 2aadcdd7..acd1a66e 100644 --- a/src/rtech/pak/pakparse.cpp +++ b/src/rtech/pak/pakparse.cpp @@ -332,7 +332,6 @@ bool Pak_ProcessPakFile(PakFile_t* const pak) fileStream->bytesStreamed, (memoryData->processedPatchedDataSize + PAK_DECODE_OUT_RING_BUFFER_SIZE), v22->compressionMode); qword1D0 = pak->pakDecoder.outBufBytePos; - pak->inputBytePos = pak->pakDecoder.inBufBytePos; if (didDecode) @@ -353,10 +352,6 @@ bool Pak_ProcessPakFile(PakFile_t* const pak) size_t numBytesToProcess = qword1D0 - memoryData->processedPatchedDataSize; - // DEBUG: REMOVE - if ((long long)pak->memoryData.patchFunc == 0x14043E2A0) - pak->memoryData.patchFunc = g_pakPatchApi[0]; - while (memoryData->patchSrcSize + memoryData->field_2A8) { // if there are no bytes left to process in this patch operation @@ -1310,6 +1305,3 @@ void V_PakParse::Detour(const bool bAttach) const DetourSetup(&v_Pak_RunAssetLoadingJobs, &Pak_RunAssetLoadingJobs, bAttach); } - -// Symbols taken from R2 dll's. -PakLoadFuncs_t* g_pakLoadApi = nullptr; diff --git a/src/rtech/pak/pakparse.h b/src/rtech/pak/pakparse.h index 22d62df3..30a176fe 100644 --- a/src/rtech/pak/pakparse.h +++ b/src/rtech/pak/pakparse.h @@ -28,49 +28,6 @@ inline int (*Pak_TrackAsset)(PakFile_t* const a1, PakAsset_t* a2); // TODO: name these! inline void (*sub_14043D870)(PakLoadedInfo_t* a1, int a2); -typedef struct PakLoadFuncs_s -{ - void* Initialize; // Returns the pak handle of the patch master RPak once initialized. - void* RegisterAsset; - char unknown0[8]; - PakHandle_t(*LoadAsync)(const char* pakFileName, CAlignedMemAlloc* allocator, int nIdx, bool bUnk); - void* LoadAsyncAndWait; - void (*UnloadAsync)(PakHandle_t handle); - void* UnloadAsyncAndWait; - char unknown2[16]; - void* Func7; - void* Func8; - EPakStatus(*WaitAsync)(PakHandle_t handle, void* finishCallback); - void* Func10; - void* Func11; - void* FindByGUID; - void* FindByName; - char unknown3[8]; - void* Func14; - void* Func15; - void* Func16; - void* Func17; - void* Func18; - void* IncrementStreamingAssetCount; - void* DecrementStreamingAssetCount; - void* IsFullStreamingInstall; - char unknown4[48]; - int (*OpenAsyncFile)(const char* const fileName, int logLevel, size_t* const outFileSize); - void (*CloseAsyncFile)(short fileHandle); - void* Func24; - void* Func25; - void* ReadAsyncFile; - void* ReadAsyncFileWithUserData; - uint8_t (*CheckAsyncRequest)(int idx, size_t* const bytesProcessed, const char** const statusMsg); - uint8_t (*WaitAndCheckAsyncRequest)(int idx, size_t* const bytesProcessed, const char** const statusMsg); - void* WaitForAsyncFileRead; - void* Func31; - void* Func32; - void* Func33; -} PakLoadFuncs_t; - -extern PakLoadFuncs_t* g_pakLoadApi; - /////////////////////////////////////////////////////////////////////////////// class V_PakParse : public IDetour { @@ -89,8 +46,6 @@ class V_PakParse : public IDetour LogFunAdr("Pak_ProcessPakFile", v_Pak_ProcessPakFile); LogFunAdr("Pak_ProcessAssets", v_Pak_ProcessAssets); LogFunAdr("Pak_ResolveAssetRelations", v_Pak_ResolveAssetRelations); - - LogVarAdr("g_pakLoadApi", g_pakLoadApi); } virtual void GetFun(void) const { @@ -111,10 +66,7 @@ class V_PakParse : public IDetour g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? EB 14 48 8D 0D ?? ?? ?? ??").FollowNearCallSelf().GetPtr(sub_14043D870); } - virtual void GetVar(void) const - { - g_pakLoadApi = CMemory(v_LauncherMain).Offset(0x820).FindPatternSelf("48 89").ResolveRelativeAddressSelf(0x3, 0x7).RCast(); - } + virtual void GetVar(void) const { } virtual void GetCon(void) const { } virtual void Detour(const bool bAttach) const; }; diff --git a/src/rtech/pak/pakstate.cpp b/src/rtech/pak/pakstate.cpp index a12979bf..496d855d 100644 --- a/src/rtech/pak/pakstate.cpp +++ b/src/rtech/pak/pakstate.cpp @@ -3,6 +3,262 @@ // Purpose: pak runtime memory and management // //=============================================================================// +#include "tier1/fmtstr.h" +#include "common/completion.h" #include "rtech/ipakfile.h" +#include "pakencode.h" +#include "pakdecode.h" +#include "paktools.h" #include "pakstate.h" +/* +===================== +Pak_ListPaks_f +===================== +*/ +static void Pak_ListPaks_f() +{ + Msg(eDLL_T::RTECH, "| id | name | status | asset count |\n"); + Msg(eDLL_T::RTECH, "|------|----------------------------------------------------|--------------------------------------|-------------|\n"); + uint32_t nTotalLoaded = 0; + + for (int16_t i = 0, n = g_pakGlobals->loadedPakCount; i < n; ++i) + { + const PakLoadedInfo_t& info = g_pakGlobals->loadedPaks[i]; + + if (info.status == EPakStatus::PAK_STATUS_FREED) + continue; + + const char* szRpakStatus = Pak_StatusToString(info.status); + + // todo: make status into a string from an array/vector + Msg(eDLL_T::RTECH, "| %04i | %-50s | %-36s | %11i |\n", info.handle, info.fileName, szRpakStatus, info.assetCount); + nTotalLoaded++; + } + Msg(eDLL_T::RTECH, "|------|----------------------------------------------------|--------------------------------------|-------------|\n"); + Msg(eDLL_T::RTECH, "| %18i loaded paks. |\n", nTotalLoaded); + Msg(eDLL_T::RTECH, "|------|----------------------------------------------------|--------------------------------------|-------------|\n"); +} + +/* +===================== +Pak_ListTypes_f +===================== +*/ +static void Pak_ListTypes_f() +{ + Msg(eDLL_T::RTECH, "| ext | description | version | header size | native size |\n"); + Msg(eDLL_T::RTECH, "|------|---------------------------|---------|-------------|-------------|\n"); + + uint32_t nRegistered = 0; + + for (int8_t i = 0; i < PAK_MAX_TYPES; ++i) + { + PakAssetBinding_t* type = &g_pakGlobals->assetBindings[i]; + + if (!type->description) + continue; + + FourCCString_t assetExtension; + FourCCToString(assetExtension, type->extension); + + Msg(eDLL_T::RTECH, "| %-4s | %-25s | %7i | %11i | %11i |\n", assetExtension, type->description, type->version, type->headerSize, type->nativeClassSize); + nRegistered++; + } + Msg(eDLL_T::RTECH, "|------|---------------------------|---------|-------------|-------------|\n"); + Msg(eDLL_T::RTECH, "| %18i registered types. |\n", nRegistered); + Msg(eDLL_T::RTECH, "|------|---------------------------|---------|-------------|-------------|\n"); +} + +/* +===================== +Pak_RequestUnload_f +===================== +*/ +static void Pak_RequestUnload_f(const CCommand& args) +{ + if (args.ArgC() < 2) + { + return; + } + + if (args.HasOnlyDigits(1)) + { + const PakHandle_t pakHandle = atoi(args.Arg(1)); + const PakLoadedInfo_t* const pakInfo = Pak_GetPakInfo(pakHandle); + + if (!pakInfo) + { + Warning(eDLL_T::RTECH, "Found no pak entry for specified handle.\n"); + return; + } + + Msg(eDLL_T::RTECH, "Requested pak unload for handle '%d'\n", pakHandle); + g_pakLoadApi->UnloadAsync(pakHandle); + } + else + { + const PakLoadedInfo_t* const pakInfo = Pak_GetPakInfo(args.Arg(1)); + if (!pakInfo) + { + Warning(eDLL_T::RTECH, "Found no pak entry for specified name.\n"); + return; + } + + Msg(eDLL_T::RTECH, "Requested pak unload for file '%s'\n", args.Arg(1)); + g_pakLoadApi->UnloadAsync(pakInfo->handle); + } +} + +/* +===================== +Pak_RequestLoad_f +===================== +*/ +static void Pak_RequestLoad_f(const CCommand& args) +{ + g_pakLoadApi->LoadAsync(args.Arg(1), AlignedMemAlloc(), NULL, 0); +} + + +/* +===================== +Pak_Swap_f +===================== +*/ +static void Pak_Swap_f(const CCommand& args) +{ + if (args.ArgC() < 2) + { + return; + } + + const char* pakName = nullptr; + + PakHandle_t pakHandle = INVALID_PAK_HANDLE; + const PakLoadedInfo_t* pakInfo = nullptr; + + if (args.HasOnlyDigits(1)) + { + pakHandle = atoi(args.Arg(1)); + pakInfo = Pak_GetPakInfo(pakHandle); + + if (!pakInfo) + { + Warning(eDLL_T::RTECH, "Found no pak entry for specified handle.\n"); + return; + } + + pakName = pakInfo->fileName; + } + else + { + pakName = args.Arg(1); + pakInfo = Pak_GetPakInfo(pakName); + + if (!pakInfo) + { + Warning(eDLL_T::RTECH, "Found no pak entry for specified name.\n"); + return; + } + + pakHandle = pakInfo->handle; + } + + Msg(eDLL_T::RTECH, "Requested pak swap for handle '%d'\n", pakHandle); + g_pakLoadApi->UnloadAsync(pakHandle); + + while (pakInfo->status != EPakStatus::PAK_STATUS_FREED) // Wait till this slot gets free'd. + std::this_thread::sleep_for(std::chrono::seconds(1)); + + g_pakLoadApi->LoadAsync(pakName, AlignedMemAlloc(), NULL, 0); +} + +/* +===================== +RTech_StringToGUID_f +===================== +*/ +static void Pak_StringToGUID_f(const CCommand& args) +{ + if (args.ArgC() < 2) + { + return; + } + + unsigned long long guid = Pak_StringToGuid(args.Arg(1)); + + Msg(eDLL_T::RTECH, "______________________________________________________________\n"); + Msg(eDLL_T::RTECH, "] RTECH_HASH ]------------------------------------------------\n"); + Msg(eDLL_T::RTECH, "] GUID: '0x%llX'\n", guid); +} + +/* +===================== +RTech_Decompress_f + + Decompresses input RPak file and + dumps results to override path +===================== +*/ +static void Pak_Decompress_f(const CCommand& args) +{ + if (args.ArgC() < 2) + { + return; + } + + CFmtStr1024 inPakFile(PLATFORM_PAK_PATH "%s", args.Arg(1)); + CFmtStr1024 outPakFile(PLATFORM_PAK_OVERRIDE_PATH "%s", args.Arg(1)); + + if (!Pak_DecodePakFile(inPakFile.String(), outPakFile.String())) + { + Error(eDLL_T::RTECH, NO_ERROR, "%s - decompression failed for '%s'!\n", + __FUNCTION__, inPakFile.String()); + } +} + +/* +===================== +RTech_Compress_f + + Compresses input RPak file and + dumps results to base path +===================== +*/ +static void Pak_Compress_f(const CCommand& args) +{ + if (args.ArgC() < 2) + { + return; + } + + CFmtStr1024 inPakFile(PLATFORM_PAK_OVERRIDE_PATH "%s", args.Arg(1)); + CFmtStr1024 outPakFile(PLATFORM_PAK_PATH "%s", args.Arg(1)); + + // NULL means default compress level + const int compressLevel = args.ArgC() > 2 ? atoi(args.Arg(2)) : NULL; + + if (!Pak_EncodePakFile(inPakFile.String(), outPakFile.String(), compressLevel)) + { + Error(eDLL_T::RTECH, NO_ERROR, "%s - compression failed for '%s'!\n", + __FUNCTION__, inPakFile.String()); + } +} + +static ConCommand pak_strtoguid("pak_strtoguid", Pak_StringToGUID_f, "Calculates the GUID from input data", FCVAR_DEVELOPMENTONLY); + +static ConCommand pak_compress("pak_compress", Pak_Compress_f, "Compresses specified RPAK file", FCVAR_DEVELOPMENTONLY, RTech_PakCompress_f_CompletionFunc); +static ConCommand pak_decompress("pak_decompress", Pak_Decompress_f, "Decompresses specified RPAK file", FCVAR_DEVELOPMENTONLY, RTech_PakDecompress_f_CompletionFunc); + +static ConCommand pak_requestload("pak_requestload", Pak_RequestLoad_f, "Requests asynchronous load for specified RPAK file", FCVAR_DEVELOPMENTONLY, RTech_PakLoad_f_CompletionFunc); +static ConCommand pak_requestunload("pak_requestunload", Pak_RequestUnload_f, "Requests unload for specified RPAK file or ID", FCVAR_DEVELOPMENTONLY, RTech_PakUnload_f_CompletionFunc); + +static ConCommand pak_swap("pak_swap", Pak_Swap_f, "Requests swap for specified RPAK file or ID", FCVAR_DEVELOPMENTONLY); + +static ConCommand pak_listpaks("pak_listpaks", Pak_ListPaks_f, "Display a list of the loaded Pak files", FCVAR_RELEASE); +static ConCommand pak_listtypes("pak_listtypes", Pak_ListTypes_f, "Display a list of the registered asset types", FCVAR_RELEASE); + + +// Symbols taken from R2 dll's. +PakLoadFuncs_s* g_pakLoadApi = nullptr; diff --git a/src/rtech/pak/pakstate.h b/src/rtech/pak/pakstate.h index f3efb868..c2c08f28 100644 --- a/src/rtech/pak/pakstate.h +++ b/src/rtech/pak/pakstate.h @@ -6,7 +6,50 @@ #include "rtech/ipakfile.h" +struct PakLoadFuncs_s +{ + void* Initialize; // Returns the pak handle of the patch master RPak once initialized. + void* RegisterAsset; + char unknown0[8]; + PakHandle_t(*LoadAsync)(const char* pakFileName, CAlignedMemAlloc* allocator, int nIdx, bool bUnk); + void* LoadAsyncAndWait; + void (*UnloadAsync)(PakHandle_t handle); + void* UnloadAsyncAndWait; + char unknown2[16]; + void* Func7; + void* Func8; + EPakStatus(*WaitAsync)(PakHandle_t handle, void* finishCallback); + void* Func10; + void* Func11; + void* FindByGUID; + void* FindByName; + char unknown3[8]; + void* Func14; + void* Func15; + void* Func16; + void* Func17; + void* Func18; + void* IncrementStreamingAssetCount; + void* DecrementStreamingAssetCount; + void* IsFullStreamingInstall; + char unknown4[48]; + int (*OpenAsyncFile)(const char* const fileName, int logLevel, size_t* const outFileSize); + void (*CloseAsyncFile)(short fileHandle); + void* Func24; + void* Func25; + void* ReadAsyncFile; + void* ReadAsyncFileWithUserData; + uint8_t(*CheckAsyncRequest)(int idx, size_t* const bytesProcessed, const char** const statusMsg); + uint8_t(*WaitAndCheckAsyncRequest)(int idx, size_t* const bytesProcessed, const char** const statusMsg); + void* WaitForAsyncFileRead; + void* Func31; + void* Func32; + void* Func33; +}; + inline PakGlobals_s* g_pakGlobals; +extern PakLoadFuncs_s* g_pakLoadApi; + inline JobHelpCallback_t g_pPakFifoLockWrapper; // Pointer to functor that takes the global pak fifolock as argument. // TODO: rename to 'g_bPakFifoLockAcquiredInMainThread' @@ -21,6 +64,7 @@ class V_PakState : public IDetour virtual void GetAdr(void) const { LogVarAdr("g_pakGlobals", g_pakGlobals); + LogVarAdr("g_pakLoadApi", g_pakLoadApi); LogVarAdr("g_pakFifoLockWrapper", g_pPakFifoLockWrapper); LogVarAdr("g_pakFifoLockAcquired", g_bPakFifoLockAcquired); @@ -28,7 +72,8 @@ class V_PakState : public IDetour virtual void GetFun(void) const { } virtual void GetVar(void) const { - g_pakGlobals = g_GameDll.FindPatternSIMD("48 8D 1D ?? ?? ?? ?? 45 8D 5A 0E").ResolveRelativeAddressSelf(0x3, 0x7).RCast(); /*48 8D 1D ? ? ? ? 45 8D 5A 0E*/ + g_pakGlobals = g_GameDll.FindPatternSIMD("48 8D 1D ?? ?? ?? ?? 45 8D 5A 0E").ResolveRelativeAddressSelf(0x3, 0x7).RCast(); + g_pakLoadApi = CMemory(v_LauncherMain).Offset(0x820).FindPatternSelf("48 89").ResolveRelativeAddressSelf(0x3, 0x7).RCast(); const CMemory jtBase(JT_HelpWithAnything); diff --git a/src/rtech/playlists/playlists.cpp b/src/rtech/playlists/playlists.cpp index 50039276..059bbe59 100644 --- a/src/rtech/playlists/playlists.cpp +++ b/src/rtech/playlists/playlists.cpp @@ -11,6 +11,19 @@ KeyValues** g_pPlaylistKeyValues = nullptr; // Get the KeyValue for the playlist vector g_vAllPlaylists = { "<>" }; std::mutex g_PlaylistsVecMutex; +/* +===================== +Host_ReloadPlaylists_f +===================== +*/ +static void Host_ReloadPlaylists_f() +{ + v_Playlists_Download_f(); + Playlists_SDKInit(); // Re-Init playlist. +} + +static ConCommand playlist_reload("playlist_reload", Host_ReloadPlaylists_f, "Reloads the playlists file", FCVAR_RELEASE); + //----------------------------------------------------------------------------- // Purpose: Initializes the playlist globals //----------------------------------------------------------------------------- diff --git a/src/rtech/playlists/playlists.h b/src/rtech/playlists/playlists.h index 735a134e..32b4f0cd 100644 --- a/src/rtech/playlists/playlists.h +++ b/src/rtech/playlists/playlists.h @@ -11,6 +11,7 @@ bool Playlists_Parse(const char* pszPlaylist); inline bool(*v_Playlists_Load)(const char* pszPlaylist); inline bool(*v_Playlists_Parse)(const char* pszPlaylist); inline const char* (*v_Playlists_GetCurrent)(void); +inline void(*v_Playlists_Download_f)(void); extern KeyValues** g_pPlaylistKeyValues; @@ -25,6 +26,7 @@ class VPlaylists : public IDetour LogFunAdr("Playlists_Load", v_Playlists_Load); LogFunAdr("Playlists_Parse", v_Playlists_Parse); LogFunAdr("Playlists_GetCurrent", v_Playlists_GetCurrent); + LogFunAdr("Playlists_Download_f", v_Playlists_Download_f); LogVarAdr("g_pPlaylistKeyValues", g_pPlaylistKeyValues); } virtual void GetFun(void) const @@ -32,6 +34,7 @@ class VPlaylists : public IDetour g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 56 57 41 56 48 83 EC 40 48 8B F1").GetPtr(v_Playlists_Load); g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? 80 3D ?? ?? ?? ?? ?? 74 0C").FollowNearCallSelf().GetPtr(v_Playlists_Parse); g_GameDll.FindPatternSIMD("48 8B 05 ?? ?? ?? ?? 48 85 C0 75 08 48 8D 05 ?? ?? ?? ?? C3 0F B7 50 2A").GetPtr(v_Playlists_GetCurrent); + g_GameDll.FindPatternSIMD("33 C9 C6 05 ?? ?? ?? ?? ?? E9 ?? ?? ?? ??").GetPtr(v_Playlists_Download_f); } virtual void GetVar(void) const { diff --git a/src/tier0/commandline.cpp b/src/tier0/commandline.cpp index 38526d69..8cb9dd18 100644 --- a/src/tier0/commandline.cpp +++ b/src/tier0/commandline.cpp @@ -86,7 +86,7 @@ void CCommandLine::AppendParametersFromFile(const char* const pszConfig) } /////////////////////////////////////////////////////////////////////////////// -CCommandLine* g_pCmdLine = nullptr; +CCommandLine* g_pCmdLine = CModule::GetExportedSymbol(CModule::GetProcessEnvironmentBlock()->ImageBaseAddress, "g_pCmdLine").RCast(); void VCommandLine::Detour(const bool bAttach) const diff --git a/src/tier1/convar.cpp b/src/tier1/convar.cpp index 10317c80..9dd0c692 100644 --- a/src/tier1/convar.cpp +++ b/src/tier1/convar.cpp @@ -7,13 +7,238 @@ #include "tier1/convar.h" //----------------------------------------------------------------------------- -// Purpose: Checks if ConCommand has requested flags. -// Input : nFlags - -// Output : True if ConCommand has nFlags. +// Statically constructed list of ConCommandBases, +// used for registering them with the ICVar interface //----------------------------------------------------------------------------- -bool ConCommandBase::HasFlags(int nFlags) const +ConCommandBase* ConCommandBase::s_pConCommandBases = NULL; +IConCommandBaseAccessor* ConCommandBase::s_pAccessor = NULL; + +static int s_nCVarFlag = 0; + +// An unique identifier indicating which DLL this convar came from +static int s_nDLLIdentifier = -1; +static bool s_bRegistered = false; + +class CDefaultAccessor : public IConCommandBaseAccessor { - return m_nFlags & nFlags; +public: + virtual bool RegisterConCommandBase(ConCommandBase* const pVar) + { + // Link to engine's list instead + g_pCVar->RegisterConCommand(pVar); + return true; + } +}; + +static CDefaultAccessor s_DefaultAccessor; + +//----------------------------------------------------------------------------- +// Called by the framework to register ConCommandBases with the ICVar +//----------------------------------------------------------------------------- +void ConVar_Register(int nCVarFlag, IConCommandBaseAccessor* pAccessor) +{ + if (!g_pCVar || s_bRegistered) + return; + + Assert(s_nDLLIdentifier < 0); + s_bRegistered = true; + s_nCVarFlag = nCVarFlag; + s_nDLLIdentifier = g_pCVar->AllocateDLLIdentifier(); + + ConCommandBase* pCur, * pNext; + + ConCommandBase::s_pAccessor = pAccessor ? pAccessor : &s_DefaultAccessor; + pCur = ConCommandBase::s_pConCommandBases; + + while (pCur) + { + pNext = pCur->m_pNext; + pCur->AddFlags(s_nCVarFlag); + pCur->Init(); + pCur = pNext; + } + + g_pCVar->ProcessQueuedMaterialThreadConVarSets(); + + ConCommandBase::s_pConCommandBases = NULL; +} + +void ConVar_Unregister() +{ + if (!g_pCVar || !s_bRegistered) + return; + + Assert(s_nDLLIdentifier >= 0); + + // Do this after unregister!!! + g_pCVar->UnregisterConCommands(s_nDLLIdentifier); + s_nDLLIdentifier = -1; + s_bRegistered = false; +} + +//----------------------------------------------------------------------------- +// Purpose: Returns true if this is a command +//----------------------------------------------------------------------------- +bool ConCommandBase::IsCommand(void) const +{ + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: Checks if ConCommand has requested flags. +// Input : flag - +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool ConCommandBase::IsFlagSet(const int flag) const +{ + return (flag & m_nFlags) ? true : false; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : flags - +//----------------------------------------------------------------------------- +void ConCommandBase::AddFlags(const int flags) +{ + m_nFlags |= flags; +} + +//----------------------------------------------------------------------------- +// Purpose: removes specified flags +//----------------------------------------------------------------------------- +void ConCommandBase::RemoveFlags(const int flags) +{ + m_nFlags &= ~flags; +} + +//----------------------------------------------------------------------------- +// Purpose: returns current flags +//----------------------------------------------------------------------------- +int ConCommandBase::GetFlags() const +{ + return m_nFlags; +} + +//----------------------------------------------------------------------------- +// Purpose: Return name of the command/var +// Output : const char +//----------------------------------------------------------------------------- +const char* ConCommandBase::GetName(void) const +{ + return m_pszName; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : const char +//----------------------------------------------------------------------------- +const char* ConCommandBase::GetHelpText(void) const +{ + return m_pszHelpString; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : const char +//----------------------------------------------------------------------------- +const char* ConCommandBase::GetUsageText(void) const +{ + return m_pszUsageString; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void ConCommandBase::SetAccessor(IConCommandBaseAccessor* const pAccessor) +{ + m_pAccessor = pAccessor; +} + +//----------------------------------------------------------------------------- +// Purpose: Has this cvar been registered +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool ConCommandBase::IsRegistered(void) const +{ + return m_bRegistered; +} + +//----------------------------------------------------------------------------- +// Purpose: Returns the DLL identifier +//----------------------------------------------------------------------------- +int ConCommandBase::GetDLLIdentifier(void) const +{ + return s_nDLLIdentifier; +} + +//----------------------------------------------------------------------------- +// Purpose: Used internally by OneTimeInit to initialize. +//----------------------------------------------------------------------------- +void ConCommandBase::Init() +{ + if (s_pAccessor) + { + s_pAccessor->RegisterConCommandBase(this); + } +} + +void ConCommandBase::Shutdown() +{ + if (g_pCVar) + { + g_pCVar->UnregisterConCommand(this); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *pName - +// callback - +// *pHelpString - +// flags - +//----------------------------------------------------------------------------- +ConCommandBase* ConCommandBase::Create(const char* pName, const char* pHelpString, int flags, const char* pszUsageString) +{ + m_bRegistered = false; + + // Name should be static data + Assert(pName); + m_pszName = pName; + + m_pszHelpString = pHelpString ? pHelpString : ""; + m_pszUsageString = pszUsageString ? pszUsageString : ""; + + m_pAccessor = nullptr; + + m_nFlags = flags; + + const int releaseMask = FCVAR_ARCHIVE|FCVAR_USERINFO|FCVAR_CHEAT| + FCVAR_RELEASE|FCVAR_ARCHIVE_PLAYERPROFILE|FCVAR_CLIENTCMD_CAN_EXECUTE; + + if (!(m_nFlags & releaseMask)) + { + m_nFlags |= FCVAR_DEVELOPMENTONLY; + } + + if (!(m_nFlags & FCVAR_UNREGISTERED)) + { + m_pNext = s_pConCommandBases; + s_pConCommandBases = this; + } + else + { + // It's unregistered + m_pNext = NULL; + } + + // If s_pAccessor is already set (this ConVar is not a global variable), + // register it. + if (s_pAccessor) + { + Init(); + } + + return m_pNext; } //----------------------------------------------------------------------------- @@ -65,50 +290,144 @@ int DefaultCompletionFunc(const char* partial, char commands[COMMAND_COMPLETION_ return 0; } -//----------------------------------------------------------------------------- -// Purpose: create -//----------------------------------------------------------------------------- -ConCommand* ConCommand::StaticCreate(const char* pszName, const char* pszHelpString, const char* pszUsageString, - int nFlags, FnCommandCallback_t pCallback, FnCommandCompletionCallback pCompletionFunc) +ConCommand::ConCommand(const char* pName, FnCommandCallbackV1_t callback, const char* pHelpString /*= 0*/, + int flags /*= 0*/, FnCommandCompletionCallback completionFunc /*= 0*/, const char* pszUsageString /*= 0*/) { - ConCommand* pCommand = (ConCommand*)malloc(sizeof(ConCommand)); - *(ConCommand**)pCommand = g_pConCommandVFTable; + m_nNullCallBack = DefaultNullSub; + m_pSubCallback = nullptr; - pCommand->m_pNext = nullptr; - pCommand->m_bRegistered = false; + // Set the callback + m_fnCommandCallbackV1 = callback; + m_bUsingNewCommandCallback = false; + m_bUsingCommandCallbackInterface = false; + m_fnCompletionCallback = completionFunc ? completionFunc : DefaultCompletionFunc; + m_bHasCompletionCallback = completionFunc != 0 ? true : false; - pCommand->m_pszName = pszName; - pCommand->m_pszHelpString = pszHelpString; - pCommand->m_pszUsageString = pszUsageString; - pCommand->s_pAccessor = nullptr; - pCommand->m_nFlags = nFlags; + // Setup the rest + BaseClass::Create(pName, pHelpString, flags, pszUsageString); +} - pCommand->m_nNullCallBack = DefaultNullSub; - pCommand->m_pSubCallback = nullptr; - pCommand->m_fnCommandCallback = pCallback; - pCommand->m_bHasCompletionCallback = pCompletionFunc != nullptr ? true : false; - pCommand->m_bUsingNewCommandCallback = true; - pCommand->m_bUsingCommandCallbackInterface = false; - pCommand->m_fnCompletionCallback = pCompletionFunc ? pCompletionFunc : DefaultCompletionFunc; +ConCommand::ConCommand(const char* pName, FnCommandCallback_t callback, const char* pHelpString /*= 0*/, + int flags /*= 0*/, FnCommandCompletionCallback completionFunc /*= 0*/, const char* pszUsageString /*= 0*/) +{ + m_nNullCallBack = DefaultNullSub; + m_pSubCallback = nullptr; - g_pCVar->RegisterConCommand(pCommand); - return pCommand; + // Set the callback + m_fnCommandCallback = callback; + m_bUsingNewCommandCallback = true; + m_fnCompletionCallback = completionFunc ? completionFunc : DefaultCompletionFunc; + m_bHasCompletionCallback = completionFunc != 0 ? true : false; + m_bUsingCommandCallbackInterface = false; + + // Setup the rest + BaseClass::Create(pName, pHelpString, flags, pszUsageString); +} + +ConCommand::ConCommand(const char* pName, ICommandCallback* pCallback, const char* pHelpString /*= 0*/, + int flags /*= 0*/, ICommandCompletionCallback* pCompletionCallback /*= 0*/, const char* pszUsageString /*= 0*/) +{ + m_nNullCallBack = DefaultNullSub; + m_pSubCallback = nullptr; + + // Set the callback + m_pCommandCallback = pCallback; + m_bUsingNewCommandCallback = false; + m_pCommandCompletionCallback = pCompletionCallback; + m_bHasCompletionCallback = (pCompletionCallback != 0); + m_bUsingCommandCallbackInterface = true; + + // Setup the rest + BaseClass::Create(pName, pHelpString, flags, pszUsageString); } //----------------------------------------------------------------------------- -// Purpose: construct/allocate +// Purpose: destructor //----------------------------------------------------------------------------- -ConCommand::ConCommand() - : m_nNullCallBack(nullptr) - , m_pSubCallback(nullptr) - , m_fnCommandCallbackV1(nullptr) - , m_fnCompletionCallback(nullptr) - , m_bHasCompletionCallback(false) - , m_bUsingNewCommandCallback(false) - , m_bUsingCommandCallbackInterface(false) +ConCommand::~ConCommand() { } +//----------------------------------------------------------------------------- +// Purpose: Returns true if this is a command +//----------------------------------------------------------------------------- +bool ConCommand::IsCommand(void) const +{ + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: calls the autocompletion method to get autocompletion suggestions +//----------------------------------------------------------------------------- +int ConCommand::AutoCompleteSuggest(const char* partial, CUtlVector< CUtlString >& commands) +{ + if (m_bUsingCommandCallbackInterface) + { + if (!m_pCommandCompletionCallback) + return 0; + + return m_pCommandCompletionCallback->CommandCompletionCallback(partial, commands); + } + + Assert(m_fnCompletionCallback); + + if (!m_fnCompletionCallback) + return 0; + + char rgpchCommands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH]; + const int iret = (m_fnCompletionCallback)(partial, rgpchCommands); + + for (int i = 0; i < iret; ++i) + { + const CUtlString str = rgpchCommands[i]; + commands.AddToTail(str); + } + + return iret; +} + +//----------------------------------------------------------------------------- +// Returns true if the console command can autocomplete +//----------------------------------------------------------------------------- +bool ConCommand::CanAutoComplete(void) const +{ + return m_bHasCompletionCallback; +} + +//----------------------------------------------------------------------------- +// Purpose: invoke the function if there is one +//----------------------------------------------------------------------------- +void ConCommand::Dispatch(const CCommand& command) +{ + if (m_bUsingNewCommandCallback) + { + if (m_fnCommandCallback) + { + (*m_fnCommandCallback)(command); + return; + } + } + else if (m_bUsingCommandCallbackInterface) + { + if (m_pCommandCallback) + { + m_pCommandCallback->CommandCallback(command); + return; + } + } + else + { + if (m_fnCommandCallbackV1) + { + (*m_fnCommandCallbackV1)(); + return; + } + } + + // Command without callback!!! + AssertMsg(0, "Encountered ConCommand '%s' without a callback!\n", GetName()); +} + //----------------------------------------------------------------------------- // Purpose: create //----------------------------------------------------------------------------- @@ -126,7 +445,7 @@ ConVar* ConVar::StaticCreate(const char* pszName, const char* pszDefaultValue, pNewConVar->m_pszName = nullptr; pNewConVar->m_pszHelpString = nullptr; pNewConVar->m_pszUsageString = nullptr; - pNewConVar->s_pAccessor = nullptr; + pNewConVar->m_pAccessor = nullptr; pNewConVar->m_nFlags = FCVAR_NONE; pNewConVar->m_pNext = nullptr; diff --git a/src/tier1/cvar.cpp b/src/tier1/cvar.cpp index 83f07a89..81c2addd 100644 --- a/src/tier1/cvar.cpp +++ b/src/tier1/cvar.cpp @@ -675,11 +675,69 @@ int CCvarUtilities::CvarFindFlagsCompletionCallback(const char* partial, return values; } +/* +===================== +CON_Help_f + + Shows the colors and + description of each + context. +===================== +*/ +static void CON_Help_f() +{ + Msg(eDLL_T::COMMON, "Contexts:\n"); + + Msg(eDLL_T::SCRIPT_SERVER, " = Server DLL (Script)\n"); + Msg(eDLL_T::SCRIPT_CLIENT, " = Client DLL (Script)\n"); + Msg(eDLL_T::SCRIPT_UI, " = UI DLL (Script)\n"); + + Msg(eDLL_T::SERVER, " = Server DLL (Code)\n"); + Msg(eDLL_T::CLIENT, " = Client DLL (Code)\n"); + Msg(eDLL_T::UI, " = UI DLL (Code)\n"); + + Msg(eDLL_T::ENGINE, " = Engine DLL (Code)\n"); + Msg(eDLL_T::FS, " = FileSystem (Code)\n"); + Msg(eDLL_T::RTECH, " = PakLoad API (Code)\n"); + Msg(eDLL_T::MS, " = MaterialSystem (Code)\n"); + + Msg(eDLL_T::AUDIO, " = Audio DLL (Code)\n"); + Msg(eDLL_T::VIDEO, " = Video DLL (Code)\n"); + Msg(eDLL_T::NETCON, " = NetConsole (Code)\n"); +} + +static ConCommand con_help("con_help", CON_Help_f, "Shows the colors and description of each context", FCVAR_RELEASE); + /////////////////////////////////////////////////////////////////////////////// -CCvar* g_pCVar = nullptr; +CCvar* g_pCVar = CModule::GetExportedSymbol(CModule::GetProcessEnvironmentBlock()->ImageBaseAddress, "g_pCVar").RCast(); + + +static bool CVar_Connect(CCvar* thisptr, CreateInterfaceFn factory) +{ + CCvar__Connect(thisptr, factory); + + ConVar_InitShipped(); + ConVar_PurgeShipped(); + ConCommand_InitShipped(); + ConCommand_PurgeShipped(); + + ConVar_Register(); + + // CCvar::Connect() always returns true in the implementation of the engine + return true; +} + +static void CVar_Disconnect(CCvar* thisptr) +{ + ConVar_Unregister(); + CCvar__Disconnect(thisptr); +} /////////////////////////////////////////////////////////////////////////////// void VCVar::Detour(const bool bAttach) const { + DetourSetup(&CCvar__Connect, &CVar_Connect, bAttach); + DetourSetup(&CCvar__Disconnect, &CVar_Disconnect, bAttach); + DetourSetup(&v_ConVar_PrintDescription, &ConVar_PrintDescription, bAttach); }