[General]: Fix some things (#667)

This commit is contained in:
Edo 2022-12-25 18:23:53 +01:00 committed by GitHub
parent 79758e1752
commit 01a629d02b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 368 additions and 393 deletions

View File

@ -21,7 +21,6 @@
| `--copy-to=PATH` | Optional, copy the DLL to a custom folder after build, define the path here if wanted. | | `--copy-to=PATH` | Optional, copy the DLL to a custom folder after build, define the path here if wanted. |
| `--copy-pdb` | Copy debug information for binaries as well to the path given via --copy-to. | | `--copy-pdb` | Copy debug information for binaries as well to the path given via --copy-to. |
| `--force-unit-tests` | Always compile unit tests. | | `--force-unit-tests` | Always compile unit tests. |
| `--force-exception-handler` | Install custom unhandled exception handler even for Debug builds. |
| `--disable-binary-check` | Do not perform integrity checks on the exe. | | `--disable-binary-check` | Do not perform integrity checks on the exe. |
## Command line arguments ## Command line arguments

View File

@ -76,11 +76,6 @@ newoption {
description = "Always compile unit tests." description = "Always compile unit tests."
} }
newoption {
trigger = "force-exception-handler",
description = "Install custom unhandled exception handler even for Debug builds."
}
newoption { newoption {
trigger = "disable-binary-check", trigger = "disable-binary-check",
description = "Do not perform integrity checks on the exe." description = "Do not perform integrity checks on the exe."
@ -257,9 +252,6 @@ workspace "iw4x"
if _OPTIONS["force-unit-tests"] then if _OPTIONS["force-unit-tests"] then
defines {"FORCE_UNIT_TESTS"} defines {"FORCE_UNIT_TESTS"}
end end
if _OPTIONS["force-exception-handler"] then
defines {"FORCE_EXCEPTION_HANDLER"}
end
if _OPTIONS["disable-binary-check"] then if _OPTIONS["disable-binary-check"] then
defines {"DISABLE_BINARY_CHECK"} defines {"DISABLE_BINARY_CHECK"}
end end

View File

@ -9,128 +9,128 @@ namespace Components
bool Loader::IsPregame() bool Loader::IsPregame()
{ {
return Loader::Pregame; return Pregame;
} }
bool Loader::IsPostgame() bool Loader::IsPostgame()
{ {
return Loader::Postgame; return Postgame;
} }
bool Loader::IsUninitializing() bool Loader::IsUninitializing()
{ {
return Loader::Uninitializing; return Uninitializing;
} }
void Loader::Initialize() void Loader::Initialize()
{ {
Loader::Pregame = true; Pregame = true;
Loader::Postgame = false; Postgame = false;
Loader::Uninitializing = false; Uninitializing = false;
Utils::Memory::GetAllocator()->clear(); Utils::Memory::GetAllocator()->clear();
Loader::Register(new Flags()); Register(new Auth());
Loader::Register(new Singleton()); Register(new Command());
// Install our exception handler as early as posssible to get better debug dumps from startup crashes Register(new Dvar());
Loader::Register(new Exception()); Register(new Exception()); // Install our exception handler as early as posssible to get better debug dumps from startup crashes
Loader::Register(new Auth()); Register(new Flags());
Loader::Register(new Bans()); Register(new Network());
Loader::Register(new Dvar()); Register(new Logger());
Loader::Register(new Bots()); Register(new Singleton());
Loader::Register(new Lean()); Register(new UIScript());
Loader::Register(new Maps()); Register(new ZoneBuilder());
Loader::Register(new News());
Loader::Register(new Node());
Loader::Register(new RCon());
Loader::Register(new Stats());
Loader::Register(new Menus());
Loader::Register(new Toast());
Loader::Register(new Party());
Loader::Register(new Zones());
Loader::Register(new D3D9Ex());
Loader::Register(new Logger());
Loader::Register(new Weapon());
Loader::Register(new Window());
Loader::Register(new Command());
Loader::Register(new Console());
Loader::Register(new Friends());
Loader::Register(new IPCPipe());
Loader::Register(new MapDump());
Loader::Register(new ModList());
Loader::Register(new Network());
Loader::Register(new NetworkDebug());
Loader::Register(new Session());
Loader::Register(new Theatre());
Loader::Register(new ClanTags());
Loader::Register(new Download());
Loader::Register(new Playlist());
Loader::Register(new RawFiles());
Loader::Register(new Renderer());
Loader::Register(new UIFeeder());
Loader::Register(new UIScript());
Loader::Register(new Changelog());
Loader::Register(new Dedicated());
Loader::Register(new Discovery());
Loader::Register(new FastFiles());
Loader::Register(new Gametypes());
Loader::Register(new Materials());
Loader::Register(new Scheduler());
Loader::Register(new Threading());
Loader::Register(new CardTitles());
Loader::Register(new FileSystem());
Loader::Register(new ModelSurfs());
Loader::Register(new PlayerName());
Loader::Register(new QuickPatch());
Loader::Register(new Security());
Loader::Register(new ServerInfo());
Loader::Register(new ServerList());
Loader::Register(new SlowMotion());
Loader::Register(new ArenaLength());
Loader::Register(new StringTable());
Loader::Register(new ZoneBuilder());
Loader::Register(new AssetHandler());
Loader::Register(new Localization());
Loader::Register(new ServerCommands());
Loader::Register(new StructuredData());
Loader::Register(new ConnectProtocol());
Loader::Register(new StartupMessages());
Loader::Register(new SoundMutexFix());
Loader::Register(new Gamepad());
Loader::Register(new Chat());
Loader::Register(new TextRenderer());
Loader::Register(new PlayerMovement());
Loader::Register(new Elevators());
Loader::Register(new ClientCommand());
Loader::Register(new VisionFile());
Loader::Register(new Branding());
Loader::Register(new Debug());
Loader::Register(new RawMouse());
Loader::Register(new Bullet());
Loader::Register(new MapRotation());
Loader::Register(new Ceg());
Loader::Register(new UserInfo());
Loader::Register(new Events());
Loader::Register(new Voice());
Loader::Register(new Vote());
Loader::Register(new GSC()); Register(new ArenaLength());
Register(new AssetHandler());
Register(new Bans());
Register(new Bots());
Register(new Branding());
Register(new Bullet());
Register(new CardTitles());
Register(new Ceg());
Register(new Changelog());
Register(new Chat());
Register(new ClanTags());
Register(new ClientCommand());
Register(new ConnectProtocol());
Register(new Console());
Register(new D3D9Ex());
Register(new Debug());
Register(new Dedicated());
Register(new Discovery());
Register(new Download());
Register(new Elevators());
Register(new Events());
Register(new FastFiles());
Register(new FileSystem());
Register(new Friends());
Register(new Gamepad());
Register(new Gametypes());
Register(new IPCPipe());
Register(new Lean());
Register(new Localization());
Register(new MapDump());
Register(new MapRotation());
Register(new Maps());
Register(new Materials());
Register(new Menus());
Register(new ModList());
Register(new ModelSurfs());
Register(new NetworkDebug());
Register(new News());
Register(new Node());
Register(new Party());
Register(new PlayerMovement());
Register(new PlayerName());
Register(new Playlist());
Register(new QuickPatch());
Register(new RCon());
Register(new RawFiles());
Register(new RawMouse());
Register(new Renderer());
Register(new Scheduler());
Register(new Security());
Register(new ServerCommands());
Register(new ServerInfo());
Register(new ServerList());
Register(new Session());
Register(new SlowMotion());
Register(new SoundMutexFix());
Register(new StartupMessages());
Register(new Stats());
Register(new StringTable());
Register(new StructuredData());
Register(new TextRenderer());
Register(new Theatre());
Register(new Threading());
Register(new Toast());
Register(new UIFeeder());
Register(new UserInfo());
Register(new VisionFile());
Register(new Voice());
Register(new Vote());
Register(new Weapon());
Register(new Window());
Register(new Zones());
Loader::Pregame = false; Register(new GSC());
Pregame = false;
// Make sure preDestroy is called when the game shuts down // Make sure preDestroy is called when the game shuts down
Scheduler::OnGameShutdown(Loader::PreDestroy); Scheduler::OnGameShutdown(PreDestroy);
} }
void Loader::Uninitialize() void Loader::Uninitialize()
{ {
Loader::Uninitializing = true; Uninitializing = true;
Loader::PreDestroyNoPostGame(); PreDestroyNoPostGame();
std::reverse(Loader::Components.begin(), Loader::Components.end()); std::reverse(Components.begin(), Components.end());
for (auto component : Loader::Components) for (auto& component : Components)
{ {
#ifdef DEBUG #ifdef DEBUG
if (!Loader::IsPerformingUnitTests()) if (!IsPerformingUnitTests())
{ {
Logger::Print("Unregister component: {}\n", component->getName()); Logger::Print("Unregister component: {}\n", component->getName());
} }
@ -138,21 +138,21 @@ namespace Components
delete component; delete component;
} }
Loader::Components.clear(); Components.clear();
Utils::Memory::GetAllocator()->clear(); Utils::Memory::GetAllocator()->clear();
Loader::Uninitializing = false; Uninitializing = false;
} }
void Loader::PreDestroy() void Loader::PreDestroy()
{ {
if (!Loader::Postgame) if (!Postgame)
{ {
Loader::Postgame = true; Postgame = true;
auto components = Loader::Components; auto components = Components;
std::reverse(components.begin(), components.end()); std::reverse(components.begin(), components.end());
for (auto component : components) for (auto& component : components)
{ {
component->preDestroy(); component->preDestroy();
} }
@ -161,17 +161,17 @@ namespace Components
void Loader::PreDestroyNoPostGame() void Loader::PreDestroyNoPostGame()
{ {
if (!Loader::Postgame) if (!Postgame)
{ {
auto components = Loader::Components; auto components = Components;
std::reverse(components.begin(), components.end()); std::reverse(components.begin(), components.end());
for (auto component : components) for (auto& component : components)
{ {
component->preDestroy(); component->preDestroy();
} }
Loader::Postgame = true; Postgame = true;
} }
} }
@ -181,7 +181,7 @@ namespace Components
Logger::Print("Performing unit tests for components:\n"); Logger::Print("Performing unit tests for components:\n");
for (const auto component : Loader::Components) for (const auto& component : Components)
{ {
#if defined(FORCE_UNIT_TESTS) #if defined(FORCE_UNIT_TESTS)
Logger::Debug("Testing '{}'...\n", component->getName()); Logger::Debug("Testing '{}'...\n", component->getName());
@ -210,12 +210,12 @@ namespace Components
if (component) if (component)
{ {
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS) #if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
if (!Loader::IsPerformingUnitTests()) if (!IsPerformingUnitTests())
{ {
Logger::Print("Component registered: {}\n", component->getName()); Logger::Print("Component registered: {}\n", component->getName());
} }
#endif #endif
Loader::Components.push_back(component); Components.push_back(component);
} }
} }
} }

View File

@ -42,7 +42,7 @@ namespace Components
template <typename T> template <typename T>
static T* GetInstance() static T* GetInstance()
{ {
for (auto& component : Loader::Components) for (auto& component : Components)
{ {
if (typeid(*component) == typeid(T)) if (typeid(*component) == typeid(T))
{ {
@ -61,87 +61,89 @@ namespace Components
}; };
} }
#include "Modules/Scheduler.hpp" // Priority
#include "Modules/Auth.hpp" #include "Modules/Auth.hpp"
#include "Modules/Bans.hpp"
#include "Modules/Dvar.hpp"
#include "Modules/Bots.hpp"
#include "Modules/Lean.hpp"
#include "Modules/Maps.hpp"
#include "Modules/News.hpp"
#include "Modules/Flags.hpp"
#include "Modules/Menus.hpp"
#include "Modules/Toast.hpp"
#include "Modules/Zones.hpp"
#include "Modules/D3D9Ex.hpp"
#include "Modules/Weapon.hpp"
#include "Modules/Window.hpp"
#include "Modules/Command.hpp" #include "Modules/Command.hpp"
#include "Modules/Console.hpp" #include "Modules/Dvar.hpp"
#include "Modules/UIScript.hpp" #include "Modules/Exception.hpp"
#include "Modules/ModList.hpp" #include "Modules/Flags.hpp"
#include "Modules/Network.hpp" #include "Modules/Network.hpp"
#include "Modules/NetworkDebug.hpp"
#include "Modules/Theatre.hpp"
#include "Modules/QuickPatch.hpp"
#include "Modules/Security.hpp"
#include "Modules/Node.hpp"
#include "Modules/RCon.hpp"
#include "Modules/Party.hpp" // Destroys the order, but requires network classes :D
#include "Modules/Logger.hpp" #include "Modules/Logger.hpp"
#include "Modules/Friends.hpp" #include "Modules/Singleton.hpp"
#include "Modules/IPCPipe.hpp" #include "Modules/UIScript.hpp"
#include "Modules/MapDump.hpp" #include "Modules/ZoneBuilder.hpp"
#include "Modules/Session.hpp"
#include "Modules/ClanTags.hpp" #include "Modules/ArenaLength.hpp"
#include "Modules/Download.hpp" #include "Modules/AssetHandler.hpp"
#include "Modules/Playlist.hpp" #include "Modules/Bans.hpp"
#include "Modules/RawFiles.hpp" #include "Modules/Bots.hpp"
#include "Modules/Renderer.hpp" #include "Modules/Branding.hpp"
#include "Modules/UIFeeder.hpp" #include "Modules/Bullet.hpp"
#include "Modules/CardTitles.hpp"
#include "Modules/Ceg.hpp"
#include "Modules/Changelog.hpp" #include "Modules/Changelog.hpp"
#include "Modules/Chat.hpp"
#include "Modules/ClanTags.hpp"
#include "Modules/ClientCommand.hpp"
#include "Modules/ConnectProtocol.hpp"
#include "Modules/Console.hpp"
#include "Modules/D3D9Ex.hpp"
#include "Modules/Debug.hpp"
#include "Modules/Dedicated.hpp" #include "Modules/Dedicated.hpp"
#include "Modules/Discovery.hpp" #include "Modules/Discovery.hpp"
#include "Modules/Exception.hpp" #include "Modules/Download.hpp"
#include "Modules/Elevators.hpp"
#include "Modules/Events.hpp"
#include "Modules/FastFiles.hpp" #include "Modules/FastFiles.hpp"
#include "Modules/Gametypes.hpp"
#include "Modules/Materials.hpp"
#include "Modules/Singleton.hpp"
#include "Modules/Threading.hpp"
#include "Modules/CardTitles.hpp"
#include "Modules/FileSystem.hpp" #include "Modules/FileSystem.hpp"
#include "Modules/Friends.hpp"
#include "Modules/Gamepad.hpp"
#include "Modules/Gametypes.hpp"
#include "Modules/IPCPipe.hpp"
#include "Modules/Lean.hpp"
#include "Modules/Localization.hpp"
#include "Modules/MapDump.hpp"
#include "Modules/MapRotation.hpp"
#include "Modules/Maps.hpp"
#include "Modules/Materials.hpp"
#include "Modules/Menus.hpp"
#include "Modules/ModList.hpp"
#include "Modules/ModelSurfs.hpp" #include "Modules/ModelSurfs.hpp"
#include "Modules/NetworkDebug.hpp"
#include "Modules/News.hpp"
#include "Modules/Node.hpp"
#include "Modules/Party.hpp"
#include "Modules/PlayerMovement.hpp"
#include "Modules/PlayerName.hpp" #include "Modules/PlayerName.hpp"
#include "Modules/Playlist.hpp"
#include "Modules/QuickPatch.hpp"
#include "Modules/RCon.hpp"
#include "Modules/RawFiles.hpp"
#include "Modules/RawMouse.hpp"
#include "Modules/Renderer.hpp"
#include "Modules/Scheduler.hpp"
#include "Modules/Security.hpp"
#include "Modules/ServerCommands.hpp"
#include "Modules/ServerInfo.hpp" #include "Modules/ServerInfo.hpp"
#include "Modules/ServerList.hpp" #include "Modules/ServerList.hpp"
#include "Modules/Session.hpp"
#include "Modules/SlowMotion.hpp" #include "Modules/SlowMotion.hpp"
#include "Modules/ArenaLength.hpp" #include "Modules/SoundMutexFix.hpp"
#include "Modules/StringTable.hpp"
#include "Modules/ZoneBuilder.hpp"
#include "Modules/AssetHandler.hpp"
#include "Modules/Localization.hpp"
#include "Modules/ServerCommands.hpp"
#include "Modules/StructuredData.hpp"
#include "Modules/ConnectProtocol.hpp"
#include "Modules/StartupMessages.hpp" #include "Modules/StartupMessages.hpp"
#include "Modules/Stats.hpp" #include "Modules/Stats.hpp"
#include "Modules/SoundMutexFix.hpp" #include "Modules/StringTable.hpp"
#include "Modules/Chat.hpp" #include "Modules/StructuredData.hpp"
#include "Modules/TextRenderer.hpp" #include "Modules/TextRenderer.hpp"
#include "Modules/PlayerMovement.hpp" #include "Modules/Theatre.hpp"
#include "Modules/Elevators.hpp" #include "Modules/Threading.hpp"
#include "Modules/ClientCommand.hpp" #include "Modules/Toast.hpp"
#include "Modules/VisionFile.hpp" #include "Modules/UIFeeder.hpp"
#include "Modules/Gamepad.hpp"
#include "Modules/Branding.hpp"
#include "Modules/Debug.hpp"
#include "Modules/RawMouse.hpp"
#include "Modules/Bullet.hpp"
#include "Modules/MapRotation.hpp"
#include "Modules/Ceg.hpp"
#include "Modules/UserInfo.hpp" #include "Modules/UserInfo.hpp"
#include "Modules/Events.hpp" #include "Modules/VisionFile.hpp"
#include "Modules/Voice.hpp" #include "Modules/Voice.hpp"
#include "Modules/Vote.hpp" #include "Modules/Vote.hpp"
#include "Modules/Weapon.hpp"
#include "Modules/Window.hpp"
#include "Modules/Zones.hpp"
#include "Modules/GSC/GSC.hpp" #include "Modules/GSC/GSC.hpp"

View File

@ -2,7 +2,7 @@
namespace Components namespace Components
{ {
std::string CardTitles::CustomTitles[18]; char CardTitles::CustomTitles[Game::MAX_CLIENTS][18];
Dvar::Var CardTitles::CustomTitle; Dvar::Var CardTitles::CustomTitle;
CClient* CardTitles::GetClientByIndex(std::uint32_t index) CClient* CardTitles::GetClientByIndex(std::uint32_t index)
@ -10,35 +10,34 @@ namespace Components
return &reinterpret_cast<CClient*>(0x8E77B0)[index]; return &reinterpret_cast<CClient*>(0x8E77B0)[index];
} }
std::int32_t CardTitles::GetPlayerCardClientInfo(std::int32_t lookupResult, Game::PlayerCardData* data) int CardTitles::GetPlayerCardClientInfo(int lookupResult, Game::PlayerCardData* data)
{ {
std::int32_t returnResult = lookupResult; auto result = lookupResult;
std::string username = Dvar::Var("name").get<std::string>(); const auto* username = Dvar::Var("name").get<const char*>();
if (std::strcmp(data->name, username) == 0)
if (data->name == username)
{ {
returnResult += 0xFE000000; result += 0xFE000000;
} }
else else
{ {
for (std::size_t clientNum = 0; clientNum < Game::MAX_CLIENTS; ++clientNum) for (std::size_t i = 0; i < Game::MAX_CLIENTS; ++i)
{ {
CClient* c = GetClientByIndex(clientNum); CClient* c = GetClientByIndex(i);
if (c != nullptr) if (c != nullptr)
{ {
if (!std::strcmp(data->name, c->Name)) if (!std::strcmp(data->name, c->Name))
{ {
// Since a 4 byte integer is overkill for a row num: We can use it to store the customprefix + clientNum and use a 2 byte integer for the row number // Since a 4 byte integer is overkill for a row num: We can use it to store the customprefix + clientNum and use a 2 byte integer for the row number
returnResult += 0xFF000000; result += 0xFF000000;
returnResult += clientNum * 0x10000; result += i * 0x10000;
break; break;
} }
} }
} }
} }
return returnResult; return result;
} }
void __declspec(naked) CardTitles::GetPlayerCardClientInfoStub() void __declspec(naked) CardTitles::GetPlayerCardClientInfoStub()
@ -71,7 +70,7 @@ namespace Components
std::uint8_t prefix = (request->tableRow >> (8 * 3)) & 0xFF; std::uint8_t prefix = (request->tableRow >> (8 * 3)) & 0xFF;
std::uint8_t data = (request->tableRow >> (8 * 2)) & 0xFF; std::uint8_t data = (request->tableRow >> (8 * 2)) & 0xFF;
if (data >= ARRAYSIZE(CardTitles::CustomTitles)) return nullptr; if (data >= Game::MAX_CLIENTS) return nullptr;
if (request->tablename == "mp/cardTitleTable.csv"s) if (request->tablename == "mp/cardTitleTable.csv"s)
{ {
@ -82,10 +81,10 @@ namespace Components
{ {
if (prefix == 0xFE) if (prefix == 0xFE)
{ {
if (!CardTitles::CustomTitle.get<std::string>().empty()) if (!CustomTitle.get<std::string>().empty())
{ {
// 0xFF in front of the title to skip localization. Or else it will wait for a couple of seconds for the asset of type localize // 0xFF in front of the title to skip localization. Or else it will wait for a couple of seconds for the asset of type localize
const char* title = Utils::String::VA("\x15%s", CardTitles::CustomTitle.get<const char*>()); const auto* title = Utils::String::VA("\x15%s", CustomTitle.get<const char*>());
// prepare return value // prepare return value
operand->internals.stringVal.string = title; operand->internals.stringVal.string = title;
@ -96,9 +95,9 @@ namespace Components
} }
else if (prefix == 0xFF) else if (prefix == 0xFF)
{ {
if (!CardTitles::CustomTitles[data].empty()) if (CustomTitles[data][0] != '\0')
{ {
const char* title = Utils::String::VA("\x15%s", CardTitles::CustomTitles[data].data()); const auto* title = Utils::String::VA("\x15%s", CustomTitles[data]);
// prepare return value // prepare return value
operand->internals.stringVal.string = title; operand->internals.stringVal.string = title;
@ -156,11 +155,11 @@ namespace Components
{ {
std::string list; std::string list;
for (std::size_t i = 0; i < Game::MAX_CLIENTS; i++) for (std::size_t i = 0; i < Game::MAX_CLIENTS; ++i)
{ {
char playerTitle[18]; char playerTitle[18]{};
if (Game::svs_clients[i].header.state >= Game::CS_CONNECTED) if (Game::svs_clients[i].userinfo[0] != '\0')
{ {
strncpy_s(playerTitle, Game::Info_ValueForKey(Game::svs_clients[i].userinfo, "customTitle"), _TRUNCATE); strncpy_s(playerTitle, Game::Info_ValueForKey(Game::svs_clients[i].userinfo, "customTitle"), _TRUNCATE);
} }
@ -180,10 +179,17 @@ namespace Components
{ {
for (std::size_t i = 0; i < Game::MAX_CLIENTS; ++i) for (std::size_t i = 0; i < Game::MAX_CLIENTS; ++i)
{ {
const char* playerTitle = Game::Info_ValueForKey(msg, std::to_string(i).c_str()); const auto index = std::to_string(i);
const auto* playerTitle = Game::Info_ValueForKey(msg, index.data());
if (playerTitle) CardTitles::CustomTitles[i] = playerTitle; if (playerTitle[0] == '\0')
else CardTitles::CustomTitles[i].clear(); {
CustomTitles[i][0] = '\0';
}
else
{
Game::I_strncpyz(CustomTitles[i], playerTitle, sizeof(CustomTitles[0]) / sizeof(char));
}
} }
} }
@ -191,16 +197,18 @@ namespace Components
{ {
Scheduler::Once([] Scheduler::Once([]
{ {
CardTitles::CustomTitle = Dvar::Register<const char*>("customTitle", "", Game::DVAR_USERINFO | Game::DVAR_ARCHIVE, "Custom card title"); CustomTitle = Dvar::Register<const char*>("customTitle", "", Game::DVAR_USERINFO | Game::DVAR_ARCHIVE, "Custom card title");
}, Scheduler::Pipeline::MAIN); }, Scheduler::Pipeline::MAIN);
std::memset(&CustomTitles, 0, sizeof(char[Game::MAX_CLIENTS][18]));
ServerCommands::OnCommand(21, [](Command::Params* params) ServerCommands::OnCommand(21, [](Command::Params* params)
{ {
if (params->get(1) == "customTitles"s && !Dedicated::IsEnabled()) if (std::strcmp(params->get(1), "customTitles") == 0)
{ {
if (params->size() == 3) if (params->size() == 3)
{ {
CardTitles::ParseCustomTitles(params->get(2)); ParseCustomTitles(params->get(2));
return true; return true;
} }
} }
@ -209,10 +217,10 @@ namespace Components
}); });
Utils::Hook(0x62EB26, CardTitles::GetPlayerCardClientInfoStub).install()->quick(); Utils::Hook(0x62EB26, GetPlayerCardClientInfoStub).install()->quick();
// Table lookup stuff // Table lookup stuff
Utils::Hook(0x62DCC1, CardTitles::TableLookupByRowHookStub).install()->quick(); Utils::Hook(0x62DCC1, TableLookupByRowHookStub).install()->quick();
Utils::Hook::Nop(0x62DCC6, 1); Utils::Hook::Nop(0x62DCC6, 1);
} }
} }

View File

@ -44,19 +44,20 @@ namespace Components
public: public:
AssertOffset(Game::PlayerCardData, Game::PlayerCardData::name, 0x1C); AssertOffset(Game::PlayerCardData, Game::PlayerCardData::name, 0x1C);
static Dvar::Var CustomTitle;
static std::string CustomTitles[18];
static void SendCustomTitlesToClients(); static void SendCustomTitlesToClients();
static void ParseCustomTitles(const char* msg);
CardTitles(); CardTitles();
private: private:
static Dvar::Var CustomTitle;
static char CustomTitles[Game::MAX_CLIENTS][18];
static CClient* GetClientByIndex(std::uint32_t index); static CClient* GetClientByIndex(std::uint32_t index);
static std::int32_t GetPlayerCardClientInfo(std::int32_t lookupResult, Game::PlayerCardData* data); static int GetPlayerCardClientInfo(int lookupResult, Game::PlayerCardData* data);
static void GetPlayerCardClientInfoStub(); static void GetPlayerCardClientInfoStub();
static const char* TableLookupByRowHook(Game::Operand* operand, tablelookuprequest_s* request); static const char* TableLookupByRowHook(Game::Operand* operand, tablelookuprequest_s* request);
static void TableLookupByRowHookStub(); static void TableLookupByRowHookStub();
static void ParseCustomTitles(const char* msg);
}; };
} }

View File

@ -186,24 +186,24 @@ namespace Components
} }
} }
template<> Dvar::Var Dvar::Register(const char* dvarName, bool value, Flag flag, const char* description) template<> Dvar::Var Dvar::Register(const char* dvarName, bool value, std::uint16_t flag, const char* description)
{ {
return Game::Dvar_RegisterBool(dvarName, value, flag.val, description); return Game::Dvar_RegisterBool(dvarName, value, flag, description);
} }
template<> Dvar::Var Dvar::Register(const char* dvarName, const char* value, Flag flag, const char* description) template<> Dvar::Var Dvar::Register(const char* dvarName, const char* value, std::uint16_t flag, const char* description)
{ {
return Game::Dvar_RegisterString(dvarName, value, flag.val, description); return Game::Dvar_RegisterString(dvarName, value, flag, description);
} }
template<> Dvar::Var Dvar::Register(const char* dvarName, int value, int min, int max, Flag flag, const char* description) template<> Dvar::Var Dvar::Register(const char* dvarName, int value, int min, int max, std::uint16_t flag, const char* description)
{ {
return Game::Dvar_RegisterInt(dvarName, value, min, max, flag.val, description); return Game::Dvar_RegisterInt(dvarName, value, min, max, flag, description);
} }
template<> Dvar::Var Dvar::Register(const char* dvarName, float value, float min, float max, Flag flag, const char* description) template<> Dvar::Var Dvar::Register(const char* dvarName, float value, float min, float max, std::uint16_t flag, const char* description)
{ {
return Game::Dvar_RegisterFloat(dvarName, value, min, max, flag.val, description); return Game::Dvar_RegisterFloat(dvarName, value, min, max, flag, description);
} }
void Dvar::ResetDvarsValue() void Dvar::ResetDvarsValue()

View File

@ -5,15 +5,6 @@ namespace Components
class Dvar : public Component class Dvar : public Component
{ {
public: public:
class Flag
{
public:
Flag(Game::DvarFlags flag) : val(flag) {}
Flag(std::uint16_t flag) : Flag(static_cast<Game::DvarFlags>(flag)) {}
Game::DvarFlags val;
};
class Var class Var
{ {
public: public:
@ -44,8 +35,8 @@ namespace Components
~Dvar(); ~Dvar();
// Only strings and bools use this type of declaration // Only strings and bools use this type of declaration
template<typename T> static Var Register(const char* dvarName, T value, Flag flag, const char* description); template<typename T> static Var Register(const char* dvarName, T value, std::uint16_t flag, const char* description);
template<typename T> static Var Register(const char* dvarName, T value, T min, T max, Flag flag, const char* description); template<typename T> static Var Register(const char* dvarName, T value, T min, T max, std::uint16_t flag, const char* description);
static void ResetDvarsValue(); static void ResetDvarsValue();

View File

@ -7,20 +7,10 @@ namespace Components
Utils::Hook Exception::SetFilterHook; Utils::Hook Exception::SetFilterHook;
int Exception::MiniDumpType; int Exception::MiniDumpType;
__declspec(noreturn) void Exception::ErrorLongJmp(jmp_buf _Buf, int _Value) __declspec(noreturn) void Exception::LongJmp_Internal_Stub(jmp_buf env, int status)
{
if (!*reinterpret_cast<DWORD*>(0x1AD7EB4))
{
TerminateProcess(GetCurrentProcess(), 1337);
}
longjmp(_Buf, _Value);
}
__declspec(noreturn) void Exception::LongJmp(jmp_buf _Buf, int _Value)
{ {
AssetHandler::ResetBypassState(); AssetHandler::ResetBypassState();
longjmp(_Buf, _Value); Game::longjmp_internal(env, status);
} }
void Exception::SuspendProcess() void Exception::SuspendProcess()
@ -76,7 +66,7 @@ namespace Components
return; return;
} }
auto lock = GlobalLock(hMem); auto* lock = GlobalLock(hMem);
if (lock != nullptr) if (lock != nullptr)
{ {
std::memcpy(lock, error.data(), error.size() + 1); std::memcpy(lock, error.data(), error.size() + 1);
@ -107,17 +97,15 @@ namespace Components
errorStr = Utils::String::VA("Fatal error (0x%08X) at 0x%08X.\nCopy exception address to clipboard?", ExceptionInfo->ExceptionRecord->ExceptionCode, ExceptionInfo->ExceptionRecord->ExceptionAddress); errorStr = Utils::String::VA("Fatal error (0x%08X) at 0x%08X.\nCopy exception address to clipboard?", ExceptionInfo->ExceptionRecord->ExceptionCode, ExceptionInfo->ExceptionRecord->ExceptionAddress);
} }
//Exception::SuspendProcess();
// Message should be copied to the keyboard if no button is pressed // Message should be copied to the keyboard if no button is pressed
if (MessageBoxA(nullptr, errorStr.data(), nullptr, MB_YESNO | MB_ICONERROR) == IDYES) if (MessageBoxA(nullptr, errorStr.data(), nullptr, MB_YESNO | MB_ICONERROR) == IDYES)
{ {
Exception::CopyMessageToClipboard(Utils::String::VA("0x%08X", ExceptionInfo->ExceptionRecord->ExceptionAddress)); CopyMessageToClipboard(Utils::String::VA("0x%08X", ExceptionInfo->ExceptionRecord->ExceptionAddress));
} }
if (Flags::HasFlag("bigminidumps")) if (Flags::HasFlag("bigminidumps"))
{ {
Exception::SetMiniDumpType(true, false); SetMiniDumpType(true, false);
} }
// Current executable name // Current executable name
@ -134,23 +122,22 @@ namespace Components
_localtime64_s(&ltime, &time); _localtime64_s(&ltime, &time);
strftime(filenameFriendlyTime, sizeof(filenameFriendlyTime) - 1, "%Y%m%d%H%M%S", &ltime); strftime(filenameFriendlyTime, sizeof(filenameFriendlyTime) - 1, "%Y%m%d%H%M%S", &ltime);
// Combine with queuedMinidumpsFolder // Combine with queued MinidumpsFolder
char filename[MAX_PATH] = { 0 }; char filename[MAX_PATH]{};
Utils::IO::CreateDir("minidumps"); CreateDirectoryA("minidumps", nullptr);
PathCombineA(filename, "minidumps\\", Utils::String::VA("%s-" VERSION "-%s.dmp", exeFileName, filenameFriendlyTime)); PathCombineA(filename, "minidumps\\", Utils::String::VA("%s-" VERSION "-%s.dmp", exeFileName, filenameFriendlyTime));
DWORD fileShare = FILE_SHARE_READ | FILE_SHARE_WRITE; constexpr auto fileShare = FILE_SHARE_READ | FILE_SHARE_WRITE;
HANDLE hFile = CreateFileA(filename, GENERIC_WRITE | GENERIC_READ, fileShare, nullptr, (fileShare & FILE_SHARE_WRITE) > 0 ? OPEN_ALWAYS : OPEN_EXISTING, NULL, nullptr); HANDLE hFile = CreateFileA(filename, GENERIC_WRITE | GENERIC_READ, fileShare, nullptr, (fileShare & FILE_SHARE_WRITE) > 0 ? OPEN_ALWAYS : OPEN_EXISTING, NULL, nullptr);
MINIDUMP_EXCEPTION_INFORMATION ex = { GetCurrentThreadId(), ExceptionInfo, FALSE }; MINIDUMP_EXCEPTION_INFORMATION ex = { GetCurrentThreadId(), ExceptionInfo, FALSE };
if (!MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, static_cast<MINIDUMP_TYPE>(Exception::MiniDumpType), &ex, nullptr, nullptr)) if (!MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, static_cast<MINIDUMP_TYPE>(MiniDumpType), &ex, nullptr, nullptr))
{ {
MessageBoxA(nullptr, Utils::String::VA("There was an error creating the minidump (%s)! Hit OK to close the program.", Utils::GetLastWindowsError().data()), "Minidump Error", MB_OK | MB_ICONERROR); MessageBoxA(nullptr, Utils::String::Format("There was an error creating the minidump ({})! Hit OK to close the program.", Utils::GetLastWindowsError()), "ERROR", MB_OK | MB_ICONERROR);
OutputDebugStringA("Failed to create new minidump!"); OutputDebugStringA("Failed to create new minidump!");
Utils::OutputDebugLastError(); Utils::OutputDebugLastError();
TerminateProcess(GetCurrentProcess(), ExceptionInfo->ExceptionRecord->ExceptionCode); TerminateProcess(GetCurrentProcess(), ExceptionInfo->ExceptionRecord->ExceptionCode);
} }
//if (ExceptionInfo->ExceptionRecord->ExceptionFlags == EXCEPTION_NONCONTINUABLE)
{ {
TerminateProcess(GetCurrentProcess(), ExceptionInfo->ExceptionRecord->ExceptionCode); TerminateProcess(GetCurrentProcess(), ExceptionInfo->ExceptionRecord->ExceptionCode);
} }
@ -158,54 +145,39 @@ namespace Components
return EXCEPTION_CONTINUE_SEARCH; return EXCEPTION_CONTINUE_SEARCH;
} }
LPTOP_LEVEL_EXCEPTION_FILTER WINAPI Exception::SetUnhandledExceptionFilterStub(LPTOP_LEVEL_EXCEPTION_FILTER)
{
Exception::SetFilterHook.uninstall();
LPTOP_LEVEL_EXCEPTION_FILTER retval = SetUnhandledExceptionFilter(&Exception::ExceptionFilter);
Exception::SetFilterHook.install();
return retval;
}
LPTOP_LEVEL_EXCEPTION_FILTER Exception::Hook()
{
return SetUnhandledExceptionFilter(&Exception::ExceptionFilter);
}
void Exception::SetMiniDumpType(bool codeseg, bool dataseg) void Exception::SetMiniDumpType(bool codeseg, bool dataseg)
{ {
Exception::MiniDumpType = MiniDumpIgnoreInaccessibleMemory; MiniDumpType = MiniDumpIgnoreInaccessibleMemory;
Exception::MiniDumpType |= MiniDumpWithHandleData; MiniDumpType |= MiniDumpWithHandleData;
Exception::MiniDumpType |= MiniDumpScanMemory; MiniDumpType |= MiniDumpScanMemory;
Exception::MiniDumpType |= MiniDumpWithProcessThreadData; MiniDumpType |= MiniDumpWithProcessThreadData;
Exception::MiniDumpType |= MiniDumpWithFullMemoryInfo; MiniDumpType |= MiniDumpWithFullMemoryInfo;
Exception::MiniDumpType |= MiniDumpWithThreadInfo; MiniDumpType |= MiniDumpWithThreadInfo;
//Exception::MiniDumpType |= MiniDumpWithModuleHeaders;
if (codeseg) if (codeseg)
{ {
Exception::MiniDumpType |= MiniDumpWithCodeSegs; MiniDumpType |= MiniDumpWithCodeSegs;
} }
if (dataseg) if (dataseg)
{ {
Exception::MiniDumpType |= MiniDumpWithDataSegs; MiniDumpType |= MiniDumpWithDataSegs;
} }
} }
Exception::Exception() Exception::Exception()
{ {
Exception::SetMiniDumpType(Flags::HasFlag("bigminidumps"), Flags::HasFlag("reallybigminidumps")); SetMiniDumpType(Flags::HasFlag("bigminidumps"), Flags::HasFlag("reallybigminidumps"));
#if !defined(DEBUG) || defined(FORCE_EXCEPTION_HANDLER)
Exception::SetFilterHook.initialize(SetUnhandledExceptionFilter, Exception::SetUnhandledExceptionFilterStub, HOOK_JUMP);
Exception::SetFilterHook.install();
SetUnhandledExceptionFilter(&Exception::ExceptionFilter); SetUnhandledExceptionFilter(&Exception::ExceptionFilter);
#endif
//Utils::Hook(0x4B241F, Exception::ErrorLongJmp, HOOK_CALL).install()->quick(); Utils::Hook(0x4B241F, LongJmp_Internal_Stub, HOOK_CALL).install()->quick();
Utils::Hook(0x6B8898, Exception::LongJmp, HOOK_JUMP).install()->quick(); Utils::Hook(0x61DB44, LongJmp_Internal_Stub, HOOK_CALL).install()->quick();
Utils::Hook(0x61F17D, LongJmp_Internal_Stub, HOOK_CALL).install()->quick();
Utils::Hook(0x61F248, LongJmp_Internal_Stub, HOOK_CALL).install()->quick();
Utils::Hook(0x61F5E7, LongJmp_Internal_Stub, HOOK_CALL).install()->quick();
#ifdef _DEBUG #ifdef MAP_TEST
Command::Add("mapTest", [](Command::Params* params) Command::Add("mapTest", [](Command::Params* params)
{ {
Game::UI_UpdateArenas(); Game::UI_UpdateArenas();
@ -227,6 +199,6 @@ namespace Components
Exception::~Exception() Exception::~Exception()
{ {
Exception::SetFilterHook.uninstall(); SetFilterHook.uninstall();
} }
} }

View File

@ -15,9 +15,7 @@ namespace Components
private: private:
static void SuspendProcess(); static void SuspendProcess();
static LONG WINAPI ExceptionFilter(LPEXCEPTION_POINTERS ExceptionInfo); static LONG WINAPI ExceptionFilter(LPEXCEPTION_POINTERS ExceptionInfo);
static LPTOP_LEVEL_EXCEPTION_FILTER WINAPI SetUnhandledExceptionFilterStub(LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter); static __declspec(noreturn) void LongJmp_Internal_Stub(jmp_buf env, int status);
static __declspec(noreturn) void ErrorLongJmp(jmp_buf _Buf, int _Value);
static __declspec(noreturn) void LongJmp(jmp_buf _Buf, int _Value);
static void CopyMessageToClipboard(const std::string& error); static void CopyMessageToClipboard(const std::string& error);

View File

@ -319,7 +319,7 @@ namespace Components
auto clientCount = 0; auto clientCount = 0;
auto maxClientCount = *Game::svs_clientCount; auto maxClientCount = *Game::svs_clientCount;
const auto securityLevel = Dvar::Var("sv_securityLevel").get<int>(); const auto securityLevel = Dvar::Var("sv_securityLevel").get<int>();
const auto password = Dvar::Var("g_password").get<std::string>(); const auto* password = (*Game::g_password)->current.string;
if (maxClientCount) if (maxClientCount)
{ {
@ -352,7 +352,7 @@ namespace Components
info.set("shortversion", SHORTVERSION); info.set("shortversion", SHORTVERSION);
info.set("checksum", std::to_string(Game::Sys_Milliseconds())); info.set("checksum", std::to_string(Game::Sys_Milliseconds()));
info.set("mapname", Dvar::Var("mapname").get<std::string>()); info.set("mapname", Dvar::Var("mapname").get<std::string>());
info.set("isPrivate", password.empty() ? "0" : "1"); info.set("isPrivate", *password ? "1" : "0");
info.set("hc", (Dvar::Var("g_hardcore").get<bool>() ? "1" : "0")); info.set("hc", (Dvar::Var("g_hardcore").get<bool>() ? "1" : "0"));
info.set("securityLevel", std::to_string(securityLevel)); info.set("securityLevel", std::to_string(securityLevel));
info.set("sv_running", (Dedicated::IsRunning() ? "1" : "0")); info.set("sv_running", (Dedicated::IsRunning() ? "1" : "0"));

View File

@ -9,26 +9,26 @@ namespace Components
void Playlist::LoadPlaylist() void Playlist::LoadPlaylist()
{ {
// Check if playlist already loaded // Check if playlist already loaded
if (Utils::Hook::Get<bool>(0x1AD3680)) return; if (*Game::s_havePlaylists) return;
// Don't load playlists when dedi and no party // Don't load playlists when dedi and no party
if (Dedicated::IsEnabled() && !Dvar::Var("party_enable").get<bool>()) if (Dedicated::IsEnabled() && !Dvar::Var("party_enable").get<bool>())
{ {
Utils::Hook::Set<bool>(0x1AD3680, true); // Set received to true *Game::s_havePlaylists = true;
Dvar::Var("xblive_privateserver").set(true); Dvar::Var("xblive_privateserver").set(true);
return; return;
} }
Dvar::Var("xblive_privateserver").set(false); Dvar::Var("xblive_privateserver").set(false);
auto playlistFilename = Dvar::Var("playlistFilename").get<std::string>(); const auto playlistFilename = Dvar::Var("playlistFilename").get<std::string>();
FileSystem::File playlist(playlistFilename); FileSystem::File playlist(playlistFilename);
if (playlist.exists()) if (playlist.exists())
{ {
Logger::Print("Parsing playlist '{}'...\n", playlist.getName()); Logger::Print("Parsing playlist '{}'...\n", playlist.getName());
Game::Playlist_ParsePlaylists(playlist.getBuffer().data()); Game::Playlist_ParsePlaylists(playlist.getBuffer().data());
Utils::Hook::Set<bool>(0x1AD3680, true); // Playlist loaded *Game::s_havePlaylists = true;
} }
else else
{ {
@ -36,18 +36,18 @@ namespace Components
} }
} }
DWORD Playlist::StorePlaylistStub(const char** buffer) char* Playlist::Com_ParseOnLine_Hk(const char** data_p)
{ {
Playlist::MapRelocation.clear(); MapRelocation.clear();
Playlist::CurrentPlaylistBuffer = Utils::Compression::ZLib::Compress(*buffer); CurrentPlaylistBuffer = Utils::Compression::ZLib::Compress(*data_p);
return Utils::Hook::Call<DWORD(const char**)>(0x4C0350)(buffer); return Game::Com_ParseOnLine(data_p);
} }
void Playlist::PlaylistRequest(const Network::Address& address, [[maybe_unused]] const std::string& data) void Playlist::PlaylistRequest(const Network::Address& address, [[maybe_unused]] const std::string& data)
{ {
const auto password = Dvar::Var("g_password").get<std::string>(); const auto* password = (*Game::g_password)->current.string;
if (password.length()) if (*password)
{ {
if (password != data) if (password != data)
{ {
@ -58,7 +58,7 @@ namespace Components
Logger::Print("Received playlist request, sending currently stored buffer.\n"); Logger::Print("Received playlist request, sending currently stored buffer.\n");
std::string compressedList = Playlist::CurrentPlaylistBuffer; std::string compressedList = CurrentPlaylistBuffer;
Proto::Party::Playlist list; Proto::Party::Playlist list;
list.set_hash(Utils::Cryptography::JenkinsOneAtATime::Compute(compressedList)); list.set_hash(Utils::Cryptography::JenkinsOneAtATime::Compute(compressedList));
@ -67,19 +67,26 @@ namespace Components
Network::SendCommand(address, "playlistResponse", list.SerializeAsString()); Network::SendCommand(address, "playlistResponse", list.SerializeAsString());
} }
void Playlist::PlaylistReponse(const Network::Address& address, [[maybe_unused]] const std::string& data) void Playlist::PlaylistResponse(const Network::Address& address, [[maybe_unused]] const std::string& data)
{ {
if (Party::PlaylistAwaiting()) if (!Party::PlaylistAwaiting())
{ {
if (address == Party::Target()) Logger::Print("Received stray playlist response, ignoring it.\n");
return;
}
if (address != Party::Target())
{ {
Logger::Print("Received playlist from someone else than our target host, ignoring it.\n");
return;
}
Proto::Party::Playlist list; Proto::Party::Playlist list;
if (!list.ParseFromString(data)) if (!list.ParseFromString(data))
{ {
Party::PlaylistError(Utils::String::VA("Received playlist response from %s, but it is invalid.", address.getCString())); Party::PlaylistError(std::format("Received playlist response from {}, but it is invalid.", address.getString()));
Playlist::ReceivedPlaylistBuffer.clear(); ReceivedPlaylistBuffer.clear();
return;
} }
else else
{ {
@ -87,60 +94,50 @@ namespace Components
const auto& compressedData = list.buffer(); const auto& compressedData = list.buffer();
const auto hash = Utils::Cryptography::JenkinsOneAtATime::Compute(compressedData); const auto hash = Utils::Cryptography::JenkinsOneAtATime::Compute(compressedData);
//Validate hashes // Validate hashes
if (hash != list.hash()) if (hash != list.hash())
{ {
Party::PlaylistError(Utils::String::VA("Received playlist response from %s, but the checksum did not match (%X != %X).", address.getCString(), list.hash(), hash)); Party::PlaylistError(std::format("Received playlist response from {}, but the checksum did not match ({} != {}).", address.getString(), list.hash(), hash));
Playlist::ReceivedPlaylistBuffer.clear(); ReceivedPlaylistBuffer.clear();
return; return;
} }
// Decompress buffer // Decompress buffer
Playlist::ReceivedPlaylistBuffer = Utils::Compression::ZLib::Decompress(compressedData); ReceivedPlaylistBuffer = Utils::Compression::ZLib::Decompress(compressedData);
// Load and continue connection // Load and continue connection
Logger::Print("Received playlist, loading and continuing connection...\n"); Logger::Print("Received playlist, loading and continuing connection...\n");
Game::Playlist_ParsePlaylists(Playlist::ReceivedPlaylistBuffer.data()); Game::Playlist_ParsePlaylists(ReceivedPlaylistBuffer.data());
Party::PlaylistContinue(); Party::PlaylistContinue();
} }
} }
else
{
Logger::Print("Received playlist from someone else than our target host, ignoring it.\n");
}
}
else
{
Logger::Print("Received stray playlist response, ignoring it.\n");
}
}
void Playlist::PlaylistInvalidPassword([[maybe_unused]] const Network::Address& address, [[maybe_unused]] const std::string& data) void Playlist::PlaylistInvalidPassword([[maybe_unused]] const Network::Address& address, [[maybe_unused]] const std::string& data)
{ {
Party::PlaylistError("Error: Invalid Password for Party."); Party::PlaylistError("Error: Invalid Password for Party.");
} }
void Playlist::MapNameCopy(char *dest, const char *src, int destsize) void Playlist::MapNameCopy(char* dest, const char* src, int destsize)
{ {
Utils::Hook::Call<void(char*, const char*, int)>(0x4D6F80)(dest, src, destsize); Utils::Hook::Call<void(char*, const char*, int)>(0x4D6F80)(dest, src, destsize);
Playlist::MapRelocation[dest] = src; MapRelocation[dest] = src;
} }
void Playlist::SetMapName(const char* cvar, const char* value) void Playlist::SetMapName(const char* dvarName, const char* value)
{ {
auto i = Playlist::MapRelocation.find(value); auto i = MapRelocation.find(value);
if (i != Playlist::MapRelocation.end()) if (i != MapRelocation.end())
{ {
value = i->second.data(); value = i->second.data();
} }
Game::Dvar_SetStringByName(cvar, value); Game::Dvar_SetStringByName(dvarName, value);
} }
int Playlist::GetMapIndex(const char* mapname) int Playlist::GetMapIndex(const char* mapname)
{ {
auto i = Playlist::MapRelocation.find(mapname); auto i = MapRelocation.find(mapname);
if (i != Playlist::MapRelocation.end()) if (i != MapRelocation.end())
{ {
mapname = i->second.data(); mapname = i->second.data();
} }
@ -153,7 +150,7 @@ namespace Components
// Default playlists // Default playlists
Utils::Hook::Set<const char*>(0x60B06E, "playlists_default.info"); Utils::Hook::Set<const char*>(0x60B06E, "playlists_default.info");
// disable playlist download function // Disable playlist download function
Utils::Hook::Set<BYTE>(0x4D4790, 0xC3); Utils::Hook::Set<BYTE>(0x4D4790, 0xC3);
// Load playlist, but don't delete it // Load playlist, but don't delete it
@ -161,34 +158,34 @@ namespace Components
Utils::Hook::Nop(0x4D6E67, 5); Utils::Hook::Nop(0x4D6E67, 5);
Utils::Hook::Nop(0x4D6E71, 2); Utils::Hook::Nop(0x4D6E71, 2);
// playlist dvar 'validity check' // Disable Playlist_ValidatePlaylistNum
Utils::Hook::Set<BYTE>(0x4B1170, 0xC3); Utils::Hook::Set<BYTE>(0x4B1170, 0xC3);
// disable playlist checking // Disable playlist checking
Utils::Hook::Set<BYTE>(0x5B69E9, 0xEB); // too new Utils::Hook::Set<BYTE>(0x5B69E9, 0xEB); // Too new
Utils::Hook::Set<BYTE>(0x5B696E, 0xEB); // too old Utils::Hook::Set<BYTE>(0x5B696E, 0xEB); // Too old
//Got playlists is true // Got playlists is true
//Utils::Hook::Set<bool>(0x1AD3680, true); //Utils::Hook::Set<bool>(0x1AD3680, true);
Utils::Hook(0x497DB5, Playlist::GetMapIndex, HOOK_CALL).install()->quick(); Utils::Hook(0x497DB5, GetMapIndex, HOOK_CALL).install()->quick();
Utils::Hook(0x42A19D, Playlist::MapNameCopy, HOOK_CALL).install()->quick(); Utils::Hook(0x42A19D, MapNameCopy, HOOK_CALL).install()->quick();
Utils::Hook(0x4A6FEE, Playlist::SetMapName, HOOK_CALL).install()->quick(); Utils::Hook(0x4A6FEE, SetMapName, HOOK_CALL).install()->quick();
// Store playlist buffer on load // Store playlist buffer on load
Utils::Hook(0x42961C, Playlist::StorePlaylistStub, HOOK_CALL).install()->quick(); Utils::Hook(0x42961C, Com_ParseOnLine_Hk, HOOK_CALL).install()->quick(); // Playlist_ParsePlaylists
//if (Dedicated::IsDedicated()) //if (Dedicated::IsDedicated())
{ {
// Custom playlist loading // Custom playlist loading
Utils::Hook(0x420B5A, Playlist::LoadPlaylist, HOOK_JUMP).install()->quick(); Utils::Hook(0x420B5A, LoadPlaylist, HOOK_JUMP).install()->quick();
// disable playlist.ff loading function // disable playlist.ff loading function (Win_LoadPlaylistFastfile)
Utils::Hook::Set<BYTE>(0x4D6E60, 0xC3); Utils::Hook::Set<std::uint8_t>(0x4D6E60, 0xC3);
} }
Network::OnClientPacket("getPlaylist", PlaylistRequest); Network::OnClientPacket("getPlaylist", PlaylistRequest);
Network::OnClientPacket("playlistResponse", PlaylistReponse); Network::OnClientPacket("playlistResponse", PlaylistResponse);
Network::OnClientPacket("playlistInvalidPassword", PlaylistInvalidPassword); Network::OnClientPacket("playlistInvalidPassword", PlaylistInvalidPassword);
} }
} }

View File

@ -17,14 +17,14 @@ namespace Components
static std::string CurrentPlaylistBuffer; static std::string CurrentPlaylistBuffer;
static std::unordered_map<const void*, std::string> MapRelocation; static std::unordered_map<const void*, std::string> MapRelocation;
static DWORD StorePlaylistStub(const char** buffer); static char* Com_ParseOnLine_Hk(const char** data_p);
static void PlaylistRequest(const Network::Address& address, const std::string& data); static void PlaylistRequest(const Network::Address& address, const std::string& data);
static void PlaylistReponse(const Network::Address& address, const std::string& data); static void PlaylistResponse(const Network::Address& address, const std::string& data);
static void PlaylistInvalidPassword(const Network::Address& address, const std::string& data); static void PlaylistInvalidPassword(const Network::Address& address, const std::string& data);
static void MapNameCopy(char *dest, const char *src, int destsize); static void MapNameCopy(char* dest, const char* src, int destsize);
static void SetMapName(const char* cvar, const char* value); static void SetMapName(const char* dvarName, const char* value);
static int GetMapIndex(const char* mapname); static int GetMapIndex(const char* mapname);
}; };
} }

View File

@ -131,7 +131,7 @@ namespace Components
Utils::InfoString ServerInfo::GetInfo() Utils::InfoString ServerInfo::GetInfo()
{ {
auto maxClientCount = *Game::svs_clientCount; auto maxClientCount = *Game::svs_clientCount;
const auto password = Dvar::Var("g_password").get<std::string>(); const auto* password = (*Game::g_password)->current.string;
if (!maxClientCount) if (!maxClientCount)
{ {
@ -145,7 +145,7 @@ namespace Components
info.set("shortversion", SHORTVERSION); info.set("shortversion", SHORTVERSION);
info.set("version", (*Game::version)->current.string); info.set("version", (*Game::version)->current.string);
info.set("mapname", (*Game::sv_mapname)->current.string); info.set("mapname", (*Game::sv_mapname)->current.string);
info.set("isPrivate", password.empty() ? "0" : "1"); info.set("isPrivate", *password ? "1" : "0");
info.set("checksum", Utils::String::VA("%X", Utils::Cryptography::JenkinsOneAtATime::Compute(Utils::String::VA("%u", Game::Sys_Milliseconds())))); info.set("checksum", Utils::String::VA("%X", Utils::Cryptography::JenkinsOneAtATime::Compute(Utils::String::VA("%u", Game::Sys_Milliseconds()))));
info.set("aimAssist", (Gamepad::sv_allowAimAssist.get<bool>() ? "1" : "0")); info.set("aimAssist", (Gamepad::sv_allowAimAssist.get<bool>() ? "1" : "0"));
info.set("voiceChat", (Voice::SV_VoiceEnabled() ? "1" : "0")); info.set("voiceChat", (Voice::SV_VoiceEnabled() ? "1" : "0"));

View File

@ -17,7 +17,7 @@ namespace Components
{ {
printf("%s", "IW4x " VERSION " (built " __DATE__ " " __TIME__ ")\n"); printf("%s", "IW4x " VERSION " (built " __DATE__ " " __TIME__ ")\n");
printf("%d\n", REVISION); printf("%d\n", REVISION);
ExitProcess(0); std::exit(0);
} }
Console::FreeNativeConsole(); Console::FreeNativeConsole();
@ -28,7 +28,7 @@ namespace Components
if (!FirstInstance && !ConnectProtocol::Used() && MessageBoxA(nullptr, "Do you want to start another instance?\nNot all features will be available!", "Game already running", MB_ICONEXCLAMATION | MB_YESNO) == IDNO) if (!FirstInstance && !ConnectProtocol::Used() && MessageBoxA(nullptr, "Do you want to start another instance?\nNot all features will be available!", "Game already running", MB_ICONEXCLAMATION | MB_YESNO) == IDNO)
{ {
ExitProcess(0); std::exit(0);
} }
} }
} }

View File

@ -49,7 +49,6 @@ BOOL APIENTRY DllMain(HINSTANCE /*hinstDLL*/, DWORD fdwReason, LPVOID /*lpvReser
if (fdwReason == DLL_PROCESS_ATTACH) if (fdwReason == DLL_PROCESS_ATTACH)
{ {
SetProcessDEPPolicy(PROCESS_DEP_ENABLE); SetProcessDEPPolicy(PROCESS_DEP_ENABLE);
Steam::Proxy::RunMod();
std::srand(std::uint32_t(std::time(nullptr)) ^ ~(GetTickCount() * GetCurrentProcessId())); std::srand(std::uint32_t(std::time(nullptr)) ^ ~(GetTickCount() * GetCurrentProcessId()));
@ -72,6 +71,7 @@ BOOL APIENTRY DllMain(HINSTANCE /*hinstDLL*/, DWORD fdwReason, LPVOID /*lpvReser
} }
#endif #endif
Steam::Proxy::RunMod();
// Install entry point hook // Install entry point hook
Utils::Hook(0x6BAC0F, Main::EntryPoint, HOOK_JUMP).install()->quick(); Utils::Hook(0x6BAC0F, Main::EntryPoint, HOOK_JUMP).install()->quick();
} }

View File

@ -31,6 +31,8 @@ namespace Game
int* com_errorPrintsCount = reinterpret_cast<int*>(0x1AD7910); int* com_errorPrintsCount = reinterpret_cast<int*>(0x1AD7910);
int* errorcode = reinterpret_cast<int*>(0x1AD7EB4);
char* Com_GetParseThreadInfo() char* Com_GetParseThreadInfo()
{ {
if (Sys_IsMainThread()) if (Sys_IsMainThread())

View File

@ -35,7 +35,7 @@ namespace Game
typedef void(*Com_BeginParseSession_t)(const char* filename); typedef void(*Com_BeginParseSession_t)(const char* filename);
extern Com_BeginParseSession_t Com_BeginParseSession; extern Com_BeginParseSession_t Com_BeginParseSession;
typedef char* (*Com_ParseOnLine_t)(const char** data_p); typedef char*(*Com_ParseOnLine_t)(const char** data_p);
extern Com_ParseOnLine_t Com_ParseOnLine; extern Com_ParseOnLine_t Com_ParseOnLine;
typedef void(*Com_SkipRestOfLine_t)(const char** data); typedef void(*Com_SkipRestOfLine_t)(const char** data);
@ -71,6 +71,8 @@ namespace Game
extern int* com_errorPrintsCount; extern int* com_errorPrintsCount;
extern int* errorcode;
extern char* Com_GetParseThreadInfo(); extern char* Com_GetParseThreadInfo();
extern void Com_SetParseNegativeNumbers(int parse); extern void Com_SetParseNegativeNumbers(int parse);

View File

@ -52,6 +52,7 @@ namespace Game
const dvar_t** g_allowVote = reinterpret_cast<const dvar_t**>(0x19BD644); const dvar_t** g_allowVote = reinterpret_cast<const dvar_t**>(0x19BD644);
const dvar_t** g_oldVoting = reinterpret_cast<const dvar_t**>(0x1A45DEC); const dvar_t** g_oldVoting = reinterpret_cast<const dvar_t**>(0x1A45DEC);
const dvar_t** g_gametype = reinterpret_cast<const dvar_t**>(0x1A45DC8); const dvar_t** g_gametype = reinterpret_cast<const dvar_t**>(0x1A45DC8);
const dvar_t** g_password = reinterpret_cast<const dvar_t**>(0x18835C0);
const dvar_t** version = reinterpret_cast<const dvar_t**>(0x1AD7930); const dvar_t** version = reinterpret_cast<const dvar_t**>(0x1AD7930);

View File

@ -108,6 +108,7 @@ namespace Game
extern const dvar_t** g_allowVote; extern const dvar_t** g_allowVote;
extern const dvar_t** g_oldVoting; extern const dvar_t** g_oldVoting;
extern const dvar_t** g_gametype; extern const dvar_t** g_gametype;
extern const dvar_t** g_password;
extern const dvar_t** version; extern const dvar_t** version;

View File

@ -268,6 +268,8 @@ namespace Game
LargeLocalBeginRight_t LargeLocalBeginRight = LargeLocalBeginRight_t(0x644140); LargeLocalBeginRight_t LargeLocalBeginRight = LargeLocalBeginRight_t(0x644140);
LargeLocalReset_t LargeLocalReset = LargeLocalReset_t(0x430630); LargeLocalReset_t LargeLocalReset = LargeLocalReset_t(0x430630);
longjmp_internal_t longjmp_internal = longjmp_internal_t(0x6B8898);
CmdArgs* cmd_args = reinterpret_cast<CmdArgs*>(0x1AAC5D0); CmdArgs* cmd_args = reinterpret_cast<CmdArgs*>(0x1AAC5D0);
CmdArgs* sv_cmd_args = reinterpret_cast<CmdArgs*>(0x1ACF8A0); CmdArgs* sv_cmd_args = reinterpret_cast<CmdArgs*>(0x1ACF8A0);
@ -405,6 +407,8 @@ namespace Game
punctuation_s* default_punctuations = reinterpret_cast<punctuation_s*>(0x797F80); punctuation_s* default_punctuations = reinterpret_cast<punctuation_s*>(0x797F80);
bool* s_havePlaylists = reinterpret_cast<bool*>(0x1AD3680);
const char* TableLookup(StringTable* stringtable, int row, int column) const char* TableLookup(StringTable* stringtable, int row, int column)
{ {
if (!stringtable || !stringtable->values || row >= stringtable->rowCount || column >= stringtable->columnCount) return ""; if (!stringtable || !stringtable->values || row >= stringtable->rowCount || column >= stringtable->columnCount) return "";

View File

@ -593,6 +593,9 @@ namespace Game
typedef void(*LargeLocalReset_t)(); typedef void(*LargeLocalReset_t)();
extern LargeLocalReset_t LargeLocalReset; extern LargeLocalReset_t LargeLocalReset;
typedef void(*longjmp_internal_t)(jmp_buf env, int status);
extern longjmp_internal_t longjmp_internal;
constexpr std::size_t STATIC_MAX_LOCAL_CLIENTS = 1; constexpr std::size_t STATIC_MAX_LOCAL_CLIENTS = 1;
constexpr std::size_t MAX_LOCAL_CLIENTS = 1; constexpr std::size_t MAX_LOCAL_CLIENTS = 1;
constexpr std::size_t MAX_CLIENTS = 18; constexpr std::size_t MAX_CLIENTS = 18;
@ -739,6 +742,8 @@ namespace Game
extern punctuation_s* default_punctuations; extern punctuation_s* default_punctuations;
extern bool* s_havePlaylists;
constexpr auto MAX_MSGLEN = 0x20000; constexpr auto MAX_MSGLEN = 0x20000;
ScreenPlacement* ScrPlace_GetFullPlacement(); ScreenPlacement* ScrPlace_GetFullPlacement();