Refactor clientcommand

This commit is contained in:
FutureRave 2022-05-11 19:32:56 +01:00
parent dfe71ad8f7
commit 62cd7362b0
No known key found for this signature in database
GPG Key ID: E883E2BC9657D955
15 changed files with 133 additions and 124 deletions

View File

@ -1,5 +1,7 @@
#include <std_include.hpp>
#include "loader/component_loader.hpp"
#include "game/game.hpp"
#include "steam/steam.hpp"
#include "auth.hpp"
#include "command.hpp"
@ -11,9 +13,6 @@
#include <utils/info_string.hpp>
#include <utils/cryptography.hpp>
#include "game/game.hpp"
#include "steam/steam.hpp"
namespace auth
{
namespace

View File

@ -1,5 +1,7 @@
#include <std_include.hpp>
#include "loader/component_loader.hpp"
#include "game/game.hpp"
#include "game/scripting/execution.hpp"
#include "command.hpp"
#include "scheduler.hpp"
@ -7,9 +9,6 @@
#include "network.hpp"
#include "server_list.hpp"
#include "game/game.hpp"
#include "game/scripting/execution.hpp"
#include <utils/hook.hpp>
#include <utils/string.hpp>
#include <utils/cryptography.hpp>
@ -62,7 +61,7 @@ namespace bots
auto* bot_ent = game::SV_AddBot(bot_name);
if (bot_ent)
{
spawn_bot(bot_ent->s.entityNum);
spawn_bot(bot_ent->s.number);
}
else if (can_add()) // workaround since first bot won't ever spawn
{

View File

@ -1,10 +1,9 @@
#include <std_include.hpp>
#include "loader/component_loader.hpp"
#include "localized_strings.hpp"
#include "scheduler.hpp"
#include "command.hpp"
#include "game/game.hpp"
#include "localized_strings.hpp"
#include "scheduler.hpp"
#include "dvars.hpp"
#include <utils/hook.hpp>

View File

@ -1,15 +1,16 @@
#include <std_include.hpp>
#include "loader/component_loader.hpp"
#include "game/game.hpp"
#include "game/dvars.hpp"
#include "command.hpp"
#include "console.hpp"
#include "game_console.hpp"
#include "game/game.hpp"
#include <utils/hook.hpp>
#include <utils/string.hpp>
#include <utils/memory.hpp>
#include "utils/io.hpp"
#include <utils/io.hpp>
namespace command
{
@ -18,7 +19,7 @@ namespace command
utils::hook::detour client_command_hook;
std::unordered_map<std::string, std::function<void(params&)>> handlers;
std::unordered_map<std::string, std::function<void(int, params_sv&)>> handlers_sv;
std::unordered_map<std::string, std::function<void(game::mp::gentity_s*, params_sv&)>> handlers_sv;
void main_handler()
{
@ -31,17 +32,23 @@ namespace command
}
}
void client_command(const int client_num, void* a2)
void client_command(const int client_num)
{
if (game::mp::g_entities[client_num].client == nullptr)
{
// Client is not fully connected
return;
}
params_sv params = {};
const auto command = utils::string::to_lower(params[0]);
if (handlers_sv.find(command) != handlers_sv.end())
if (const auto got = handlers_sv.find(command); got != handlers_sv.end())
{
handlers_sv[command](client_num, params);
got->second(&game::mp::g_entities[client_num], params);
}
client_command_hook.invoke<void>(client_num, a2);
client_command_hook.invoke<void>(client_num);
}
// Shamelessly stolen from Quake3
@ -203,7 +210,7 @@ namespace command
});
}
void add_sv(const char* name, std::function<void(int, const params_sv&)> callback)
void add_sv(const char* name, std::function<void(game::mp::gentity_s*, const params_sv&)> callback)
{
// doing this so the sv command would show up in the console
add_raw(name, nullptr);
@ -214,6 +221,25 @@ namespace command
handlers_sv[command] = std::move(callback);
}
bool cheats_ok(const game::mp::gentity_s* ent)
{
if (!dvars::sv_cheats->current.enabled)
{
game::SV_GameSendServerCommand(ent->s.number, game::SV_CMD_RELIABLE,
"f \"Cheats are not enabled on this server\"");
return false;
}
if (ent->health < 1)
{
game::SV_GameSendServerCommand(ent->s.number, game::SV_CMD_RELIABLE,
"f \"You must be alive to use this command\"");
return false;
}
return true;
}
void execute(std::string command, const bool sync)
{
command += "\n";
@ -231,10 +257,10 @@ namespace command
void enum_assets(const game::XAssetType type, const std::function<void(game::XAssetHeader)>& callback, const bool includeOverride)
{
game::DB_EnumXAssets_Internal(type, static_cast<void(*)(game::XAssetHeader, void*)>([](game::XAssetHeader header, void* data)
{
const auto& cb = *static_cast<const std::function<void(game::XAssetHeader)>*>(data);
cb(header);
}), &callback, includeOverride);
{
const auto& cb = *static_cast<const std::function<void(game::XAssetHeader)>*>(data);
cb(header);
}), &callback, includeOverride);
}
class component final : public component_interface
@ -249,9 +275,9 @@ namespace command
else
{
utils::hook::call(0x1403CDF1C, &parse_commandline_stub);
add_commands_mp();
}
add_commands_generic();
}
@ -260,9 +286,9 @@ namespace command
{
add("quit", game::Com_Quit_f);
add("quit_hard", utils::nt::raise_hard_exception);
add("crash", []()
add("crash", []
{
*reinterpret_cast<int*>(1) = 0;
*reinterpret_cast<int*>(1) = 0x12345678;
});
add("consoleList", [](const params& params)
@ -545,136 +571,98 @@ namespace command
{
client_command_hook.create(0x1402E98F0, &client_command);
add_sv("god", [](const int client_num, const params_sv&)
add_sv("god", [](game::mp::gentity_s* ent, const params_sv&)
{
if (!game::Dvar_FindVar("sv_cheats")->current.enabled)
{
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
"f \"Cheats are not enabled on this server\"");
if (!cheats_ok(ent))
return;
}
game::mp::g_entities[client_num].flags ^= 1;
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
utils::string::va("f \"godmode %s\"",
game::mp::g_entities[client_num].flags & 1
? "^2on"
: "^1off"));
ent->flags ^= 1;
game::SV_GameSendServerCommand(ent->s.number, game::SV_CMD_RELIABLE,
utils::string::va("f \"godmode %s\"", ent->flags & 1 ? "^2on" : "^1off"));
});
add_sv("demigod", [](const int client_num, const params_sv&)
add_sv("demigod", [](game::mp::gentity_s* ent, const params_sv&)
{
if (!game::Dvar_FindVar("sv_cheats")->current.enabled)
{
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
"f \"Cheats are not enabled on this server\"");
if (!cheats_ok(ent))
return;
}
game::mp::g_entities[client_num].flags ^= 2;
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
utils::string::va("f \"demigod mode %s\"",
game::mp::g_entities[client_num].flags & 2
? "^2on"
: "^1off"));
ent->flags ^= 2;
game::SV_GameSendServerCommand(ent->s.number, game::SV_CMD_RELIABLE,
utils::string::va("f \"demigod mode %s\"", ent->flags & 2 ? "^2on" : "^1off"));
});
add_sv("notarget", [](const int client_num, const params_sv&)
add_sv("notarget", [](game::mp::gentity_s* ent, const params_sv&)
{
if (!game::Dvar_FindVar("sv_cheats")->current.enabled)
{
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
"f \"Cheats are not enabled on this server\"");
if (!cheats_ok(ent))
return;
}
game::mp::g_entities[client_num].flags ^= 4;
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
utils::string::va("f \"notarget %s\"",
game::mp::g_entities[client_num].flags & 4
? "^2on"
: "^1off"));
ent->flags ^= 4;
game::SV_GameSendServerCommand(ent->s.number, game::SV_CMD_RELIABLE,
utils::string::va("f \"notarget %s\"", ent->flags & 4 ? "^2on" : "^1off"));
});
add_sv("noclip", [](const int client_num, const params_sv&)
add_sv("noclip", [](game::mp::gentity_s* ent, const params_sv&)
{
if (!game::Dvar_FindVar("sv_cheats")->current.enabled)
{
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
"f \"Cheats are not enabled on this server\"");
if (!cheats_ok(ent))
return;
}
game::mp::g_entities[client_num].client->flags ^= 1;
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
utils::string::va("f \"noclip %s\"",
game::mp::g_entities[client_num].client->flags & 1
? "^2on"
: "^1off"));
ent->client->flags ^= 1;
game::SV_GameSendServerCommand(ent->s.number, game::SV_CMD_RELIABLE,
utils::string::va("f \"noclip %s\"", ent->client->flags & 1 ? "^2on" : "^1off"));
});
add_sv("ufo", [](const int client_num, const params_sv&)
add_sv("ufo", [](game::mp::gentity_s* ent, const params_sv&)
{
if (!game::Dvar_FindVar("sv_cheats")->current.enabled)
{
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
"f \"Cheats are not enabled on this server\"");
if (!cheats_ok(ent))
return;
}
game::mp::g_entities[client_num].client->flags ^= 2;
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
utils::string::va("f \"ufo %s\"",
game::mp::g_entities[client_num].client->flags & 2
? "^2on"
: "^1off"));
ent->client->flags ^= 2;
game::SV_GameSendServerCommand(ent->s.number, game::SV_CMD_RELIABLE,
utils::string::va("f \"ufo %s\"", ent->client->flags & 2 ? "^2on" : "^1off"));
});
add_sv("give", [](const int client_num, const params_sv& params)
add_sv("give", [](game::mp::gentity_s* ent, const params_sv& params)
{
if (!game::Dvar_FindVar("sv_cheats")->current.enabled)
{
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
"f \"Cheats are not enabled on this server\"");
if (!cheats_ok(ent))
return;
}
if (params.size() < 2)
{
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
"f \"You did not specify a weapon name\"");
game::SV_GameSendServerCommand(ent->s.number, game::SV_CMD_RELIABLE,
"f \"You did not specify a weapon name\"");
return;
}
auto ps = game::SV_GetPlayerstateForClientNum(client_num);
auto ps = game::SV_GetPlayerstateForClientNum(ent->s.number);
const auto wp = game::G_GetWeaponForName(params.get(1));
if (wp)
{
if (game::G_GivePlayerWeapon(ps, wp, 0, 0, 0, 0, 0, 0))
{
game::G_InitializeAmmo(ps, wp, 0);
game::G_SelectWeapon(client_num, wp);
game::G_SelectWeapon(ent->s.number, wp);
}
}
});
add_sv("take", [](const int client_num, const params_sv& params)
add_sv("take", [](game::mp::gentity_s* ent, const params_sv& params)
{
if (!game::Dvar_FindVar("sv_cheats")->current.enabled)
{
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
"f \"Cheats are not enabled on this server\"");
if (!cheats_ok(ent))
return;
}
if (params.size() < 2)
{
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
game::SV_GameSendServerCommand(ent->s.number, game::SV_CMD_RELIABLE,
"f \"You did not specify a weapon name\"");
return;
}
auto ps = game::SV_GetPlayerstateForClientNum(client_num);
auto ps = game::SV_GetPlayerstateForClientNum(ent->s.number);
const auto wp = game::G_GetWeaponForName(params.get(1));
if (wp)
{

View File

@ -44,7 +44,7 @@ namespace command
void add(const char* name, const std::function<void(const params&)>& callback);
void add(const char* name, const std::function<void()>& callback);
void add_sv(const char* name, std::function<void(int, const params_sv&)> callback);
void add_sv(const char* name, std::function<void(game::mp::gentity_s*, const params_sv&)> callback);
void execute(std::string command, bool sync = false);
}

View File

@ -2,6 +2,7 @@
#include "loader/component_loader.hpp"
#include "game/game.hpp"
#include "game/dvars.hpp"
#include "console.hpp"
#include "scheduler.hpp"
@ -21,7 +22,7 @@ namespace dvar_cheats
value->enabled = dvar->current.enabled;
}
// if sv_cheats was enabled and it changes to disabled, we need to reset all cheat dvars
// if sv_cheats was enabled and it changes to disabled, we need to reset all cheat dvars
else if (dvar->current.enabled && !value->enabled)
{
for (auto i = 0; i < *game::dvarCount; ++i)
@ -63,8 +64,7 @@ namespace dvar_cheats
return false;
}
const auto sv_cheats = game::Dvar_FindVar("sv_cheats");
if ((dvar->flags & game::DvarFlags::DVAR_FLAG_CHEAT) && (sv_cheats && !sv_cheats->current.enabled))
if ((dvar->flags & game::DvarFlags::DVAR_FLAG_CHEAT) && (!dvars::sv_cheats->current.enabled))
{
console::error("%s is cheat protected\n", dvar->name);
return false;
@ -179,8 +179,14 @@ namespace dvar_cheats
scheduler::once([]()
{
game::Dvar_RegisterBool("sv_cheats", false, game::DvarFlags::DVAR_FLAG_REPLICATED,
"Allow cheat commands and dvars on this server");
#ifdef _DEBUG
constexpr auto value = true;
#else
constexpr auto value = false;
#endif
dvars::sv_cheats = game::Dvar_RegisterBool("sv_cheats", value, game::DvarFlags::DVAR_FLAG_REPLICATED,
"Allow cheat commands and dvars on this server");
}, scheduler::pipeline::main);
}
};

