[Command]: Refactor (#1013)

This commit is contained in:
Edo 2023-05-06 14:20:56 +01:00 committed by GitHub
parent da1c5bfcf6
commit d7d06ea47b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
43 changed files with 190 additions and 201 deletions

View File

@ -511,7 +511,7 @@ namespace Components
if (!Dedicated::IsEnabled() && !ZoneBuilder::IsEnabled())
{
Command::Add("securityLevel", [](Command::Params* params)
Command::Add("securityLevel", [](const Command::Params* params)
{
if (params->size() < 2)
{

View File

@ -232,9 +232,9 @@ namespace Components
SaveBans(&list);
}
Bans::Bans()
void Bans::AddServerCommands()
{
Command::Add("banClient", [](Command::Params* params)
Command::AddSV("banClient", [](const Command::Params* params)
{
if (!Dedicated::IsRunning())
{
@ -278,11 +278,11 @@ namespace Components
return;
}
const std::string reason = params->size() < 3 ? "EXE_ERR_BANNED_PERM" : params->join(2);
const auto reason = params->size() < 3 ? "EXE_ERR_BANNED_PERM"s : params->join(2);
BanClient(cl, reason);
});
Command::Add("unbanClient", [](Command::Params* params)
Command::AddSV("unbanClient", [](const Command::Params* params)
{
if (!Dedicated::IsRunning())
{
@ -317,4 +317,9 @@ namespace Components
}
});
}
Bans::Bans()
{
Events::OnSVInit(AddServerCommands);
}
}

View File

@ -29,5 +29,7 @@ namespace Components
static void LoadBans(BanList* list);
static void SaveBans(const BanList* list);
static void AddServerCommands();
};
}

View File

@ -407,37 +407,9 @@ namespace Components
}
}
Bots::Bots()
void Bots::AddServerCommands()
{
AssertOffset(Game::client_s, bIsTestClient, 0x41AF0);
AssertOffset(Game::client_s, ping, 0x212C8);
AssertOffset(Game::client_s, gentity, 0x212A0);
// Replace connect string
Utils::Hook::Set<const char*>(0x48ADA6, "connect bot%d \"\\cg_predictItems\\1\\cl_anonymous\\0\\color\\4\\head\\default\\model\\multi\\snaps\\20\\rate\\5000\\name\\%s\\clanAbbrev\\%s\\protocol\\%d\\checksum\\%d\\statver\\%d %u\\qport\\%d\"");
// Intercept sprintf for the connect string
Utils::Hook(0x48ADAB, BuildConnectString, HOOK_CALL).install()->quick();
Utils::Hook(0x627021, SV_BotUserMove_Hk, HOOK_CALL).install()->quick();
Utils::Hook(0x627241, SV_BotUserMove_Hk, HOOK_CALL).install()->quick();
Utils::Hook(0x441B80, G_SelectWeaponIndex_Hk, HOOK_JUMP).install()->quick();
Utils::Hook(0x459654, SV_GetClientPing_Hk, HOOK_CALL).install()->quick();
sv_randomBotNames = Game::Dvar_RegisterBool("sv_randomBotNames", false, Game::DVAR_NONE, "Randomize the bots' names");
sv_replaceBots = Game::Dvar_RegisterBool("sv_replaceBots", false, Game::DVAR_NONE, "Test clients will be replaced by connecting players when the server is full.");
// Reset BotMovementInfo.active when client is dropped
Events::OnClientDisconnect([](const int clientNum) -> void
{
g_botai[clientNum].active = false;
});
CleanBotArray();
Command::Add("spawnBot", [](Command::Params* params)
Command::AddSV("spawnBot", [](const Command::Params* params)
{
if (!Dedicated::IsRunning())
{
@ -467,8 +439,7 @@ namespace Components
if (input == end)
{
Logger::Warning(Game::CON_CHANNEL_DONT_FILTER, "{} is not a valid input\nUsage: {} optional <number of bots> or optional <\"all\">\n",
input, params->get(0));
Logger::Warning(Game::CON_CHANNEL_DONT_FILTER, "{} is not a valid input\nUsage: {} optional <number of bots> or optional <\"all\">\n", input, params->get(0));
return;
}
}
@ -480,6 +451,39 @@ namespace Components
Spawn(count);
});
}
Bots::Bots()
{
AssertOffset(Game::client_s, bIsTestClient, 0x41AF0);
AssertOffset(Game::client_s, ping, 0x212C8);
AssertOffset(Game::client_s, gentity, 0x212A0);
// Replace connect string
Utils::Hook::Set<const char*>(0x48ADA6, "connect bot%d \"\\cg_predictItems\\1\\cl_anonymous\\0\\color\\4\\head\\default\\model\\multi\\snaps\\20\\rate\\5000\\name\\%s\\clanAbbrev\\%s\\protocol\\%d\\checksum\\%d\\statver\\%d %u\\qport\\%d\"");
// Intercept sprintf for the connect string
Utils::Hook(0x48ADAB, BuildConnectString, HOOK_CALL).install()->quick();
Utils::Hook(0x627021, SV_BotUserMove_Hk, HOOK_CALL).install()->quick();
Utils::Hook(0x627241, SV_BotUserMove_Hk, HOOK_CALL).install()->quick();
Utils::Hook(0x441B80, G_SelectWeaponIndex_Hk, HOOK_JUMP).install()->quick();
Utils::Hook(0x459654, SV_GetClientPing_Hk, HOOK_CALL).install()->quick();
sv_randomBotNames = Game::Dvar_RegisterBool("sv_randomBotNames", false, Game::DVAR_NONE, "Randomize the bots' names");
sv_replaceBots = Game::Dvar_RegisterBool("sv_replaceBots", false, Game::DVAR_NONE, "Test clients will be replaced by connecting players when the server is full.");
// Reset BotMovementInfo.active when client is dropped
Events::OnClientDisconnect([](const int clientNum) -> void
{
g_botai[clientNum].active = false;
});
Events::OnSVInit(AddServerCommands);
CleanBotArray();
AddScriptMethods();

View File

@ -36,5 +36,7 @@ namespace Components
static bool IsFull();
static void CleanBotArray();
static void AddServerCommands();
};
}

View File

@ -202,7 +202,7 @@ namespace Components
std::memset(&CustomTitles, 0, sizeof(char[Game::MAX_CLIENTS][18]));
ServerCommands::OnCommand(21, [](Command::Params* params)
ServerCommands::OnCommand(21, [](const Command::Params* params)
{
if (std::strcmp(params->get(1), "customTitles") == 0)
{
@ -214,7 +214,6 @@ namespace Components
}
return false;
});
Utils::Hook(0x62EB26, GetPlayerCardClientInfoStub).install()->quick();

View File

@ -380,9 +380,9 @@ namespace Components
});
}
void Chat::AddChatCommands()
void Chat::AddServerCommands()
{
Command::AddSV("muteClient", [](Command::Params* params)
Command::AddSV("muteClient", [](const Command::Params* params)
{
if (!Dedicated::IsRunning())
{
@ -405,7 +405,7 @@ namespace Components
}
});
Command::AddSV("unmute", [](Command::Params* params)
Command::AddSV("unmute", [](const Command::Params* params)
{
if (!Dedicated::IsRunning())
{
@ -446,7 +446,7 @@ namespace Components
}
});
Command::AddSV("say", [](Command::Params* params)
Command::AddSV("say", [](const Command::Params* params)
{
if (!Dedicated::IsRunning())
{
@ -471,7 +471,7 @@ namespace Components
}
});
Command::AddSV("tell", [](Command::Params* params)
Command::AddSV("tell", [](const Command::Params* params)
{
if (!Dedicated::IsRunning())
{
@ -499,7 +499,7 @@ namespace Components
}
});
Command::AddSV("sayraw", [](Command::Params* params)
Command::AddSV("sayraw", [](const Command::Params* params)
{
if (!Dedicated::IsRunning())
{
@ -514,7 +514,7 @@ namespace Components
Logger::Print("Raw: {}\n", message);
});
Command::AddSV("tellraw", [](Command::Params* params)
Command::AddSV("tellraw", [](const Command::Params* params)
{
if (!Dedicated::IsRunning())
{
@ -610,7 +610,7 @@ namespace Components
cg_chatWidth = Dvar::Register<int>("cg_chatWidth", 52, 1, std::numeric_limits<int>::max(), Game::DVAR_ARCHIVE, "The normalized maximum width of a chat message");
sv_disableChat = Dvar::Register<bool>("sv_disableChat", false, Game::DVAR_NONE, "Disable chat messages from clients");
Events::OnSVInit(AddChatCommands);
Events::OnSVInit(AddServerCommands);
LoadMutedList();
@ -622,6 +622,12 @@ namespace Components
// Change logic that does word splitting with new lines for chat messages to support fonticons
Utils::Hook(0x592E10, CG_AddToTeamChat_Stub, HOOK_JUMP).install()->quick();
// Add back removed command from CoD4
Command::Add("mp_QuickMessage", []() -> void
{
Command::Execute("openmenu quickmessage");
});
AddScriptFunctions();
// Avoid duplicates

View File

@ -42,7 +42,7 @@ namespace Components
static void SaveMutedList(const muteList& list);
static void LoadMutedList();
static void AddChatCommands();
static void AddServerCommands();
static int GetCallbackReturn();
static int ChatCallback(Game::gentity_s* self, const char* codePos, const char* message, int mode);

View File

@ -240,7 +240,7 @@ namespace Components
std::memset(&ClientState, 0, sizeof(char[Game::MAX_CLIENTS][MAX_CLAN_NAME_LENGTH]));
ServerCommands::OnCommand(22, [](Command::Params* params)
ServerCommands::OnCommand(22, [](const Command::Params* params)
{
if (std::strcmp(params->get(1), "clanNames") == 0)
{

View File

@ -2,8 +2,8 @@
namespace Components
{
std::unordered_map<std::string, std::function<void(Command::Params*)>> Command::FunctionMap;
std::unordered_map<std::string, std::function<void(Command::Params*)>> Command::FunctionMapSV;
std::unordered_map<std::string, Command::commandCallback> Command::FunctionMap;
std::unordered_map<std::string, Command::commandCallback> Command::FunctionMapSV;
std::string Command::Params::join(const int index) const
{
@ -68,7 +68,7 @@ namespace Components
});
}
void Command::Add(const char* name, const std::function<void(Params*)>& callback)
void Command::Add(const char* name, const commandCallback& callback)
{
const auto command = Utils::String::ToLower(name);
@ -80,7 +80,7 @@ namespace Components
FunctionMap.insert_or_assign(command, callback);
}
void Command::AddSV(const char* name, const std::function<void(Params*)>& callback)
void Command::AddSV(const char* name, const commandCallback& callback)
{
if (Loader::IsPregame())
{

View File

@ -54,19 +54,21 @@ namespace Components
Command();
static Game::cmd_function_s* Allocate();
using commandCallback = std::function<void(const Params*)>;
static void Add(const char* name, const std::function<void()>& callback);
static void Add(const char* name, const std::function<void(Params*)>& callback);
static void Add(const char* name, const commandCallback& callback);
static void AddRaw(const char* name, void(*callback)(), bool key = false);
static void AddSV(const char* name, const std::function<void(Params*)>& callback);
static void AddSV(const char* name, const commandCallback& callback);
static void Execute(std::string command, bool sync = true);
static Game::cmd_function_s* Find(const std::string& command);
private:
static std::unordered_map<std::string, std::function<void(Params*)>> FunctionMap;
static std::unordered_map<std::string, std::function<void(Params*)>> FunctionMapSV;
static std::unordered_map<std::string, commandCallback> FunctionMap;
static std::unordered_map<std::string, commandCallback> FunctionMapSV;
static Game::cmd_function_s* Allocate();
static void AddRawSV(const char* name, void(*callback)());

View File

@ -272,7 +272,7 @@ namespace Components
assert(0 && "a");
}
void Debug::Com_Bug_f(Command::Params* params)
void Debug::Com_Bug_f(const Command::Params* params)
{
char newFileName[MAX_PATH]{};
char to_ospath[MAX_OSPATH]{};

View File

@ -40,7 +40,7 @@ namespace Components
static void CG_DrawDebugOverlays_Hk(int localClientNum);
static void Com_Assert_f();
static void Com_Bug_f(Command::Params* params);
static void Com_Bug_f(const Command::Params* params);
static void Com_BugNameInc_f();
static void CL_InitDebugDvars();

View File

@ -267,7 +267,6 @@ namespace Components
Game::DvarValue value;
value.integer = 0;
Game::Dvar_SetVariant(const_cast<Game::dvar_t*>(com_dedicated), value, Game::DVAR_SOURCE_INTERNAL);
}
});
@ -291,14 +290,10 @@ namespace Components
}
else
{
for (int i = 0; i < ARRAYSIZE(PlayerGuids); ++i)
{
PlayerGuids[i][0].bits = 0;
PlayerGuids[i][1].bits = 0;
}
ZeroMemory(PlayerGuids, sizeof(PlayerGuids));
// Intercept server commands
ServerCommands::OnCommand(20, [](Command::Params* params)
ServerCommands::OnCommand(20, [](const Command::Params* params)
{
for (int client = 0; client < 18; client++)
{

View File

@ -609,7 +609,7 @@ namespace Components
}, Scheduler::Pipeline::RENDERER);
}
Command::Add("loadzone", [](Command::Params* params)
Command::Add("loadzone", [](const Command::Params* params)
{
if (params->size() < 2) return;
@ -621,7 +621,7 @@ namespace Components
Game::DB_LoadXAssets(&info, 1, true);
});
Command::Add("awaitDatabase", [](Command::Params*)
Command::Add("awaitDatabase", []()
{
Logger::Print("Waiting for database...\n");
while (!Game::Sys_IsDatabaseReady()) std::this_thread::sleep_for(100ms);

View File

@ -461,21 +461,6 @@ namespace Components
Friends::CurrentFriend = index;
}
void Friends::AddFriend(SteamID user)
{
if (Steam::Proxy::ClientFriends && Steam::Proxy::SteamFriends)
{
if (Steam::Proxy::ClientFriends.invoke<bool>("AddFriend", user))
{
Toast::Show("cardicon_joystick", Steam::Proxy::SteamFriends->GetFriendPersonaName(user), "friend request sent", 3000);
}
else
{
Toast::Show("cardicon_stop", Steam::Proxy::SteamFriends->GetFriendPersonaName(user), "unable to send friend request", 3000);
}
}
}
int Friends::GetGame(SteamID user)
{
int appId = 0;
@ -574,20 +559,6 @@ namespace Components
Friends::CLAnonymous = Dvar::Register<bool>("cl_anonymous", false, Game::DVAR_ARCHIVE, "Enable invisible mode for Steam");
Friends::CLNotifyFriendState = Dvar::Register<bool>("cl_notifyFriendState", true, Game::DVAR_ARCHIVE, "Update friends about current game status");
Command::Add("addFriend", [](Command::Params* params)
{
if (params->size() < 2)
{
Logger::Print("Usage: {} <Steam ID in hexadecimal format>\n", params->get(0));
return;
}
SteamID id;
id.bits = std::strtoull(params->get(1), nullptr, 16);
Friends::AddFriend(id);
});
// Hook Live_ShowFriendsList
Utils::Hook(0x4D6C70, []()
{

View File

@ -19,8 +19,6 @@ namespace Components
static void RequestPresence(SteamID user);
static std::string GetPresence(SteamID user, const std::string& key);
static void AddFriend(SteamID user);
static int GetGame(SteamID user);
static bool IsInvisible();

View File

@ -1760,7 +1760,7 @@ namespace Components
return Game::GPAD_MAP_NONE;
}
void Gamepad::Axis_Bind_f(Command::Params* params)
void Gamepad::Axis_Bind_f(const Command::Params* params)
{
if (params->size() < 4)
{
@ -1796,7 +1796,7 @@ namespace Components
Gamepad_BindAxis(0, physicalAxis, virtualAxis, mapping);
}
void Gamepad::Axis_Unbindall_f(Command::Params*)
void Gamepad::Axis_Unbindall_f()
{
auto& gamePadGlobal = gamePadGlobals[0];
@ -1807,19 +1807,19 @@ namespace Components
}
}
void Gamepad::Bind_GP_SticksConfigs_f(Command::Params*)
void Gamepad::Bind_GP_SticksConfigs_f()
{
const auto* stickConfigName = gpad_sticksConfig.get<const char*>();
Game::Cbuf_AddText(0, Utils::String::VA("exec %s\n", stickConfigName));
}
void Gamepad::Bind_GP_ButtonsConfigs_f(Command::Params*)
void Gamepad::Bind_GP_ButtonsConfigs_f()
{
const auto* buttonConfigName = gpad_buttonConfig.get<const char*>();
Game::Cbuf_AddText(0, Utils::String::VA("exec %s\n", buttonConfigName));
}
void Gamepad::Scores_Toggle_f(Command::Params*)
void Gamepad::Scores_Toggle_f()
{
if (Game::cgArray[0].nextSnap)
{

View File

@ -184,11 +184,11 @@ namespace Components
static Game::GamepadPhysicalAxis StringToPhysicalAxis(const char* str);
static Game::GamepadVirtualAxis StringToVirtualAxis(const char* str);
static Game::GamepadMapping StringToGamePadMapping(const char* str);
static void Axis_Bind_f(Command::Params* params);
static void Axis_Unbindall_f(Command::Params* params);
static void Bind_GP_SticksConfigs_f(Command::Params* params);
static void Bind_GP_ButtonsConfigs_f(Command::Params* params);
static void Scores_Toggle_f(Command::Params* params);
static void Axis_Bind_f(const Command::Params* params);
static void Axis_Unbindall_f();
static void Bind_GP_SticksConfigs_f();
static void Bind_GP_ButtonsConfigs_f();
static void Scores_Toggle_f();
static void InitDvars();
static void CG_RegisterDvars_Hk();

View File

@ -225,7 +225,7 @@ namespace Components
});
// Test pipe functionality by sending pings
Command::Add("ipcping", []([[maybe_unused]] Command::Params* params)
Command::Add("ipcping", []()
{
Logger::Print("Sending ping to pipe!\n");
Write("ping", {});

View File

@ -274,20 +274,20 @@ namespace Components
void Logger::AddServerCommands()
{
Command::AddSV("log_add", [](Command::Params* params)
Command::AddSV("log_add", [](const Command::Params* params)
{
if (params->size() < 2) return;
std::unique_lock lock(LoggingMutex);
Network::Address addr(params->get(1));
if (std::find(LoggingAddresses[0].begin(), LoggingAddresses[0].end(), addr) == LoggingAddresses[0].end())
if (std::ranges::find(LoggingAddresses[0], addr) == LoggingAddresses[0].end())
{
LoggingAddresses[0].push_back(addr);
}
});
Command::AddSV("log_del", [](Command::Params* params)
Command::AddSV("log_del", [](const Command::Params* params)
{
if (params->size() < 2) return;
@ -304,8 +304,7 @@ namespace Components
{
Network::Address addr(params->get(1));
const auto i = std::find(LoggingAddresses[0].begin(), LoggingAddresses[0].end(), addr);
if (i != LoggingAddresses[0].end())
if (const auto i = std::ranges::find(LoggingAddresses[0], addr); i != LoggingAddresses[0].end())
{
LoggingAddresses[0].erase(i);
Print("Address {} removed\n", addr.getString());
@ -317,7 +316,7 @@ namespace Components
}
});
Command::AddSV("log_list", []([[maybe_unused]] Command::Params* params)
Command::AddSV("log_list", []([[maybe_unused]] const Command::Params* params)
{
Print("# ID: Address\n");
Print("-------------\n");
@ -330,20 +329,20 @@ namespace Components
}
});
Command::AddSV("g_log_add", [](Command::Params* params)
Command::AddSV("g_log_add", [](const Command::Params* params)
{
if (params->size() < 2) return;
std::unique_lock lock(LoggingMutex);
const Network::Address addr(params->get(1));
if (std::find(LoggingAddresses[1].begin(), LoggingAddresses[1].end(), addr) == LoggingAddresses[1].end())
if (std::ranges::find(LoggingAddresses[1], addr) == LoggingAddresses[1].end())
{
LoggingAddresses[1].push_back(addr);
}
});
Command::AddSV("g_log_del", [](Command::Params* params)
Command::AddSV("g_log_del", [](const Command::Params* params)
{
if (params->size() < 2) return;
@ -372,7 +371,7 @@ namespace Components
}
});
Command::AddSV("g_log_list", [](Command::Params*)
Command::AddSV("g_log_list", []([[maybe_unused]] const Command::Params* params)
{
Print("# ID: Address\n");
Print("-------------\n");

View File

@ -434,7 +434,7 @@ namespace Components
MapDump::MapDump()
{
Command::Add("dumpmap", [](Command::Params*)
Command::Add("dumpmap", []()
{
if (Dedicated::IsEnabled() || ZoneBuilder::IsEnabled())
{

View File

@ -176,7 +176,7 @@ namespace Components
void MapRotation::AddMapRotationCommands()
{
Command::AddSV("addMap", [](Command::Params* params)
Command::AddSV("addMap", [](const Command::Params* params)
{
if (params->size() < 2)
{
@ -187,7 +187,7 @@ namespace Components
DedicatedRotation.addEntry("map", params->get(1));
});
Command::AddSV("addGametype", [](Command::Params* params)
Command::AddSV("addGametype", [](const Command::Params* params)
{
if (params->size() < 2)
{

View File

@ -838,7 +838,7 @@ namespace Components
Utils::Hook(0x5A9D51, Maps::LoadMapLoadscreenStub, HOOK_CALL).install()->quick();
Utils::Hook(0x5B34DD, Maps::LoadMapLoadscreenStub, HOOK_CALL).install()->quick();
Command::Add("delayReconnect", []([[maybe_unused]] Command::Params* params)
Command::Add("delayReconnect", []()
{
Scheduler::Once([]
{
@ -852,7 +852,7 @@ namespace Components
Utils::Hook(0x4A7251, Maps::LoadNewMapCommand, HOOK_CALL).install()->quick();
}
// Download the map before a maprotation if necessary
// Download the map before a map rotation if necessary
// Conflicts with Theater's SV map rotation check, but this one is safer!
Utils::Hook(0x5AA91C, Maps::RotateCheckStub, HOOK_CALL).install()->quick();

View File

@ -828,7 +828,7 @@ namespace Components
// make Com_Error and similar go back to main_text instead of menu_xboxlive.
Utils::Hook::SetString(0x6FC790, "main_text");
Command::Add("openmenu", [](Command::Params* params)
Command::Add("openmenu", [](const Command::Params* params)
{
if (params->size() != 2)
{
@ -845,7 +845,7 @@ namespace Components
Game::Menus_OpenByName(Game::uiContext, params->get(1));
});
Command::Add("reloadmenus", []([[maybe_unused]] Command::Params* params)
Command::Add("reloadmenus", []()
{
// Close all menus
Game::Menus_CloseAll(Game::uiContext);
@ -868,11 +868,6 @@ namespace Components
}
});
Command::Add("mp_QuickMessage", [](Command::Params*)
{
Command::Execute("openmenu quickmessage");
});
// Define custom menus here
Add("ui_mp/changelog.menu");
Add("ui_mp/theater_menu.menu");

View File

@ -341,6 +341,33 @@ namespace Components
}
}
int Network::Sys_StringToSockaddr_Hk(const char* s, sockaddr* sadr)
{
hostent* h;
ZeroMemory(sadr, sizeof(*sadr));
((sockaddr_in*)sadr)->sin_family = AF_INET;
((sockaddr_in*)sadr)->sin_port = 0;
if (Game::I_isdigit(*s))
{
// ReSharper disable once CppDeprecatedEntity
*(int*)&((sockaddr_in*)sadr)->sin_addr = static_cast<int>(::inet_addr(s));
}
else
{
// ReSharper disable once CppDeprecatedEntity
if ((h = ::gethostbyname(s)) == nullptr)
{
return false;
}
*(int*)&((sockaddr_in*)sadr)->sin_addr = *(int*)h->h_addr_list[0];
}
return true;
}
Network::Network()
{
AssertSize(Game::netadr_t, 20);
@ -374,6 +401,10 @@ namespace Components
// Handle client packets
Utils::Hook(0x5AA703, CL_HandleCommandStub, HOOK_JUMP).install()->quick();
// Use the version of Sys_StringToSockaddr made by 3arc
Utils::Hook(0x44E23C, Sys_StringToSockaddr_Hk, HOOK_CALL).install()->quick();
Utils::Hook(0x64D480, Sys_StringToSockaddr_Hk, HOOK_CALL).install()->quick();
// Disable unused OOB packets handlers just to be sure
Utils::Hook::Set<std::uint8_t>(0x5AA5B6, 0xEB); // CL_SteamServerAuth
Utils::Hook::Set<std::uint8_t>(0x5AA69F, 0xEB); // echo
@ -413,6 +444,7 @@ namespace Components
auto* clc = Game::CL_GetLocalClientConnection(0);
if (!Game::NET_CompareBaseAdr(clc->serverAddress, *address))
{
Logger::Debug("Ignoring stray 'print' network message from '{}'", Game::NET_AdrToString(*address));
return;
}

View File

@ -89,6 +89,8 @@ namespace Components
static bool CL_HandleCommand(Game::netadr_t* address, const char* command, Game::msg_t* message);
static void CL_HandleCommandStub();
static int Sys_StringToSockaddr_Hk(const char* s, sockaddr* sadr);
};
}

View File

@ -13,7 +13,7 @@ namespace Components
std::recursive_mutex Node::Mutex;
std::vector<Node::Entry> Node::Nodes;
bool Node::wasIngame = false;
bool Node::WasIngame = false;
bool Node::Entry::isValid()
{
@ -154,14 +154,14 @@ namespace Components
{
if (ServerList::UseMasterServer) return; // don't run node frame if master server is active
if (*Game::clcState > 0)
if (Game::CL_GetLocalClientConnectionState(0) != Game::CA_DISCONNECTED)
{
wasIngame = true;
return; // don't run while ingame because it can still cause lag spikes on lower end PCs
WasIngame = true;
return; // don't run while in-game because it can still cause lag spikes on lower end PCs
}
}
if (wasIngame) // our last frame we were ingame and now we aren't so touch all nodes
if (WasIngame) // our last frame we were in-game and now we aren't so touch all nodes
{
for (auto i = Node::Nodes.begin(); i != Node::Nodes.end();++i)
{
@ -170,7 +170,8 @@ namespace Components
i->lastRequest.reset();
i->lastResponse.reset();
}
wasIngame = false;
WasIngame = false;
}
static Utils::Time::Interval frameLimit;
@ -344,7 +345,7 @@ namespace Components
Scheduler::OnGameInitialized(loadNodes, Scheduler::Pipeline::MAIN);
Command::Add("listnodes", [](Command::Params*)
Command::Add("listnodes", [](const Command::Params*)
{
Logger::Print("Nodes: {}\n", Node::Nodes.size());
@ -355,7 +356,7 @@ namespace Components
}
});
Command::Add("addnode", [](Command::Params* params)
Command::Add("addnode", [](const Command::Params* params)
{
if (params->size() < 2) return;
Node::Add({ params->get(1) });

View File

@ -44,7 +44,7 @@ namespace Components
private:
static std::recursive_mutex Mutex;
static std::vector<Entry> Nodes;
static bool wasIngame;
static bool WasIngame;
static void HandleResponse(Network::Address address, const std::string& data);

View File

@ -293,7 +293,7 @@ namespace Components
Utils::Hook::Xor<DWORD>(0x4D376D, Game::DVAR_LATCH);
Utils::Hook::Xor<DWORD>(0x5E3789, Game::DVAR_LATCH);
Command::Add("connect", [](Command::Params* params)
Command::Add("connect", [](const Command::Params* params)
{
if (params->size() < 2)
{
@ -311,7 +311,7 @@ namespace Components
}
});
Command::Add("reconnect", [](Command::Params*)
Command::Add("reconnect", []()
{
Connect(Container.target);
});

View File

@ -522,7 +522,7 @@ namespace Components
Command::Add("unlockstats", QuickPatch::UnlockStats);
Command::Add("dumptechsets", [](Command::Params* param)
Command::Add("dumptechsets", [](const Command::Params* param)
{
if (param->size() != 2)
{

View File

@ -21,7 +21,7 @@ namespace Components
void RCon::AddCommands()
{
Command::Add("rcon", [](Command::Params* params)
Command::Add("rcon", [](const Command::Params* params)
{
if (params->size() < 2) return;
@ -60,7 +60,7 @@ namespace Components
Logger::Print("You are connected to an invalid server\n");
});
Command::Add("remoteCommand", [](Command::Params* params)
Command::Add("remoteCommand", [](const Command::Params* params)
{
if (params->size() < 2) return;
@ -79,7 +79,7 @@ namespace Components
}
});
Command::AddSV("RconWhitelistAdd", [](Command::Params* params)
Command::AddSV("RconWhitelistAdd", [](const Command::Params* params)
{
if (params->size() < 2)
{

View File

@ -124,7 +124,7 @@ namespace Components
Utils::Hook(0x631640, GetMenuBuffer, HOOK_JUMP).install()->quick();
Utils::Hook(0x463500, Com_LoadInfoString_Hk, HOOK_JUMP).install()->quick();
Command::Add("dumpraw", [](Command::Params* params)
Command::Add("dumpraw", [](const Command::Params* params)
{
if (params->size() < 2)
{
@ -140,7 +140,7 @@ namespace Components
return;
}
const char* data = Game::Scr_AddSourceBuffer(nullptr, file.getName().data(), nullptr, false);
const auto* data = Game::Scr_AddSourceBuffer(nullptr, file.getName().data(), nullptr, false);
if (data)
{

View File

@ -7,7 +7,7 @@ namespace Components
public:
ServerCommands();
using serverCommandHandler = std::function<bool(Command::Params*)>;
using serverCommandHandler = std::function<bool(const Command::Params*)>;
static void OnCommand(std::int32_t cmd, const serverCommandHandler& callback);
private:

View File

@ -162,7 +162,7 @@ namespace Components
Utils::Hook::Set<BYTE>(0x4CC5F9, 0xEB);
// 'M' Seems to be used on Xbox only for parsing platform specific ranks
ServerCommands::OnCommand('M', [](Command::Params* params)
ServerCommands::OnCommand('M', [](const Command::Params* params)
{
const auto* arg1 = params->get(1);
const auto* arg2 = params->get(2);
@ -171,7 +171,7 @@ namespace Components
return true;
});
Command::Add("statGet", []([[maybe_unused]] Command::Params* params)
Command::Add("statGet", [](const Command::Params* params)
{
if (params->size() < 2)
{

View File

@ -157,20 +157,6 @@ namespace Components
// 15 or more custom classes
Utils::Hook::Set<BYTE>(0x60A2FE, NUM_CUSTOM_CLASSES);
#ifdef _DEBUG
// Reset empty names
Command::Add("checkClasses", [](Command::Params*)
{
for (int i = 0; i < NUM_CUSTOM_CLASSES; ++i)
{
// TODO: Correctly lookup using structured data
char* className = (reinterpret_cast<char*>(0x1AD3694) - 4 + 3003 + (64 * i) + 0x29);
if (!*className) strcpy_s(className, 24, Game::SEH_StringEd_GetString(Utils::String::VA("CLASS_SLOT%i", i + 1)));
}
});
#endif
return;
}
AssetHandler::OnLoad([](Game::XAssetType type, Game::XAssetHeader asset, const std::string& filename, bool* /*restrict*/)

View File

@ -1211,7 +1211,7 @@ namespace Components
}
});
Command::Add("verifyzone", [](Command::Params* params)
Command::Add("verifyzone", [](const Command::Params* params)
{
if (params->size() < 2) return;
@ -1250,7 +1250,7 @@ namespace Components
Logger::Print("\n");
});
Command::Add("buildzone", [](Command::Params* params)
Command::Add("buildzone", [](const Command::Params* params)
{
if (params->size() < 2) return;
@ -1260,7 +1260,7 @@ namespace Components
Zone(zoneName).build();
});
Command::Add("buildall", []([[maybe_unused]] Command::Params* params)
Command::Add("buildall", []()
{
auto path = std::format("{}\\zone_source", (*Game::fs_basepath)->current.string);
auto zoneSources = FileSystem::GetSysFileList(path, "csv", false);
@ -1327,7 +1327,7 @@ namespace Components
}
});
Command::Add("buildtechsets", [](Command::Params*)
Command::Add("buildtechsets", [](const Command::Params*)
{
Utils::IO::CreateDir("zone_source/techsets");
Utils::IO::CreateDir("zone/techsets");
@ -1580,7 +1580,7 @@ namespace Components
Zone("techsets/techsets").build();
});
Command::Add("listassets", [](Command::Params* params)
Command::Add("listassets", [](const Command::Params* params)
{
if (params->size() < 2) return;
Game::XAssetType type = Game::DB_GetXAssetNameType(params->get(1));
@ -1595,7 +1595,7 @@ namespace Components
}
});
Command::Add("loadtempzone", [](Command::Params* params)
Command::Add("loadtempzone", [](const Command::Params* params)
{
if (params->size() < 2) return;
@ -1609,7 +1609,7 @@ namespace Components
}
});
Command::Add("unloadtempzones", [](Command::Params*)
Command::Add("unloadtempzones", [](const Command::Params*)
{
Game::XZoneInfo info;
info.name = nullptr;
@ -1619,7 +1619,7 @@ namespace Components
AssetHandler::FindOriginalAsset(Game::XAssetType::ASSET_TYPE_RAWFILE, "default"); // Lock until zone is unloaded
});
Command::Add("materialInfoDump", [](Command::Params*)
Command::Add("materialInfoDump", [](const Command::Params*)
{
Game::DB_EnumXAssets(Game::ASSET_TYPE_MATERIAL, [](Game::XAssetHeader header, void*)
{
@ -1628,7 +1628,7 @@ namespace Components
}, nullptr, false);
});
Command::Add("iwiDump", [](Command::Params* params)
Command::Add("iwiDump", [](const Command::Params* params)
{
if (params->size() < 2) return;

View File

@ -1,4 +1,4 @@
#include <STDInclude.hpp>
#include <STDInclude.hpp>
#include <zlib.h>
@ -3482,7 +3482,7 @@ namespace Components
if (ZoneBuilder::IsEnabled())
{
Command::Add("decryptImages", [](Command::Params*)
Command::Add("decryptImages", []()
{
auto images = FileSystem::GetSysFileList("iw4x/images", "iwi");
Logger::Print("decrypting {} images...\n", images.size());
@ -3516,7 +3516,7 @@ namespace Components
Logger::Print("decrypted {} images!\n", images.size());
});
Command::Add("decryptSounds", []([[maybe_unused]] Command::Params* params)
Command::Add("decryptSounds", []()
{
auto sounds = FileSystem::GetSysFileList("iw4x/sound", "iwi");
Logger::Print("decrypting {} sounds...\n", sounds.size());
@ -3653,13 +3653,6 @@ namespace Components
Utils::Hook(0x4597DD, Zones::LoadStatement, HOOK_CALL).install()->quick();
Utils::Hook(0x471A39, Zones::LoadWindowImage, HOOK_JUMP).install()->quick();
#ifdef DEBUG
// Easy dirty disk debugging
Utils::Hook::Set<WORD>(0x4CF7F0, 0xC3CC);
// disable _invoke_watson to allow debugging
Utils::Hook::Set<WORD>(0x6B9602, 0xCCCC);
#endif
}
}
#pragma optimize( "", on )

View File

@ -58,12 +58,12 @@ BOOL APIENTRY DllMain(HINSTANCE /*hinstDLL*/, DWORD fdwReason, LPVOID /*lpvReser
if (!binary || std::memcmp(binary, BASEGAME_NAME, 14) != 0)
#endif
{
MessageBoxA(nullptr,
"Failed to load game binary.\n"
"You did not install the iw4x-rawfiles!\n"
"Please use the XLabs launcher to run the game. For support, please visit https://xlabs.dev/support_iw4x_client",
"ERROR",
MB_ICONERROR
MessageBoxA(nullptr,
"Failed to load game binary.\n"
"You did not install the iw4x-rawfiles!\n"
"Please use the XLabs launcher to run the game. For support, please visit https://xlabs.dev/support_iw4x_client",
"ERROR",
MB_ICONERROR
);
return FALSE;
}

View File

@ -58,6 +58,7 @@ namespace Game
connstate_t CL_GetLocalClientConnectionState(const int localClientNum)
{
AssertOffset(clientUIActive_t, connectionState, 0x9B8);
AssertIn(localClientNum, STATIC_MAX_LOCAL_CLIENTS);
return clientUIActives[localClientNum].connectionState;

View File

@ -238,6 +238,7 @@ namespace Game
I_strncpyz_t I_strncpyz = I_strncpyz_t(0x4D6F80);
I_CleanStr_t I_CleanStr = I_CleanStr_t(0x4AD470);
I_isdigit_t I_isdigit = I_isdigit_t(0x4E71E0);
XNAddrToString_t XNAddrToString = XNAddrToString_t(0x452690);
@ -318,8 +319,6 @@ namespace Game
infoParm_t* infoParams = reinterpret_cast<infoParm_t*>(0x79D260); // Count 0x1E
clientState_t* clcState = reinterpret_cast<clientState_t*>(0xB2C540);
GfxScene* scene = reinterpret_cast<GfxScene*>(0x6944914);
Console* con = reinterpret_cast<Console*>(0x9FCCF8);

View File

@ -554,6 +554,9 @@ namespace Game
typedef char*(*I_CleanStr_t)(char* string);
extern I_CleanStr_t I_CleanStr;
typedef bool(*I_isdigit_t)(int c);
extern I_isdigit_t I_isdigit;
typedef void(*XNAddrToString_t)(const XNADDR* xnaddr, char* str);
extern XNAddrToString_t XNAddrToString;
@ -659,8 +662,6 @@ namespace Game
extern infoParm_t* infoParams;
extern clientState_t* clcState;
extern GfxScene* scene;
extern Console* con;

View File

@ -2,15 +2,11 @@
#ifndef RC_INVOKED
#define VC_EXTRALEAN
#define WIN32_LEAN_AND_MEAN
#define _CRT_SECURE_NO_WARNINGS
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define _USE_MATH_DEFINES
// Requires Visual Leak Detector plugin: http://vld.codeplex.com/
#define VLD_FORCE_ENABLE
//#include <vld.h>
#include <Windows.h>
#include <WinSock2.h>
#include <ShlObj.h>