diff --git a/src/Components/Modules/Bans.cpp b/src/Components/Modules/Bans.cpp index 1457f85d..f1cac387 100644 --- a/src/Components/Modules/Bans.cpp +++ b/src/Components/Modules/Bans.cpp @@ -225,7 +225,7 @@ namespace Components { Command::Add("banClient", [](Command::Params* params) { - if (!Dvar::Var("sv_running").get()) + if (!(*Game::com_sv_running)->current.enabled) { Logger::Print("Server is not running.\n"); return; @@ -269,7 +269,7 @@ namespace Components Command::Add("unbanClient", [](Command::Params* params) { - if (!Dvar::Var("sv_running").get()) + if (!(*Game::com_sv_running)->current.enabled) { Logger::Print("Server is not running.\n"); return; diff --git a/src/Components/Modules/Branding.cpp b/src/Components/Modules/Branding.cpp index e878e625..6f1c3fbf 100644 --- a/src/Components/Modules/Branding.cpp +++ b/src/Components/Modules/Branding.cpp @@ -5,7 +5,6 @@ namespace Components Dvar::Var Branding::CGDrawVersion; Dvar::Var Branding::CGDrawVersionX; Dvar::Var Branding::CGDrawVersionY; - Game::dvar_t** Branding::Version = reinterpret_cast(0x1AD7930); #ifdef _DEBUG constexpr auto* BUILD_TYPE = "IW4x_DEV MP"; @@ -25,12 +24,12 @@ namespace Components auto* const placement = Game::ScrPlace_GetUnsafeFullPlacement(); auto* const font = Game::UI_GetFontHandle(placement, 0, 0.583f); - const auto width = Game::UI_TextWidth((*Version)->current.string, 0, font, fontScale); + const auto width = Game::UI_TextWidth((*Game::version)->current.string, 0, font, fontScale); const auto height = Game::UI_TextHeight(font, fontScale); - Game::UI_DrawText(placement, (*Version)->current.string, maxChars, font, 1.0f - (CGDrawVersionX.get() + static_cast(width)), + Game::UI_DrawText(placement, (*Game::version)->current.string, maxChars, font, 1.0f - (CGDrawVersionX.get() + static_cast(width)), 1.0f - (CGDrawVersionY.get() + static_cast(height)), 3, 3, fontScale, shadowColor, 0); - Game::UI_DrawText(placement, (*Version)->current.string, maxChars, font, (0.0f - static_cast(width)) - CGDrawVersionX.get(), + Game::UI_DrawText(placement, (*Game::version)->current.string, maxChars, font, (0.0f - static_cast(width)) - CGDrawVersionX.get(), (0.0f - static_cast(height)) - CGDrawVersionY.get(), 3, 3, fontScale, color, 0); } diff --git a/src/Components/Modules/Branding.hpp b/src/Components/Modules/Branding.hpp index b8424ae4..f70fdcdd 100644 --- a/src/Components/Modules/Branding.hpp +++ b/src/Components/Modules/Branding.hpp @@ -14,7 +14,6 @@ namespace Components static Dvar::Var CGDrawVersion; static Dvar::Var CGDrawVersionX; static Dvar::Var CGDrawVersionY; - static Game::dvar_t** Version; static void CG_DrawVersion(); static void CG_DrawVersion_Hk(int localClientNum); diff --git a/src/Components/Modules/Bullet.cpp b/src/Components/Modules/Bullet.cpp index fe18981a..03f9f311 100644 --- a/src/Components/Modules/Bullet.cpp +++ b/src/Components/Modules/Bullet.cpp @@ -7,10 +7,10 @@ namespace Components float Bullet::BG_GetSurfacePenetrationDepthStub(const Game::WeaponDef* weapDef, int surfaceType) { - assert(weapDef != nullptr); - assert(weapDef->penetrateType != Game::PenetrateType::PENETRATE_TYPE_NONE); - assert(weapDef->penetrateType < Game::PenetrateType::PENETRATE_TYPE_COUNT); - assert(static_cast(surfaceType) < Game::materialSurfType_t::SURF_TYPE_COUNT); + assert(weapDef); + assert(weapDef->penetrateType != Game::PENETRATE_TYPE_NONE); + AssertIn(weapDef->penetrateType, Game::PENETRATE_TYPE_COUNT); + AssertIn(surfaceType, Game::SURF_TYPE_COUNT); const auto penetrationDepth = BGSurfacePenetration.get(); if (penetrationDepth > 0.0f) diff --git a/src/Components/Modules/Chat.cpp b/src/Components/Modules/Chat.cpp index 37c55e37..bea084b5 100644 --- a/src/Components/Modules/Chat.cpp +++ b/src/Components/Modules/Chat.cpp @@ -287,7 +287,7 @@ namespace Components { Command::AddSV("muteClient", [](Command::Params* params) { - if (!Dvar::Var("sv_running").get()) + if (!(*Game::com_sv_running)->current.enabled) { Logger::Print("Server is not running.\n"); return; @@ -309,7 +309,7 @@ namespace Components Command::AddSV("unmute", [](Command::Params* params) { - if (!Dvar::Var("sv_running").get()) + if (!(*Game::com_sv_running)->current.enabled) { Logger::Print("Server is not running.\n"); return; diff --git a/src/Components/Modules/ClanTags.cpp b/src/Components/Modules/ClanTags.cpp index c3247f2b..a4074736 100644 --- a/src/Components/Modules/ClanTags.cpp +++ b/src/Components/Modules/ClanTags.cpp @@ -9,7 +9,7 @@ namespace Components const char* ClanTags::GetClanTagWithName(int clientNum, const char* playerName) { - assert(static_cast(clientNum) < Game::MAX_CLIENTS); + AssertIn(clientNum, Game::MAX_CLIENTS); if (ClientState[clientNum][0] == '\0') { @@ -96,7 +96,7 @@ namespace Components char* ClanTags::GamerProfile_GetClanName(int controllerIndex) { - assert(static_cast(controllerIndex) < Game::MAX_LOCAL_CLIENTS); + AssertIn(controllerIndex, Game::MAX_LOCAL_CLIENTS); assert(ClanName); CL_SanitizeClanName(); @@ -115,7 +115,7 @@ namespace Components void ClanTags::ClientUserinfoChanged(const char* s, int clientNum) { - assert(static_cast(clientNum) < Game::MAX_CLIENTS); + AssertIn(clientNum, Game::MAX_CLIENTS); auto* clanAbbrev = Game::Info_ValueForKey(s, "clanAbbrev"); @@ -224,7 +224,7 @@ namespace Components Game::PlayerCardData* ClanTags::PlayerCards_GetLiveProfileDataForController_Stub(const unsigned int controllerIndex) { auto* result = Utils::Hook::Call(0x463B90)(controllerIndex); - // controllerIndex should always be 0 + AssertIn(controllerIndex, Game::MAX_LOCAL_CLIENTS); Game::I_strncpyz(result->clanAbbrev, GamerProfile_GetClanName(static_cast(controllerIndex)), sizeof(Game::PlayerCardData::clanAbbrev)); return result; diff --git a/src/Components/Modules/ClientCommand.cpp b/src/Components/Modules/ClientCommand.cpp index fb052c94..bd620627 100644 --- a/src/Components/Modules/ClientCommand.cpp +++ b/src/Components/Modules/ClientCommand.cpp @@ -9,7 +9,7 @@ namespace Components { const auto entNum = ent->s.number; - if (!Dvar::Var("sv_cheats").get()) + if (!(*Game::g_cheats)->current.enabled) { Logger::Debug("Cheats are disabled!"); Game::SV_GameSendServerCommand(entNum, Game::SV_CMD_CAN_IGNORE, Utils::String::VA("%c \"GAME_CHEATSNOTENABLED\"", 0x65)); @@ -359,6 +359,8 @@ namespace Components ClientCommand::ClientCommand() { + AssertOffset(Game::playerState_s, stats, 0x150); + // Hook call to ClientCommand in SV_ExecuteClientCommand so we may add custom commands Utils::Hook(0x6259FA, ClientCommand::ClientCommandStub, HOOK_CALL).install()->quick(); diff --git a/src/Components/Modules/Console.cpp b/src/Components/Modules/Console.cpp index 586d0c42..c46f5f17 100644 --- a/src/Components/Modules/Console.cpp +++ b/src/Components/Modules/Console.cpp @@ -44,8 +44,8 @@ namespace Components void Console::RefreshStatus() { - const auto mapname = Dvar::Var("mapname").get(); - const auto hostname = TextRenderer::StripColors(Dvar::Var("sv_hostname").get()); + const std::string mapname = (*Game::sv_mapname)->current.string; + const auto hostname = TextRenderer::StripColors((*Game::sv_hostname)->current.string); if (Console::HasConsole) { diff --git a/src/Components/Modules/Dedicated.cpp b/src/Components/Modules/Dedicated.cpp index e2172144..cb1bb132 100644 --- a/src/Components/Modules/Dedicated.cpp +++ b/src/Components/Modules/Dedicated.cpp @@ -104,12 +104,12 @@ namespace Components Scheduler::Once([] { const auto partyEnable = Dvar::Var("party_enable").get(); - auto mapname = Dvar::Var("mapname").get(); + std::string mapname = (*Game::sv_mapname)->current.string; if (!partyEnable) // Time wrapping should not occur in party servers, but yeah... { if (mapname.empty()) mapname = "mp_rust"; - Command::Execute(Utils::String::VA("map %s", mapname.data()), false); + Command::Execute(Utils::String::VA("map %s", mapname.data()), true); } }, Scheduler::Pipeline::SERVER); @@ -330,7 +330,7 @@ namespace Components Scheduler::Loop([] { - if (Dvar::Var("sv_running").get()) + if ((*Game::com_sv_running)->current.enabled) { Dedicated::TransmitGuids(); } diff --git a/src/Components/Modules/Download.cpp b/src/Components/Modules/Download.cpp index 1efda662..b51d073c 100644 --- a/src/Components/Modules/Download.cpp +++ b/src/Components/Modules/Download.cpp @@ -354,9 +354,9 @@ namespace Components // Run this on the main thread Scheduler::Once([] { - auto fsGame = Dvar::Var("fs_game"); - fsGame.set(mod); - fsGame.get()->modified = true; + Game::Dvar_SetString(*Game::fs_gameDirVar, mod.data()); + const_cast(*Game::fs_gameDirVar)->modified = true; + mod.clear(); Command::Execute("closemenu mod_download_popmenu", false); @@ -594,7 +594,7 @@ namespace Components static std::string fsGamePre; static nlohmann::json jsonList; - std::string fsGame = Dvar::Var("fs_game").get(); + const std::string fsGame = (*Game::fs_gameDirVar)->current.string; if (!fsGame.empty() && fsGame != fsGamePre) { @@ -698,7 +698,7 @@ namespace Components } std::string file; - std::string fsGame = Dvar::Var("fs_game").get(); + const std::string fsGame = (*Game::fs_gameDirVar)->current.string; std::string path = Dvar::Var("fs_basepath").get() + "\\" + (isMap ? "" : fsGame + "\\") + url; if ((!isMap && fsGame.empty()) || !Utils::IO::ReadFile(path, &file)) @@ -750,7 +750,7 @@ namespace Components playerInfo["ping"] = 0; playerInfo["name"] = ""; - if (Dvar::Var("sv_running").get()) + if ((*Game::com_sv_running)->current.enabled) { if (Game::svs_clients[i].state < 3) continue; diff --git a/src/Components/Modules/Dvar.cpp b/src/Components/Modules/Dvar.cpp index 4334dd59..43806d72 100644 --- a/src/Components/Modules/Dvar.cpp +++ b/src/Components/Modules/Dvar.cpp @@ -4,33 +4,33 @@ namespace Components { const char* Dvar::ArchiveDvarPath = "userraw/archivedvars.cfg"; - Dvar::Var::Var(const std::string& dvarName) : Var() + Dvar::Var::Var(const std::string& dvarName) { - this->dvar = Game::Dvar_FindVar(dvarName.data()); + this->dvar_ = Game::Dvar_FindVar(dvarName.data()); // If the dvar can't be found it will be registered as an empty string dvar - if (this->dvar == nullptr) + if (this->dvar_ == nullptr) { - this->dvar = const_cast(Game::Dvar_SetFromStringByNameFromSource(dvarName.data(), "", + this->dvar_ = const_cast(Game::Dvar_SetFromStringByNameFromSource(dvarName.data(), "", Game::DvarSetSource::DVAR_SOURCE_INTERNAL)); } } template <> Game::dvar_t* Dvar::Var::get() { - return this->dvar; + return this->dvar_; } template <> const char* Dvar::Var::get() { - if (this->dvar == nullptr) + if (this->dvar_ == nullptr) return ""; - if (this->dvar->type == Game::dvar_type::DVAR_TYPE_STRING - || this->dvar->type == Game::dvar_type::DVAR_TYPE_ENUM) + if (this->dvar_->type == Game::DVAR_TYPE_STRING + || this->dvar_->type == Game::DVAR_TYPE_ENUM) { - if (this->dvar->current.string != nullptr) - return this->dvar->current.string; + if (this->dvar_->current.string != nullptr) + return this->dvar_->current.string; } return ""; @@ -38,12 +38,12 @@ namespace Components template <> int Dvar::Var::get() { - if (this->dvar == nullptr) + if (this->dvar_ == nullptr) return 0; - if (this->dvar->type == Game::dvar_type::DVAR_TYPE_INT || this->dvar->type == Game::dvar_type::DVAR_TYPE_ENUM) + if (this->dvar_->type == Game::DVAR_TYPE_INT || this->dvar_->type == Game::DVAR_TYPE_ENUM) { - return this->dvar->current.integer; + return this->dvar_->current.integer; } return 0; @@ -51,12 +51,12 @@ namespace Components template <> unsigned int Dvar::Var::get() { - if (this->dvar == nullptr) + if (this->dvar_ == nullptr) return 0; - if (this->dvar->type == Game::dvar_type::DVAR_TYPE_INT) + if (this->dvar_->type == Game::DVAR_TYPE_INT) { - return this->dvar->current.unsignedInt; + return this->dvar_->current.unsignedInt; } return 0; @@ -64,12 +64,12 @@ namespace Components template <> float Dvar::Var::get() { - if (this->dvar == nullptr) + if (this->dvar_ == nullptr) return 0.f; - if (this->dvar->type == Game::dvar_type::DVAR_TYPE_FLOAT) + if (this->dvar_->type == Game::DVAR_TYPE_FLOAT) { - return this->dvar->current.value; + return this->dvar_->current.value; } return 0.f; @@ -79,13 +79,13 @@ namespace Components { static Game::vec4_t vector{0.f, 0.f, 0.f, 0.f}; - if (this->dvar == nullptr) + if (this->dvar_ == nullptr) return vector; - if (this->dvar->type == Game::dvar_type::DVAR_TYPE_FLOAT_2 || this->dvar->type == Game::dvar_type::DVAR_TYPE_FLOAT_3 - || this->dvar->type == Game::dvar_type::DVAR_TYPE_FLOAT_4) + if (this->dvar_->type == Game::DVAR_TYPE_FLOAT_2 || this->dvar_->type == Game::DVAR_TYPE_FLOAT_3 + || this->dvar_->type == Game::DVAR_TYPE_FLOAT_4) { - return this->dvar->current.vector; + return this->dvar_->current.vector; } return vector; @@ -93,12 +93,12 @@ namespace Components template <> bool Dvar::Var::get() { - if (this->dvar == nullptr) + if (this->dvar_ == nullptr) return false; - if (this->dvar->type == Game::dvar_type::DVAR_TYPE_BOOL) + if (this->dvar_->type == Game::DVAR_TYPE_BOOL) { - return this->dvar->current.enabled; + return this->dvar_->current.enabled; } return false; @@ -111,10 +111,10 @@ namespace Components void Dvar::Var::set(const char* string) { - assert(this->dvar->type == Game::DVAR_TYPE_STRING); - if (this->dvar) + assert(this->dvar_->type == Game::DVAR_TYPE_STRING); + if (this->dvar_) { - Game::Dvar_SetString(this->dvar, string); + Game::Dvar_SetString(this->dvar_, string); } } @@ -125,58 +125,64 @@ namespace Components void Dvar::Var::set(int integer) { - assert(this->dvar->type == Game::DVAR_TYPE_INT); - if (this->dvar) + assert(this->dvar_->type == Game::DVAR_TYPE_INT); + + if (this->dvar_) { - Game::Dvar_SetInt(this->dvar, integer); + Game::Dvar_SetInt(this->dvar_, integer); } } void Dvar::Var::set(float value) { - assert(this->dvar->type == Game::DVAR_TYPE_FLOAT); - if (this->dvar) + assert(this->dvar_->type == Game::DVAR_TYPE_FLOAT); + + if (this->dvar_) { - Game::Dvar_SetFloat(this->dvar, value); + Game::Dvar_SetFloat(this->dvar_, value); } } void Dvar::Var::set(bool enabled) { - assert(this->dvar->type == Game::DVAR_TYPE_BOOL); - if (this->dvar) + assert(this->dvar_->type == Game::DVAR_TYPE_BOOL); + + if (this->dvar_) { - Game::Dvar_SetBool(this->dvar, enabled); + Game::Dvar_SetBool(this->dvar_, enabled); } } void Dvar::Var::setRaw(int integer) { - assert(this->dvar->type == Game::DVAR_TYPE_INT); - if (this->dvar) + assert(this->dvar_->type == Game::DVAR_TYPE_INT); + + if (this->dvar_) { - this->dvar->current.integer = integer; - this->dvar->latched.integer = integer; + this->dvar_->current.integer = integer; + this->dvar_->latched.integer = integer; } } void Dvar::Var::setRaw(float value) { - assert(this->dvar->type == Game::DVAR_TYPE_FLOAT); - if (this->dvar) + assert(this->dvar_->type == Game::DVAR_TYPE_FLOAT); + + if (this->dvar_) { - this->dvar->current.value = value; - this->dvar->latched.value = value; + this->dvar_->current.value = value; + this->dvar_->latched.value = value; } } void Dvar::Var::setRaw(bool enabled) { - assert(this->dvar->type == Game::DVAR_TYPE_BOOL); - if (this->dvar) + assert(this->dvar_->type == Game::DVAR_TYPE_BOOL); + + if (this->dvar_) { - this->dvar->current.enabled = enabled; - this->dvar->latched.enabled = enabled; + this->dvar_->current.enabled = enabled; + this->dvar_->latched.enabled = enabled; } } diff --git a/src/Components/Modules/Dvar.hpp b/src/Components/Modules/Dvar.hpp index b457f16b..dacee8ee 100644 --- a/src/Components/Modules/Dvar.hpp +++ b/src/Components/Modules/Dvar.hpp @@ -17,9 +17,9 @@ namespace Components class Var { public: - Var() : dvar(nullptr) {} - Var(const Var& obj) { this->dvar = obj.dvar; } - Var(Game::dvar_t* _dvar) : dvar(_dvar) {} + Var() : dvar_(nullptr) {} + Var(const Var& obj) { this->dvar_ = obj.dvar_; } + Var(Game::dvar_t* dvar) : dvar_(dvar) {} Var(DWORD ppdvar) : Var(*reinterpret_cast(ppdvar)) {} Var(const std::string& dvarName); @@ -37,7 +37,7 @@ namespace Components void setRaw(bool enabled); private: - Game::dvar_t* dvar; + Game::dvar_t* dvar_; }; Dvar(); diff --git a/src/Components/Modules/GSC/Script.cpp b/src/Components/Modules/GSC/Script.cpp index 7c68140a..8cd33cad 100644 --- a/src/Components/Modules/GSC/Script.cpp +++ b/src/Components/Modules/GSC/Script.cpp @@ -50,12 +50,10 @@ namespace Components void Script::RuntimeError(const char* codePos, unsigned int index, const char* msg, const char* dialogMessage) { - const auto developer = Dvar::Var("developer").get(); - // Allow error messages to be printed if developer mode is on // Should check scrVarPub.developer but it's absent // in this version of the game so let's check the dvar - if (!Game::scrVmPub->terminal_error && !developer) + if (!Game::scrVmPub->terminal_error && !(*Game::com_developer)->current.integer) return; // If were are developing let's call RuntimeErrorInternal @@ -630,7 +628,7 @@ namespace Components Utils::Hook(0x61E92E, Script::VMExecuteInternalStub, HOOK_JUMP).install()->quick(); Utils::Hook::Nop(0x61E933, 1); - Scheduler::Loop([]() + Scheduler::Loop([] { if (!Game::SV_Loaded()) return; @@ -639,11 +637,12 @@ namespace Components if (Script::LastFrameTime != -1) { - const auto timeScale = Dvar::Var("timescale").get(); - const auto timeTaken = static_cast((nowMs - Script::LastFrameTime) * timeScale); + const auto timeTaken = (nowMs - Script::LastFrameTime) * static_cast((*Game::com_timescale)->current.value); if (timeTaken >= 500) + { Logger::Print(Game::CON_CHANNEL_PARSERSCRIPT, "Hitch warning: {} msec frame time\n", timeTaken); + } } Script::LastFrameTime = nowMs; diff --git a/src/Components/Modules/MapRotation.cpp b/src/Components/Modules/MapRotation.cpp index 58d95dad..d8a29c29 100644 --- a/src/Components/Modules/MapRotation.cpp +++ b/src/Components/Modules/MapRotation.cpp @@ -5,10 +5,6 @@ namespace Components Dvar::Var MapRotation::SVRandomMapRotation; Dvar::Var MapRotation::SVDontRotate; - Game::dvar_t** MapRotation::SVMapRotation = reinterpret_cast(0x62C7C44); - Game::dvar_t** MapRotation::SVMapRotationCurrent = reinterpret_cast(0x2098DF0); - Game::dvar_t** MapRotation::SVMapname = reinterpret_cast(0x2098DDC); - MapRotation::RotationData MapRotation::DedicatedRotation; MapRotation::RotationData::RotationData() @@ -107,7 +103,7 @@ namespace Components } catch (const std::exception& ex) { - Logger::PrintError(Game::CON_CHANNEL_ERROR, "{}: {} contains invalid data!\n", ex.what(), (*SVMapRotation)->name); + Logger::PrintError(Game::CON_CHANNEL_ERROR, "{}: {} contains invalid data!\n", ex.what(), (*Game::sv_mapRotation)->name); } Logger::Debug("DedicatedRotation size after parsing is '{}'", DedicatedRotation.getEntriesSize()); @@ -178,7 +174,7 @@ namespace Components void MapRotation::RestartCurrentMap() { - std::string svMapname = (*SVMapname)->current.string; + std::string svMapname = (*Game::sv_mapname)->current.string; if (svMapname.empty()) { @@ -224,24 +220,24 @@ namespace Components assert(!data.empty()); // Ook, ook, eek - Logger::Warning(Game::CON_CHANNEL_SERVER, "You are using deprecated {}", (*SVMapRotationCurrent)->name); + Logger::Warning(Game::CON_CHANNEL_SERVER, "You are using deprecated {}", (*Game::sv_mapRotationCurrent)->name); RotationData rotationCurrent; try { - Logger::Debug("Parsing {}", (*SVMapRotationCurrent)->name); + Logger::Debug("Parsing {}", (*Game::sv_mapRotationCurrent)->name); rotationCurrent.parse(data); } catch (const std::exception& ex) { - Logger::PrintError(Game::CON_CHANNEL_ERROR, "{}: {} contains invalid data!\n", ex.what(), (*SVMapRotationCurrent)->name); + Logger::PrintError(Game::CON_CHANNEL_ERROR, "{}: {} contains invalid data!\n", ex.what(), (*Game::sv_mapRotationCurrent)->name); } - Game::Dvar_SetString(*SVMapRotationCurrent, ""); + Game::Dvar_SetString(*Game::sv_mapRotationCurrent, ""); if (rotationCurrent.getEntriesSize() == 0) { - Logger::Print(Game::CON_CHANNEL_SERVER, "{} is empty or contains invalid data. Restarting map\n", (*SVMapRotationCurrent)->name); + Logger::Print(Game::CON_CHANNEL_SERVER, "{} is empty or contains invalid data. Restarting map\n", (*Game::sv_mapRotationCurrent)->name); RestartCurrentMap(); return; } @@ -272,15 +268,15 @@ namespace Components Logger::Print(Game::CON_CHANNEL_SERVER, "Rotating map...\n"); // This takes priority because of backwards compatibility - const std::string mapRotationCurrent = (*SVMapRotationCurrent)->current.string; + const std::string mapRotationCurrent = (*Game::sv_mapRotationCurrent)->current.string; if (!mapRotationCurrent.empty()) { - Logger::Debug("Applying {}", (*SVMapRotationCurrent)->name); + Logger::Debug("Applying {}", (*Game::sv_mapRotationCurrent)->name); ApplyMapRotationCurrent(mapRotationCurrent); return; } - const std::string mapRotation = (*SVMapRotation)->current.string; + const std::string mapRotation = (*Game::sv_mapRotation)->current.string; // People may have sv_mapRotation empty because they only use 'addMap' or 'addGametype' if (!mapRotation.empty()) { @@ -290,7 +286,7 @@ namespace Components if (DedicatedRotation.getEntriesSize() == 0) { - Logger::Print(Game::CON_CHANNEL_SERVER, "{} is empty or contains invalid data. Restarting map\n", (*SVMapRotation)->name); + Logger::Print(Game::CON_CHANNEL_SERVER, "{} is empty or contains invalid data. Restarting map\n", (*Game::sv_mapRotation)->name); RestartCurrentMap(); return; } diff --git a/src/Components/Modules/MapRotation.hpp b/src/Components/Modules/MapRotation.hpp index 72ef8941..30e655cd 100644 --- a/src/Components/Modules/MapRotation.hpp +++ b/src/Components/Modules/MapRotation.hpp @@ -45,10 +45,6 @@ namespace Components // Rotation Dvars static Dvar::Var SVRandomMapRotation; static Dvar::Var SVDontRotate; - // Game Dvars - static Game::dvar_t** SVMapRotation; - static Game::dvar_t** SVMapRotationCurrent; - static Game::dvar_t** SVMapname; // Holds the parsed data from sv_mapRotation static RotationData DedicatedRotation; diff --git a/src/Components/Modules/Party.cpp b/src/Components/Modules/Party.cpp index d7b7f2cc..1b05c3dd 100644 --- a/src/Components/Modules/Party.cpp +++ b/src/Components/Modules/Party.cpp @@ -139,7 +139,7 @@ namespace Components bool Party::IsInLobby() { - return (!Dvar::Var("sv_running").get() && PartyEnable.get() && Dvar::Var("party_host").get()); + return (!(*Game::com_sv_running)->current.enabled && PartyEnable.get() && Dvar::Var("party_host").get()); } bool Party::IsInUserMapLobby() @@ -338,9 +338,9 @@ namespace Components Utils::InfoString info; info.set("challenge", Utils::ParseChallenge(data)); info.set("gamename", "IW4"); - info.set("hostname", Dvar::Var("sv_hostname").get()); - info.set("gametype", Dvar::Var("g_gametype").get()); - info.set("fs_game", Dvar::Var("fs_game").get()); + info.set("hostname", (*Game::sv_hostname)->current.string); + info.set("gametype", (*Game::sv_gametype)->current.string); + info.set("fs_game", (*Game::fs_gameDirVar)->current.string); info.set("xuid", Utils::String::VA("%llX", Steam::SteamUser()->GetSteamID().bits)); info.set("clients", Utils::String::VA("%i", clientCount)); info.set("bots", Utils::String::VA("%i", botCount)); @@ -416,7 +416,7 @@ namespace Components bool isUsermap = !info.get("usermaphash").empty(); unsigned int usermapHash = atoi(info.get("usermaphash").data()); - std::string mod = Dvar::Var("fs_game").get(); + std::string mod = (*Game::fs_gameDirVar)->current.string; // set fast server stuff here so its updated when we go to download stuff if (info.get("wwwDownload") == "1"s) @@ -468,7 +468,7 @@ namespace Components } else if (!Dvar::Var("fs_game").get().empty() && info.get("fs_game").empty()) { - Dvar::Var("fs_game").set(""); + Game::Dvar_SetString(*Game::fs_gameDirVar, ""); if (Dvar::Var("cl_modVidRestart").get()) { diff --git a/src/Components/Modules/Renderer.cpp b/src/Components/Modules/Renderer.cpp index 4c369e1e..16bb5b66 100644 --- a/src/Components/Modules/Renderer.cpp +++ b/src/Components/Modules/Renderer.cpp @@ -266,9 +266,8 @@ namespace Components float playerPosition[3]{ clientEntity->r.currentOrigin[0], clientEntity->r.currentOrigin[1], clientEntity->r.currentOrigin[2] }; - const auto mapName = Dvar::Var("mapname").get(); auto scene = Game::scene; - auto gfxAsset = Game::DB_FindXAssetEntry(Game::XAssetType::ASSET_TYPE_GFXWORLD, Utils::String::VA("maps/mp/%s.d3dbsp", mapName)); + auto gfxAsset = Game::DB_FindXAssetEntry(Game::XAssetType::ASSET_TYPE_GFXWORLD, Utils::String::VA("maps/mp/%s.d3dbsp", (*Game::sv_mapname)->current.string)); if (gfxAsset == nullptr) { @@ -368,9 +367,8 @@ namespace Components float playerPosition[3]{ clientEntity->r.currentOrigin[0], clientEntity->r.currentOrigin[1], clientEntity->r.currentOrigin[2] }; - const auto mapName = Dvar::Var("mapname").get(); auto scene = Game::scene; - auto gfxAsset = Game::DB_FindXAssetEntry(Game::XAssetType::ASSET_TYPE_GFXWORLD, Utils::String::VA("maps/mp/%s.d3dbsp", mapName)); + auto gfxAsset = Game::DB_FindXAssetEntry(Game::XAssetType::ASSET_TYPE_GFXWORLD, Utils::String::VA("maps/mp/%s.d3dbsp", (*Game::sv_mapname)->current.string)); if (gfxAsset == nullptr) { diff --git a/src/Components/Modules/ServerInfo.cpp b/src/Components/Modules/ServerInfo.cpp index 6707ef22..cdd1c4e6 100644 --- a/src/Components/Modules/ServerInfo.cpp +++ b/src/Components/Modules/ServerInfo.cpp @@ -139,7 +139,7 @@ namespace Components info.set("sv_maxclients", Utils::String::VA("%i", maxClientCount)); info.set("protocol", Utils::String::VA("%i", PROTOCOL)); info.set("shortversion", SHORTVERSION); - info.set("mapname", Dvar::Var("mapname").get()); + info.set("mapname", (*Game::sv_mapname)->current.string); info.set("isPrivate", (Dvar::Var("g_password").get().empty() ? "0" : "1")); info.set("checksum", Utils::String::VA("%X", Utils::Cryptography::JenkinsOneAtATime::Compute(Utils::String::VA("%u", Game::Sys_Milliseconds())))); @@ -158,7 +158,7 @@ namespace Components { info.set("matchtype", "1"); } - else if (Dvar::Var("sv_running").get()) // Match hosting + else if ((*Game::com_sv_running)->current.enabled) // Match hosting { info.set("matchtype", "2"); } @@ -202,7 +202,7 @@ namespace Components auto ping = 0; std::string name; - if (Dvar::Var("sv_running").get()) + if ((*Game::com_sv_running)->current.enabled) { if (Game::svs_clients[i].state < 3) continue; diff --git a/src/Components/Modules/Stats.cpp b/src/Components/Modules/Stats.cpp index dc807c37..ca710831 100644 --- a/src/Components/Modules/Stats.cpp +++ b/src/Components/Modules/Stats.cpp @@ -65,11 +65,11 @@ namespace Components int Stats::SaveStats(char* dest, const char* folder, const char* buffer, size_t length) { - const auto fs_game = Game::Dvar_FindVar("fs_game"); + assert(*Game::fs_gameDirVar); - if (fs_game && fs_game->current.string && strlen(fs_game->current.string) && !strncmp(fs_game->current.string, "mods/", 5)) + if (!std::strcmp((*Game::fs_gameDirVar)->current.string, "mods/")) { - folder = fs_game->current.string; + folder = (*Game::fs_gameDirVar)->current.string; } return Utils::Hook::Call(0x426450)(dest, folder, buffer, length); diff --git a/src/Components/Modules/TextRenderer.cpp b/src/Components/Modules/TextRenderer.cpp index 0fb0a268..11ac4766 100644 --- a/src/Components/Modules/TextRenderer.cpp +++ b/src/Components/Modules/TextRenderer.cpp @@ -1287,7 +1287,7 @@ namespace Components std::string TextRenderer::StripColors(const std::string& in) { - char buffer[1000] = { 0 }; // Should be more than enough + char buffer[1024] = {0}; // 1024 is a lucky number in the engine StripColors(in.data(), buffer, sizeof(buffer)); return std::string(buffer); } diff --git a/src/Components/Modules/Theatre.cpp b/src/Components/Modules/Theatre.cpp index e7d0fa41..97c94ab5 100644 --- a/src/Components/Modules/Theatre.cpp +++ b/src/Components/Modules/Theatre.cpp @@ -162,8 +162,8 @@ namespace Components Game::Com_Printf(channel, message, file); Theatre::CurrentInfo.name = file; - Theatre::CurrentInfo.mapname = Dvar::Var("mapname").get(); - Theatre::CurrentInfo.gametype = Dvar::Var("g_gametype").get(); + Theatre::CurrentInfo.mapname = (*Game::sv_mapname)->current.string; + Theatre::CurrentInfo.gametype = (*Game::sv_gametype)->current.string; Theatre::CurrentInfo.author = Steam::SteamFriends()->GetPersonaName(); Theatre::CurrentInfo.length = Game::Sys_Milliseconds(); std::time(&Theatre::CurrentInfo.timeStamp); diff --git a/src/Game/Dvars.cpp b/src/Game/Dvars.cpp new file mode 100644 index 00000000..fedf2e94 --- /dev/null +++ b/src/Game/Dvars.cpp @@ -0,0 +1,27 @@ +#include + +namespace Game +{ + const dvar_t** com_developer = reinterpret_cast(0x1AD78E8); + const dvar_t** com_developer_script = reinterpret_cast(0x1AD8F10); + const dvar_t** com_timescale = reinterpret_cast(0x1AD7920); + const dvar_t** com_sv_running = reinterpret_cast(0x1AD7934); + + const dvar_t** dev_timescale = reinterpret_cast(0x1AD8F20); + + const dvar_t** dvar_cheats = reinterpret_cast(0x63F3348); + + const dvar_t** fs_gameDirVar = reinterpret_cast(0x63D0CC0); + + const dvar_t** sv_hostname = reinterpret_cast(0x2098D98); + const dvar_t** sv_gametype = reinterpret_cast(0x2098DD4); + const dvar_t** sv_mapname = reinterpret_cast(0x2098DDC); + const dvar_t** sv_mapRotation = reinterpret_cast(0x62C7C44); + const dvar_t** sv_mapRotationCurrent = reinterpret_cast(0x2098DF0); + const dvar_t** sv_maxclients = reinterpret_cast(0x2098D90); + const dvar_t** sv_cheats = reinterpret_cast(0x2098DE0); + + const dvar_t** g_cheats = reinterpret_cast(0x1A45D54); + + const dvar_t** version = reinterpret_cast(0x1AD7930); +} diff --git a/src/Game/Dvars.hpp b/src/Game/Dvars.hpp new file mode 100644 index 00000000..3e4141a0 --- /dev/null +++ b/src/Game/Dvars.hpp @@ -0,0 +1,28 @@ +#pragma once + +// Put game dvars here +namespace Game +{ + extern const dvar_t** com_developer; + extern const dvar_t** com_developer_script; + extern const dvar_t** com_timescale; + extern const dvar_t** com_sv_running; + + extern const dvar_t** dev_timescale; + + extern const dvar_t** dvar_cheats; + + extern const dvar_t** fs_gameDirVar; + + extern const dvar_t** sv_hostname; + extern const dvar_t** sv_gametype; + extern const dvar_t** sv_mapname; + extern const dvar_t** sv_mapRotation; + extern const dvar_t** sv_mapRotationCurrent; + extern const dvar_t** sv_maxclients; + extern const dvar_t** sv_cheats; + + extern const dvar_t** g_cheats; + + extern const dvar_t** version; +} diff --git a/src/Game/Functions.cpp b/src/Game/Functions.cpp index 945557ec..69dca5b1 100644 --- a/src/Game/Functions.cpp +++ b/src/Game/Functions.cpp @@ -853,10 +853,9 @@ namespace Game void SV_GameDropClient(int clientNum, const char* reason) { - const auto maxClients = Dvar_FindVar("sv_maxclients")->current.integer; - assert(maxClients >= 1 && maxClients <= 18); + assert((*sv_maxclients)->current.integer >= 1 && (*sv_maxclients)->current.integer <= 18); - if (clientNum >= 0 && clientNum < maxClients) + if (clientNum >= 0 && clientNum < (*sv_maxclients)->current.integer) { SV_DropClient(&svs_clients[clientNum], reason, true); } diff --git a/src/STDInclude.hpp b/src/STDInclude.hpp index becd7189..32ca88af 100644 --- a/src/STDInclude.hpp +++ b/src/STDInclude.hpp @@ -107,6 +107,10 @@ using namespace std::literals; static_assert(offsetof(x, y) == (offset), \ #x "::" #y " is not at the right offset. Must be at " #offset) +#define AssertIn(x, y) assert(static_cast(x) < static_cast(y)) + +#define AssertUnreachable assert(0 && "unreachable") + // Protobuf #include "proto/session.pb.h" #include "proto/party.pb.h" @@ -143,6 +147,7 @@ using namespace std::literals; #include "Steam/Steam.hpp" // Some definitions are used in functions and structs #include "Game/Structs.hpp" +#include "Game/Dvars.hpp" #include "Game/Functions.hpp" #include #include diff --git a/src/Utils/Json.cpp b/src/Utils/Json.cpp index 6dd8ea9a..cbf963e3 100644 --- a/src/Utils/Json.cpp +++ b/src/Utils/Json.cpp @@ -2,7 +2,7 @@ namespace Utils::Json { - std::string TypeToString(nlohmann::json::value_t type) + std::string TypeToString(const nlohmann::json::value_t type) { switch (type) { @@ -27,6 +27,7 @@ namespace Utils::Json case nlohmann::json::value_t::discarded: return "discarded"; default: + AssertUnreachable; return "null"; } }