View File

@ -1,12 +1,12 @@
#include <std_include.hpp>
#include "loader/component_loader.hpp"
#include "game_console.hpp"
#include "game/game.hpp"
#include "game/dvars.hpp"
#include "command.hpp"
#include "console.hpp"
#include "scheduler.hpp"
#include "game/game.hpp"
#include "game/dvars.hpp"
#include "game_console.hpp"
#include <utils/string.hpp>
#include <utils/hook.hpp>

View File

@ -34,7 +34,7 @@ namespace logfile
return {};
}
const auto player = scripting::call("getEntByNum", {ent->s.entityNum});
const auto player = scripting::call("getEntByNum", {ent->s.number});
return scripting::lua::convert(state, player);
}
@ -162,7 +162,7 @@ namespace logfile
scheduler::once([cmd, message, self]()
{
const scripting::entity level{*game::levelEntityId};
const auto player = scripting::call("getEntByNum", {self->s.entityNum}).as<scripting::entity>();
const auto player = scripting::call("getEntByNum", {self->s.number}).as<scripting::entity>();
scripting::notify(level, cmd, {player, message});
scripting::notify(player, cmd, {message});

View File

@ -1,10 +1,12 @@
#include <std_include.hpp>
#include "loader/component_loader.hpp"
#include "game/game.hpp"
#include "command.hpp"
#include "scheduler.hpp"
#include <utils/hook.hpp>
#include <utils/string.hpp>
#include "game/game.hpp"
namespace map_rotation
{

View File

@ -1,5 +1,6 @@
#include <std_include.hpp>
#include "loader/component_loader.hpp"
#include "game/game.hpp"
#include "command.hpp"
#include "network.hpp"

View File

@ -1,10 +1,11 @@
#include <std_include.hpp>
#include "loader/component_loader.hpp"
#include "game/game.hpp"
#include "game/dvars.hpp"
#include "command.hpp"
#include "console.hpp"
#include "network.hpp"
#include "game/game.hpp"
#include "game/dvars.hpp"
#include "scheduler.hpp"
#include "filesystem.hpp"
#include "fastfiles.hpp"
@ -183,7 +184,7 @@ namespace patches
{
command::params_sv params{};
const auto menu_id = atoi(params.get(1));
const auto client = &game::mp::svs_clients[ent->s.entityNum];
const auto client = &game::mp::svs_clients[ent->s.number];
// 22 => "end_game"
if (menu_id == 22 && client->header.remoteAddress.type != game::NA_LOOPBACK)

View File

@ -34,6 +34,8 @@ namespace dvars
game::dvar_t* cg_legacyCrashHandling = nullptr;
game::dvar_t* sv_cheats = nullptr;
std::string dvar_get_vector_domain(const int components, const game::dvar_limits& domain)
{
if (domain.vector.min == -FLT_MAX)

View File

@ -33,6 +33,8 @@ namespace dvars
extern game::dvar_t* cg_legacyCrashHandling;
extern game::dvar_t* sv_cheats;
std::string dvar_get_vector_domain(const int components, const game::dvar_limits& domain);
std::string dvar_get_domain(const game::dvar_type type, const game::dvar_limits& domain);
}

View File

@ -1407,17 +1407,25 @@ namespace game
struct EntityState
{
char entityNum;
char number;
}; // size = ?
struct EntHandle
{
unsigned __int16 number;
unsigned __int16 infoIndex;
};
struct gentity_s
{
EntityState s;
char __pad0[343];
gclient_s* client;
gclient_s* client; // 0x158
char __pad1[80];
int flags;
char __pad2[300];
int flags; // 0x1B0
char __pad2[0x1c];
int health; // 0x1D0
char __pad3[0x10C];
};
static_assert(sizeof(gentity_s) == 0x2E0);

View File

@ -267,6 +267,8 @@ namespace game
WEAK symbol<GfxDrawMethod_s> gfxDrawMethod{0x14CDFAFE8, 0x14D80FD98};
WEAK symbol<unsigned int> tls_index{0x14f65dAF0, 0x150085C44};
namespace mp
{
WEAK symbol<gentity_s> g_entities{0, 0x144758C70};