assets(weapons): cache weapons from code (Code quaK/H1-Mod probably took from Pluto xD)
Co-authored-by: H1-Mod Team <info@auroramod.dev> Co-authored-by: HighTechRedNeck <HTRNModding@outlook.com>
This commit is contained in:
parent
199206ee5a
commit
3d77a21f3d
61
src/client/component/assets/weapons.cpp
Normal file
61
src/client/component/assets/weapons.cpp
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#include <std_include.hpp>
|
||||||
|
#include "loader/component_loader.hpp"
|
||||||
|
#include "game/game.hpp"
|
||||||
|
|
||||||
|
#include "component/console.hpp"
|
||||||
|
|
||||||
|
#include <utils/hook.hpp>
|
||||||
|
|
||||||
|
namespace weapons
|
||||||
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
void g_setup_level_weapon_def_stub()
|
||||||
|
{
|
||||||
|
game::G_SetupLevelWeaponDef();
|
||||||
|
|
||||||
|
// The count on most maps is well below 200
|
||||||
|
std::array<game::WeaponCompleteDef*, 256> weapons{};
|
||||||
|
const auto count = game::DB_GetAllXAssetOfType_FastFile(game::ASSET_TYPE_WEAPON, (void**)weapons.data(), static_cast<int>(weapons.max_size()));
|
||||||
|
|
||||||
|
std::sort(weapons.begin(), weapons.begin() + count, [](game::WeaponCompleteDef* weapon1, game::WeaponCompleteDef* weapon2)
|
||||||
|
{
|
||||||
|
assert(weapon1->szInternalName);
|
||||||
|
assert(weapon2->szInternalName);
|
||||||
|
|
||||||
|
return std::strcmp(weapon1->szInternalName, weapon2->szInternalName) < 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
console::info("Found %i weapons to precache\n", count);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (auto i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
#ifdef _DEBUG
|
||||||
|
console::info("Precaching weapon \"%s\"\n", weapons[i]->szInternalName);
|
||||||
|
#endif
|
||||||
|
(void)game::G_GetWeaponForName(weapons[i]->szInternalName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class component final : public component_interface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void post_unpack() override
|
||||||
|
{
|
||||||
|
if (game::environment::is_sp()) return;
|
||||||
|
|
||||||
|
// Kill Scr_PrecacheItem (We are going to do this from code)
|
||||||
|
utils::hook::nop(0x1403BDB10, 4);
|
||||||
|
utils::hook::set<std::uint8_t>(0x1403BDB10, 0xC3);
|
||||||
|
|
||||||
|
// Load weapons from the DB
|
||||||
|
utils::hook::call(0x14039F382, g_setup_level_weapon_def_stub);
|
||||||
|
utils::hook::call(0x1403AE31A, g_setup_level_weapon_def_stub);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_COMPONENT(weapons::component)
|
@ -2,6 +2,7 @@
|
|||||||
#include "loader/component_loader.hpp"
|
#include "loader/component_loader.hpp"
|
||||||
#include "game/game.hpp"
|
#include "game/game.hpp"
|
||||||
#include "game/dvars.hpp"
|
#include "game/dvars.hpp"
|
||||||
|
#include "game/engine/sv_game.hpp"
|
||||||
|
|
||||||
#include "command.hpp"
|
#include "command.hpp"
|
||||||
#include "console.hpp"
|
#include "console.hpp"
|
||||||
@ -459,10 +460,7 @@ namespace command
|
|||||||
}
|
}
|
||||||
|
|
||||||
game::sp::g_entities[0].flags ^= game::FL_GODMODE;
|
game::sp::g_entities[0].flags ^= game::FL_GODMODE;
|
||||||
game::CG_GameMessage(0, utils::string::va("godmode %s",
|
game::CG_GameMessage(0, utils::string::va("godmode %s", game::sp::g_entities[0].flags & game::FL_GODMODE ? "^2on" : "^1off"));
|
||||||
game::sp::g_entities[0].flags & game::FL_GODMODE
|
|
||||||
? "^2on"
|
|
||||||
: "^1off"));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
add("notarget", []
|
add("notarget", []
|
||||||
@ -473,10 +471,7 @@ namespace command
|
|||||||
}
|
}
|
||||||
|
|
||||||
game::sp::g_entities[0].flags ^= game::FL_NOTARGET;
|
game::sp::g_entities[0].flags ^= game::FL_NOTARGET;
|
||||||
game::CG_GameMessage(0, utils::string::va("notarget %s",
|
game::CG_GameMessage(0, utils::string::va("notarget %s", game::sp::g_entities[0].flags & game::FL_NOTARGET ? "^2on" : "^1off"));
|
||||||
game::sp::g_entities[0].flags & game::FL_NOTARGET
|
|
||||||
? "^2on"
|
|
||||||
: "^1off"));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
add("noclip", []
|
add("noclip", []
|
||||||
@ -487,10 +482,7 @@ namespace command
|
|||||||
}
|
}
|
||||||
|
|
||||||
game::sp::g_entities[0].client->flags ^= 1;
|
game::sp::g_entities[0].client->flags ^= 1;
|
||||||
game::CG_GameMessage(0, utils::string::va("noclip %s",
|
game::CG_GameMessage(0, utils::string::va("noclip %s", game::sp::g_entities[0].client->flags & 1 ? "^2on" : "^1off"));
|
||||||
game::sp::g_entities[0].client->flags & 1
|
|
||||||
? "^2on"
|
|
||||||
: "^1off"));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
add("ufo", []
|
add("ufo", []
|
||||||
@ -501,10 +493,7 @@ namespace command
|
|||||||
}
|
}
|
||||||
|
|
||||||
game::sp::g_entities[0].client->flags ^= 2;
|
game::sp::g_entities[0].client->flags ^= 2;
|
||||||
game::CG_GameMessage(0, utils::string::va("ufo %s",
|
game::CG_GameMessage(0, utils::string::va("ufo %s", game::sp::g_entities[0].client->flags & 2 ? "^2on" : "^1off"));
|
||||||
game::sp::g_entities[0].client->flags & 2
|
|
||||||
? "^2on"
|
|
||||||
: "^1off"));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
add("give", [](const params& params)
|
add("give", [](const params& params)
|
||||||
@ -556,78 +545,65 @@ namespace command
|
|||||||
{
|
{
|
||||||
if (!dvars::sv_cheats->current.enabled)
|
if (!dvars::sv_cheats->current.enabled)
|
||||||
{
|
{
|
||||||
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, "f \"Cheats are not enabled on this server\"");
|
game::engine::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, "f \"Cheats are not enabled on this server\"");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
game::mp::g_entities[client_num].flags ^= game::FL_GODMODE;
|
game::mp::g_entities[client_num].flags ^= game::FL_GODMODE;
|
||||||
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
|
game::engine::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, utils::string::va("f \"godmode %s\"", game::mp::g_entities[client_num].flags & game::FL_GODMODE ? "^2on" : "^1off"));
|
||||||
utils::string::va("f \"godmode %s\"",
|
|
||||||
game::mp::g_entities[client_num].flags & game::FL_GODMODE
|
|
||||||
? "^2on"
|
|
||||||
: "^1off"));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
add_sv("notarget", [](const int client_num, const params_sv&)
|
add_sv("notarget", [](const int client_num, const params_sv&)
|
||||||
{
|
{
|
||||||
if (!dvars::sv_cheats->current.enabled)
|
if (!dvars::sv_cheats->current.enabled)
|
||||||
{
|
{
|
||||||
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, "f \"Cheats are not enabled on this server\"");
|
game::engine::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, "f \"Cheats are not enabled on this server\"");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
game::mp::g_entities[client_num].flags ^= game::FL_NOTARGET;
|
game::mp::g_entities[client_num].flags ^= game::FL_NOTARGET;
|
||||||
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
|
game::engine::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
|
||||||
utils::string::va("f \"notarget %s\"",
|
utils::string::va("f \"notarget %s\"", game::mp::g_entities[client_num].flags & game::FL_NOTARGET ? "^2on" : "^1off"));
|
||||||
game::mp::g_entities[client_num].flags & game::FL_NOTARGET
|
|
||||||
? "^2on"
|
|
||||||
: "^1off"));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
add_sv("noclip", [](const int client_num, const params_sv&)
|
add_sv("noclip", [](const int client_num, const params_sv&)
|
||||||
{
|
{
|
||||||
if (!dvars::sv_cheats->current.enabled)
|
if (!dvars::sv_cheats->current.enabled)
|
||||||
{
|
{
|
||||||
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, "f \"Cheats are not enabled on this server\"");
|
game::engine::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, "f \"Cheats are not enabled on this server\"");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
game::mp::g_entities[client_num].client->flags ^= 1;
|
game::mp::g_entities[client_num].client->flags ^= 1;
|
||||||
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
|
game::engine::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
|
||||||
utils::string::va("f \"noclip %s\"",
|
utils::string::va("f \"noclip %s\"", game::mp::g_entities[client_num].client->flags & 1 ? "^2on" : "^1off"));
|
||||||
game::mp::g_entities[client_num].client->flags & 1
|
|
||||||
? "^2on"
|
|
||||||
: "^1off"));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
add_sv("ufo", [](const int client_num, const params_sv&)
|
add_sv("ufo", [](const int client_num, const params_sv&)
|
||||||
{
|
{
|
||||||
if (!dvars::sv_cheats->current.enabled)
|
if (!dvars::sv_cheats->current.enabled)
|
||||||
{
|
{
|
||||||
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, "f \"Cheats are not enabled on this server\"");
|
game::engine::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, "f \"Cheats are not enabled on this server\"");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
game::mp::g_entities[client_num].client->flags ^= 2;
|
game::mp::g_entities[client_num].client->flags ^= 2;
|
||||||
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
|
game::engine::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
|
||||||
utils::string::va("f \"ufo %s\"",
|
utils::string::va("f \"ufo %s\"", game::mp::g_entities[client_num].client->flags & 2 ? "^2on" : "^1off"));
|
||||||
game::mp::g_entities[client_num].client->flags & 2
|
|
||||||
? "^2on"
|
|
||||||
: "^1off"));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
add_sv("setviewpos", [](const int client_num, const params_sv& params)
|
add_sv("setviewpos", [](const int client_num, const params_sv& params)
|
||||||
{
|
{
|
||||||
if (!dvars::sv_cheats->current.enabled)
|
if (!dvars::sv_cheats->current.enabled)
|
||||||
{
|
{
|
||||||
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, "f \"Cheats are not enabled on this server\"");
|
game::engine::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, "f \"Cheats are not enabled on this server\"");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.size() < 4)
|
if (params.size() < 4)
|
||||||
{
|
{
|
||||||
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
|
game::engine::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
|
||||||
"f \"You did not specify the correct number of coordinates\"");
|
"f \"You did not specify the correct number of coordinates\"");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -640,14 +616,14 @@ namespace command
|
|||||||
{
|
{
|
||||||
if (!dvars::sv_cheats->current.enabled)
|
if (!dvars::sv_cheats->current.enabled)
|
||||||
{
|
{
|
||||||
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, "f \"Cheats are not enabled on this server\"");
|
game::engine::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, "f \"Cheats are not enabled on this server\"");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.size() < 4)
|
if (params.size() < 4)
|
||||||
{
|
{
|
||||||
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
|
game::engine::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
|
||||||
"f \"You did not specify the correct number of coordinates\"");
|
"f \"You did not specify the correct number of coordinates\"");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -660,13 +636,13 @@ namespace command
|
|||||||
{
|
{
|
||||||
if (!dvars::sv_cheats->current.enabled)
|
if (!dvars::sv_cheats->current.enabled)
|
||||||
{
|
{
|
||||||
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, "f \"Cheats are not enabled on this server\"");
|
game::engine::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, "f \"Cheats are not enabled on this server\"");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.size() < 2)
|
if (params.size() < 2)
|
||||||
{
|
{
|
||||||
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, "f \"You did not specify a weapon name\"");
|
game::engine::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, "f \"You did not specify a weapon name\"");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -683,13 +659,13 @@ namespace command
|
|||||||
{
|
{
|
||||||
if (!dvars::sv_cheats->current.enabled)
|
if (!dvars::sv_cheats->current.enabled)
|
||||||
{
|
{
|
||||||
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, "f \"Cheats are not enabled on this server\"");
|
game::engine::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, "f \"Cheats are not enabled on this server\"");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.size() < 2)
|
if (params.size() < 2)
|
||||||
{
|
{
|
||||||
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, "f \"You did not specify a weapon name\"");
|
game::engine::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, "f \"You did not specify a weapon name\"");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#include <std_include.hpp>
|
#include <std_include.hpp>
|
||||||
#include "loader/component_loader.hpp"
|
#include "loader/component_loader.hpp"
|
||||||
|
|
||||||
#include "game/game.hpp"
|
#include "game/game.hpp"
|
||||||
#include "game/dvars.hpp"
|
#include "game/dvars.hpp"
|
||||||
|
#include "game/engine/sv_game.hpp"
|
||||||
|
|
||||||
#include "console.hpp"
|
#include "console.hpp"
|
||||||
|
|
||||||
@ -136,7 +136,7 @@ namespace dvar_cheats
|
|||||||
const auto* dvar = game::Scr_GetString(0); // grab the original dvar again since it's never stored on stack
|
const auto* dvar = game::Scr_GetString(0); // grab the original dvar again since it's never stored on stack
|
||||||
const auto* command = utils::string::va("q %s \"%s\"", dvar, value);
|
const auto* command = utils::string::va("q %s \"%s\"", dvar, value);
|
||||||
|
|
||||||
game::SV_GameSendServerCommand(entity_num, game::SV_CMD_RELIABLE, command);
|
game::engine::SV_GameSendServerCommand(entity_num, game::SV_CMD_RELIABLE, command);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto player_cmd_set_client_dvar = utils::hook::assemble([](utils::hook::assembler& a)
|
const auto player_cmd_set_client_dvar = utils::hook::assemble([](utils::hook::assembler& a)
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include "loader/component_loader.hpp"
|
#include "loader/component_loader.hpp"
|
||||||
#include "game/game.hpp"
|
#include "game/game.hpp"
|
||||||
#include "game/dvars.hpp"
|
#include "game/dvars.hpp"
|
||||||
|
#include "game/engine/sv_game.hpp"
|
||||||
|
|
||||||
#include "command.hpp"
|
#include "command.hpp"
|
||||||
#include "console.hpp"
|
#include "console.hpp"
|
||||||
@ -380,7 +381,7 @@ namespace party
|
|||||||
const auto message = params.join(2);
|
const auto message = params.join(2);
|
||||||
const auto* const name = game::Dvar_FindVar("sv_sayName")->current.string;
|
const auto* const name = game::Dvar_FindVar("sv_sayName")->current.string;
|
||||||
|
|
||||||
game::SV_GameSendServerCommand(client_num, game::SV_CMD_CAN_IGNORE, utils::string::va("%c \"%s: %s\"", 84, name, message.data()));
|
game::engine::SV_GameSendServerCommand(client_num, game::SV_CMD_CAN_IGNORE, utils::string::va("%c \"%s: %s\"", 84, name, message.data()));
|
||||||
console::info("%s -> %i: %s\n", name, client_num, message.data());
|
console::info("%s -> %i: %s\n", name, client_num, message.data());
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -394,7 +395,7 @@ namespace party
|
|||||||
const auto client_num = atoi(params.get(1));
|
const auto client_num = atoi(params.get(1));
|
||||||
const auto message = params.join(2);
|
const auto message = params.join(2);
|
||||||
|
|
||||||
game::SV_GameSendServerCommand(client_num, game::SV_CMD_CAN_IGNORE, utils::string::va("%c \"%s\"", 84, message.data()));
|
game::engine::SV_GameSendServerCommand(client_num, game::SV_CMD_CAN_IGNORE, utils::string::va("%c \"%s\"", 84, message.data()));
|
||||||
console::info("%i: %s\n", client_num, message.data());
|
console::info("%i: %s\n", client_num, message.data());
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -408,7 +409,7 @@ namespace party
|
|||||||
const auto message = params.join(1);
|
const auto message = params.join(1);
|
||||||
const auto* const name = game::Dvar_FindVar("sv_sayName")->current.string;
|
const auto* const name = game::Dvar_FindVar("sv_sayName")->current.string;
|
||||||
|
|
||||||
game::SV_GameSendServerCommand(-1, game::SV_CMD_CAN_IGNORE, utils::string::va("%c \"%s: %s\"", 84, name, message.data()));
|
game::engine::SV_GameSendServerCommand(-1, game::SV_CMD_CAN_IGNORE, utils::string::va("%c \"%s: %s\"", 84, name, message.data()));
|
||||||
console::info("%s: %s\n", name, message.data());
|
console::info("%s: %s\n", name, message.data());
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -421,7 +422,7 @@ namespace party
|
|||||||
|
|
||||||
const auto message = params.join(1);
|
const auto message = params.join(1);
|
||||||
|
|
||||||
game::SV_GameSendServerCommand(-1, game::SV_CMD_CAN_IGNORE, utils::string::va("%c \"%s\"", 84, message.data()));
|
game::engine::SV_GameSendServerCommand(-1, game::SV_CMD_CAN_IGNORE, utils::string::va("%c \"%s\"", 84, message.data()));
|
||||||
console::info("%s\n", message.data());
|
console::info("%s\n", message.data());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include "loader/component_loader.hpp"
|
#include "loader/component_loader.hpp"
|
||||||
#include "game/game.hpp"
|
#include "game/game.hpp"
|
||||||
#include "game/dvars.hpp"
|
#include "game/dvars.hpp"
|
||||||
|
#include "game/engine/sv_game.hpp"
|
||||||
|
|
||||||
#include "command.hpp"
|
#include "command.hpp"
|
||||||
#include "console.hpp"
|
#include "console.hpp"
|
||||||
@ -290,6 +291,10 @@ namespace patches
|
|||||||
|
|
||||||
static void patch_mp()
|
static void patch_mp()
|
||||||
{
|
{
|
||||||
|
// Bypass Arxan function
|
||||||
|
utils::hook::nop(0x1404758C0, 16);
|
||||||
|
utils::hook::jump(0x1404758C0, game::engine::SV_GameSendServerCommand, true);
|
||||||
|
|
||||||
// Register dvars
|
// Register dvars
|
||||||
com_register_dvars_hook.create(0x140413A90, &com_register_dvars_stub);
|
com_register_dvars_hook.create(0x140413A90, &com_register_dvars_stub);
|
||||||
|
|
||||||
|
181
src/client/game/engine/sv_game.cpp
Normal file
181
src/client/game/engine/sv_game.cpp
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
#include <std_include.hpp>
|
||||||
|
#include <game/game.hpp>
|
||||||
|
|
||||||
|
#include "sv_game.hpp"
|
||||||
|
|
||||||
|
#include <component/console.hpp>
|
||||||
|
|
||||||
|
#include <utils/string.hpp>
|
||||||
|
|
||||||
|
namespace game::engine
|
||||||
|
{
|
||||||
|
char* SV_ExpandNewlines(char* in)
|
||||||
|
{
|
||||||
|
static char string[1024];
|
||||||
|
|
||||||
|
unsigned int l = 0;
|
||||||
|
while (*in && l < sizeof(string) - 3)
|
||||||
|
{
|
||||||
|
if (*in == '\n')
|
||||||
|
{
|
||||||
|
string[l++] = '\\';
|
||||||
|
string[l++] = 'n';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (*in != '\x14' && *in != '\x15')
|
||||||
|
{
|
||||||
|
string[l++] = *in;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
++in;
|
||||||
|
}
|
||||||
|
|
||||||
|
string[l] = '\0';
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SV_CullIgnorableServerCommands(mp::client_t* client)
|
||||||
|
{
|
||||||
|
int to = client->reliableSent + 1;
|
||||||
|
for (int from = to; from <= client->reliableSequence; ++from)
|
||||||
|
{
|
||||||
|
int from_index = from & 0x7F;
|
||||||
|
assert(client->netBuf.reliableCommandInfo[from_index].time >= 0);
|
||||||
|
if (client->netBuf.reliableCommandInfo[from_index].type)
|
||||||
|
{
|
||||||
|
int to_index = to & 0x7F;
|
||||||
|
if (to_index != from_index)
|
||||||
|
{
|
||||||
|
client->netBuf.reliableCommandInfo[to_index] = client->netBuf.reliableCommandInfo[from_index];
|
||||||
|
}
|
||||||
|
|
||||||
|
++to;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
client->reliableSequence = to - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SV_DelayDropClient(mp::client_t* drop, const char* reason)
|
||||||
|
{
|
||||||
|
assert(drop);
|
||||||
|
assert(reason);
|
||||||
|
assert(drop->header.state != CS_FREE);
|
||||||
|
if (drop->header.state == CS_ZOMBIE)
|
||||||
|
{
|
||||||
|
#ifdef _DEBUG
|
||||||
|
console::info("(drop->dropReason) = %s", drop->dropReason);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if (!drop->dropReason)
|
||||||
|
{
|
||||||
|
drop->dropReason = reason;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SV_AddServerCommand(mp::client_t* client, svscmd_type type, const char* cmd)
|
||||||
|
{
|
||||||
|
static_assert(offsetof(mp::client_t, netBuf.reliableCommandInfo[0].cmd) == 0xC44);
|
||||||
|
|
||||||
|
if (client->testClient == TC_BOT)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (client->reliableSequence - client->reliableAcknowledge < 64 && client->header.state == CS_ACTIVE || (SV_CullIgnorableServerCommands(client), type))
|
||||||
|
{
|
||||||
|
int len = static_cast<int>(std::strlen(cmd)) + 1;
|
||||||
|
int to = SV_CanReplaceServerCommand(client, reinterpret_cast<const unsigned char*>(cmd), len);
|
||||||
|
if (to < 0)
|
||||||
|
{
|
||||||
|
++client->reliableSequence;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int from = to + 1;
|
||||||
|
while (from <= client->reliableSequence)
|
||||||
|
{
|
||||||
|
client->netBuf.reliableCommandInfo[to & 0x7F] = client->netBuf.reliableCommandInfo[from & 0x7F];
|
||||||
|
++from;
|
||||||
|
++to;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (client->reliableSequence - client->reliableAcknowledge == 129)
|
||||||
|
{
|
||||||
|
#ifdef _DEBUG
|
||||||
|
console::info("===== pending server commands =====\n");
|
||||||
|
int i = 0;
|
||||||
|
for (i = client->reliableAcknowledge + 1; i <= client->reliableSequence; ++i)
|
||||||
|
{
|
||||||
|
console::info("cmd %5d: %8d: %s\n", i, client->netBuf.reliableCommandInfo[i & 0x7F].time, client->netBuf.reliableCommandInfo[i & 0x7F].cmd);
|
||||||
|
}
|
||||||
|
console::info("cmd %5d: %8d: %s\n", i, *game::mp::serverTime, cmd);
|
||||||
|
#endif
|
||||||
|
NET_OutOfBandPrint(NS_SERVER, &client->header.netchan.remoteAddress, "disconnect");
|
||||||
|
SV_DelayDropClient(client, "EXE_SERVERCOMMANDOVERFLOW");
|
||||||
|
type = SV_CMD_RELIABLE;
|
||||||
|
cmd = utils::string::va("%c \"EXE_SERVERCOMMANDOVERFLOW\"", 'r');
|
||||||
|
}
|
||||||
|
|
||||||
|
int index = client->reliableSequence & 0x7F;
|
||||||
|
MSG_WriteReliableCommandToBuffer(cmd, client->netBuf.reliableCommandInfo[index].cmd, sizeof(client->netBuf.reliableCommandInfo[index].cmd));
|
||||||
|
client->netBuf.reliableCommandInfo[index].time = *game::mp::serverTime;
|
||||||
|
client->netBuf.reliableCommandInfo[index].type = type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SV_SendServerCommand(mp::client_t* cl, svscmd_type type, const char* fmt, ...)
|
||||||
|
{
|
||||||
|
mp::client_t* client;
|
||||||
|
int j, len;
|
||||||
|
va_list va;
|
||||||
|
|
||||||
|
const auto server_command_buf_large = std::make_unique<char[]>(0x20000);
|
||||||
|
|
||||||
|
va_start(va, fmt);
|
||||||
|
len = vsnprintf_s(server_command_buf_large.get(), 0x20000, _TRUNCATE, fmt, va);
|
||||||
|
va_end(va);
|
||||||
|
|
||||||
|
assert(len >= 0);
|
||||||
|
|
||||||
|
if (cl)
|
||||||
|
{
|
||||||
|
SV_AddServerCommand(cl, type, server_command_buf_large.get());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (environment::is_dedi() && !std::strncmp(server_command_buf_large.get(), "print", 5))
|
||||||
|
{
|
||||||
|
console::info("broadcast: %s\n", SV_ExpandNewlines(server_command_buf_large.get()));
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto* sv_maxclients = Dvar_FindVar("sv_maxclients");
|
||||||
|
for (j = 0, client = mp::svs_clients; j < sv_maxclients->current.integer; j++, client++)
|
||||||
|
{
|
||||||
|
if (client->header.state < CS_CLIENTLOADING)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
SV_AddServerCommand(client, type, server_command_buf_large.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SV_GameSendServerCommand(int clientNum, svscmd_type type, const char* text)
|
||||||
|
{
|
||||||
|
[[maybe_unused]] const auto* sv_maxclients = Dvar_FindVar("sv_maxclients");
|
||||||
|
|
||||||
|
if (clientNum == -1)
|
||||||
|
{
|
||||||
|
SV_SendServerCommand(nullptr, type, "%s", text);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(sv_maxclients->current.integer >= 1 && sv_maxclients->current.integer <= 18);
|
||||||
|
assert(static_cast<unsigned>(clientNum) < sv_maxclients->current.unsignedInt);
|
||||||
|
SV_SendServerCommand(&mp::svs_clients[clientNum], type, "%s", text);
|
||||||
|
}
|
||||||
|
}
|
6
src/client/game/engine/sv_game.hpp
Normal file
6
src/client/game/engine/sv_game.hpp
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace game::engine
|
||||||
|
{
|
||||||
|
void SV_GameSendServerCommand(int clientNum, svscmd_type type, const char* text);
|
||||||
|
}
|
@ -1963,6 +1963,12 @@ namespace game
|
|||||||
const char* buffer;
|
const char* buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct WeaponCompleteDef
|
||||||
|
{
|
||||||
|
const char* szInternalName;
|
||||||
|
WeaponDef* weapDef;
|
||||||
|
}; // Incomplete
|
||||||
|
|
||||||
union XAssetHeader
|
union XAssetHeader
|
||||||
{
|
{
|
||||||
void* data;
|
void* data;
|
||||||
@ -1998,9 +2004,9 @@ namespace game
|
|||||||
menuDef_t *menu;
|
menuDef_t *menu;
|
||||||
AnimationClass *animClass;
|
AnimationClass *animClass;
|
||||||
LocalizeEntry *localize;
|
LocalizeEntry *localize;
|
||||||
WeaponAttachment *attachment;
|
WeaponAttachment *attachment;*/
|
||||||
WeaponCompleteDef *weapon;
|
WeaponCompleteDef* weapon;
|
||||||
SndDriverGlobals *sndDriverGlobals;
|
/*SndDriverGlobals *sndDriverGlobals;
|
||||||
FxEffectDef *fx;
|
FxEffectDef *fx;
|
||||||
FxImpactTable *impactFx;
|
FxImpactTable *impactFx;
|
||||||
SurfaceFxTable *surfaceFx;*/
|
SurfaceFxTable *surfaceFx;*/
|
||||||
@ -2434,6 +2440,24 @@ namespace game
|
|||||||
int isInKillcam;
|
int isInKillcam;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct svscmd_info_t
|
||||||
|
{
|
||||||
|
int time;
|
||||||
|
int type;
|
||||||
|
char cmd[1024];
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(svscmd_info_t) == 0x408);
|
||||||
|
|
||||||
|
struct client_net_buffers_t
|
||||||
|
{
|
||||||
|
svscmd_info_t reliableCommandInfo[128];
|
||||||
|
char netchanOutgoingBuffer[131072];
|
||||||
|
char netchanIncomingBuffer[2048];
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(client_net_buffers_t) == 0x40C00);
|
||||||
|
|
||||||
struct client_t
|
struct client_t
|
||||||
{
|
{
|
||||||
clientHeader_t header;
|
clientHeader_t header;
|
||||||
@ -2443,7 +2467,17 @@ namespace game
|
|||||||
int reliableAcknowledge;
|
int reliableAcknowledge;
|
||||||
int reliableSent;
|
int reliableSent;
|
||||||
int messageAcknowledge;
|
int messageAcknowledge;
|
||||||
char _0xC30[0x41238];
|
int largeCommandSequence;
|
||||||
|
int gamestateMessageNum;
|
||||||
|
int challenge;
|
||||||
|
client_net_buffers_t netBuf;
|
||||||
|
int cumulThinkTime;
|
||||||
|
int beginCmdIndex;
|
||||||
|
int currCmdIndex;
|
||||||
|
usercmd_s lastUsercmd;
|
||||||
|
usercmd_s cmds[8];
|
||||||
|
int lastClientCommand;
|
||||||
|
char lastClientCommandString[1024];
|
||||||
gentity_s* gentity;
|
gentity_s* gentity;
|
||||||
char name[16];
|
char name[16];
|
||||||
int lastPacketTime;
|
int lastPacketTime;
|
||||||
|
@ -19,6 +19,7 @@ namespace game
|
|||||||
WEAK symbol<void(void*, void*)> AimAssist_AddToTargetList{0, 0x140139D80};
|
WEAK symbol<void(void*, void*)> AimAssist_AddToTargetList{0, 0x140139D80};
|
||||||
|
|
||||||
WEAK symbol<void(unsigned int weapon, bool isAlternate, char* output, unsigned int maxStringLen)> BG_GetWeaponNameComplete{0, 0x140239370};
|
WEAK symbol<void(unsigned int weapon, bool isAlternate, char* output, unsigned int maxStringLen)> BG_GetWeaponNameComplete{0, 0x140239370};
|
||||||
|
WEAK symbol<void()> BG_ClearWeaponDef{0x0, 0x140238D20};
|
||||||
|
|
||||||
WEAK symbol<void()> Com_Frame_Try_Block_Function{0x1403BC980, 0x1404131A0};
|
WEAK symbol<void()> Com_Frame_Try_Block_Function{0x1403BC980, 0x1404131A0};
|
||||||
WEAK symbol<const char*(char const**)> Com_Parse{0x1404313E0, 0x1404F50E0};
|
WEAK symbol<const char*(char const**)> Com_Parse{0x1404313E0, 0x1404F50E0};
|
||||||
@ -57,6 +58,7 @@ namespace game
|
|||||||
WEAK symbol<int(const RawFile* rawfile)> DB_GetRawFileLen{0x140272E80, 0x14031FF80};
|
WEAK symbol<int(const RawFile* rawfile)> DB_GetRawFileLen{0x140272E80, 0x14031FF80};
|
||||||
WEAK symbol<void(const RawFile* rawfile, char* buf, int size)> DB_GetRawBuffer{0x140272D50, 0x14031FE50};
|
WEAK symbol<void(const RawFile* rawfile, char* buf, int size)> DB_GetRawBuffer{0x140272D50, 0x14031FE50};
|
||||||
WEAK symbol<int(const char* zoneName)> DB_IsLocalized{0x140273210, 0x140320360};
|
WEAK symbol<int(const char* zoneName)> DB_IsLocalized{0x140273210, 0x140320360};
|
||||||
|
WEAK symbol<int(XAssetType type, void** assets, int maxCount)> DB_GetAllXAssetOfType_FastFile{0x0, 0x14031FC00};
|
||||||
|
|
||||||
WEAK symbol<void*(unsigned int size, unsigned int alignment, unsigned int type, PMem_Source source)> PMem_AllocFromSource_NoDebug{0x140430B80, 0x1404F46C0};
|
WEAK symbol<void*(unsigned int size, unsigned int alignment, unsigned int type, PMem_Source source)> PMem_AllocFromSource_NoDebug{0x140430B80, 0x1404F46C0};
|
||||||
WEAK symbol<void(const char* name, PMem_Direction allocDir)> PMem_Free{0x140430EC0 , 0x1404F4A30};
|
WEAK symbol<void(const char* name, PMem_Direction allocDir)> PMem_Free{0x140430EC0 , 0x1404F4A30};
|
||||||
@ -96,6 +98,7 @@ namespace game
|
|||||||
WEAK symbol<Weapon(const char* pickupName, int model)> G_FindItem{0x140462490, 0x14021B7E0};
|
WEAK symbol<Weapon(const char* pickupName, int model)> G_FindItem{0x140462490, 0x14021B7E0};
|
||||||
WEAK symbol<int(playerState_s* ps, Weapon weapon, int dualWield, int startInAltMode, int usedBefore)> G_GivePlayerWeapon{0x140359E20, 0x1403DA5E0};
|
WEAK symbol<int(playerState_s* ps, Weapon weapon, int dualWield, int startInAltMode, int usedBefore)> G_GivePlayerWeapon{0x140359E20, 0x1403DA5E0};
|
||||||
WEAK symbol<Weapon(const char* name)> G_GetWeaponForName{0x140359890, 0x1403DA060};
|
WEAK symbol<Weapon(const char* name)> G_GetWeaponForName{0x140359890, 0x1403DA060};
|
||||||
|
WEAK symbol<void()> G_SetupLevelWeaponDef{0x0, 0x1403DA910};
|
||||||
WEAK symbol<void()> G_Glass_Update{0x14030E680, 0x140397450};
|
WEAK symbol<void()> G_Glass_Update{0x14030E680, 0x140397450};
|
||||||
WEAK symbol<void (playerState_s* ps, Weapon weapon, int hadWeapon)> G_InitializeAmmo{0x140311F00, 0x14039AEA0};
|
WEAK symbol<void (playerState_s* ps, Weapon weapon, int hadWeapon)> G_InitializeAmmo{0x140311F00, 0x14039AEA0};
|
||||||
WEAK symbol<void(int clientNum, Weapon weapon)> G_SelectWeapon{0x14035A200, 0x1403DA880};
|
WEAK symbol<void(int clientNum, Weapon weapon)> G_SelectWeapon{0x14035A200, 0x1403DA880};
|
||||||
@ -227,7 +230,7 @@ namespace game
|
|||||||
WEAK symbol<const char*(int clientNum)> SV_GetGuid{0, 0x140475990};
|
WEAK symbol<const char*(int clientNum)> SV_GetGuid{0, 0x140475990};
|
||||||
WEAK symbol<void(int clientNum, const char* reason)> SV_KickClientNum{0, 0x14046F730};
|
WEAK symbol<void(int clientNum, const char* reason)> SV_KickClientNum{0, 0x14046F730};
|
||||||
WEAK symbol<void(int index, const char* string)> SV_SetConfigstring{0, 0x140477450};
|
WEAK symbol<void(int index, const char* string)> SV_SetConfigstring{0, 0x140477450};
|
||||||
WEAK symbol<void(int clientNum, svscmd_type type, const char* text)> SV_GameSendServerCommand{0x140490F40, 0x1404758C0};
|
WEAK symbol<int(mp::client_t* client, const unsigned char* cmd, int cmdSize)> SV_CanReplaceServerCommand{0x0, 0x140478F00};
|
||||||
|
|
||||||
WEAK symbol<void(const char* error, ...)> Sys_Error{0x14043AC20, 0x1404FF510};
|
WEAK symbol<void(const char* error, ...)> Sys_Error{0x14043AC20, 0x1404FF510};
|
||||||
WEAK symbol<bool()> Sys_IsDatabaseReady2{0x1403C2D40, 0x140423920};
|
WEAK symbol<bool()> Sys_IsDatabaseReady2{0x1403C2D40, 0x140423920};
|
||||||
@ -255,6 +258,8 @@ namespace game
|
|||||||
|
|
||||||
WEAK symbol<void(void* ps)> Jump_ClearState{0x0, 0x140213120};
|
WEAK symbol<void(void* ps)> Jump_ClearState{0x0, 0x140213120};
|
||||||
|
|
||||||
|
WEAK symbol<void(const char* pszCommand, char* pszBuffer, int iBufferSize)> MSG_WriteReliableCommandToBuffer{0x0, 0x1404232B0};
|
||||||
|
|
||||||
WEAK symbol<void(unsigned __int64 markPos)> LargeLocalResetToMark{0x140423B50, 0x1404E4D00};
|
WEAK symbol<void(unsigned __int64 markPos)> LargeLocalResetToMark{0x140423B50, 0x1404E4D00};
|
||||||
|
|
||||||
WEAK symbol<void*(jmp_buf* Buf, int Value)> longjmp{0x14062E030, 0x140738060};
|
WEAK symbol<void*(jmp_buf* Buf, int Value)> longjmp{0x14062E030, 0x140738060};
|
||||||
|
@ -55,6 +55,7 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user