Organize scripts and add TWS plugins with HTTP timeouts
Vendor pinned T5 and T6 plugin sources under the new plugins layout. Add native HTTP deadlines, status and timing diagnostics, telemetry integration, and build/test tooling.
This commit is contained in:
@@ -0,0 +1,136 @@
|
||||
#include <stdinc.hpp>
|
||||
#include "loader/component_loader.hpp"
|
||||
|
||||
#include "game/game.hpp"
|
||||
|
||||
#include "gsc.hpp"
|
||||
|
||||
#include <utils/hook.hpp>
|
||||
#include <utils/info_string.hpp>
|
||||
|
||||
namespace user_info
|
||||
{
|
||||
namespace
|
||||
{
|
||||
using user_info_map = std::unordered_map<std::string, std::string>;
|
||||
std::array<user_info_map, 18> user_info_overrides;
|
||||
|
||||
utils::hook::detour scr_shutdown_system_hook;
|
||||
|
||||
void clear_client_overrides(unsigned int client_num)
|
||||
{
|
||||
user_info_overrides[client_num].clear();
|
||||
}
|
||||
|
||||
void clear_all_overrides()
|
||||
{
|
||||
for (auto& entry : user_info_overrides)
|
||||
{
|
||||
entry.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void scr_shutdown_system_stub(const game::scriptInstance_t inst, const unsigned char sys, const int b_complete)
|
||||
{
|
||||
clear_all_overrides();
|
||||
scr_shutdown_system_hook.invoke<void>(inst, sys, b_complete);
|
||||
}
|
||||
|
||||
void sv_get_user_info_stub(const int index, char* buffer, const int buffer_size)
|
||||
{
|
||||
game::SV_GetUserinfo(index, buffer, buffer_size);
|
||||
|
||||
utils::info_string map(buffer);
|
||||
|
||||
for (const auto& [key, val] : user_info_overrides[index])
|
||||
{
|
||||
if (val.empty())
|
||||
{
|
||||
map.remove(key);
|
||||
}
|
||||
else
|
||||
{
|
||||
map.set(key, val);
|
||||
}
|
||||
}
|
||||
|
||||
const auto user_info = map.build();
|
||||
strncpy_s(buffer, buffer_size, user_info.data(), _TRUNCATE);
|
||||
}
|
||||
}
|
||||
|
||||
class component final : public component_interface
|
||||
{
|
||||
public:
|
||||
void on_startup([[maybe_unused]] plugin::plugin* plugin) override
|
||||
{
|
||||
utils::hook::call(SELECT_VALUE(0x5D38EB, 0x4A75E2), sv_get_user_info_stub);
|
||||
utils::hook::call(SELECT_VALUE(0x67FFE9, 0x548DB0), sv_get_user_info_stub);
|
||||
|
||||
plugin->get_interface()->callbacks()->on_player_connect(clear_client_overrides);
|
||||
plugin->get_interface()->callbacks()->on_player_disconnect(clear_client_overrides);
|
||||
|
||||
scr_shutdown_system_hook.create(SELECT_VALUE(0x596D40, 0x540780), scr_shutdown_system_stub);
|
||||
|
||||
gsc::method::add_multiple([](const scripting::entity& player, const std::string& name) -> void
|
||||
{
|
||||
const auto entref = player.get_entity_reference();
|
||||
if (entref.classnum)
|
||||
{
|
||||
throw std::runtime_error("Not a player entity");
|
||||
}
|
||||
|
||||
if (name.empty())
|
||||
{
|
||||
throw std::runtime_error("set_name: Illegal parameter!");
|
||||
}
|
||||
|
||||
user_info_overrides[entref.entnum]["name"] = name;
|
||||
game::ClientUserinfoChanged(entref.entnum);
|
||||
}, "user_info::set_name", "set_name");
|
||||
|
||||
gsc::method::add_multiple([](const scripting::entity& player) -> void
|
||||
{
|
||||
const auto entref = player.get_entity_reference();
|
||||
if (entref.classnum)
|
||||
{
|
||||
throw std::runtime_error("Not a player entity");
|
||||
}
|
||||
|
||||
user_info_overrides[entref.entnum].erase("name");
|
||||
game::ClientUserinfoChanged(entref.entnum);
|
||||
}, "user_info::reset_name", "reset_name");
|
||||
|
||||
gsc::method::add_multiple([](const scripting::entity& player, const std::string& tag) -> void
|
||||
{
|
||||
const auto entref = player.get_entity_reference();
|
||||
if (entref.classnum)
|
||||
{
|
||||
throw std::runtime_error("Not a player entity");
|
||||
}
|
||||
|
||||
if (tag.empty())
|
||||
{
|
||||
throw std::runtime_error("set_clantag: Illegal parameter!");
|
||||
}
|
||||
|
||||
user_info_overrides[entref.entnum]["clanAbbrev"] = tag;
|
||||
game::ClientUserinfoChanged(entref.entnum);
|
||||
}, "user_info::set_clantag", "set_clantag");
|
||||
|
||||
gsc::method::add_multiple([](const scripting::entity& player) -> void
|
||||
{
|
||||
const auto entref = player.get_entity_reference();
|
||||
if (entref.classnum)
|
||||
{
|
||||
throw std::runtime_error("Not a player entity");
|
||||
}
|
||||
|
||||
user_info_overrides[entref.entnum].erase("clanAbbrev");
|
||||
game::ClientUserinfoChanged(entref.entnum);
|
||||
}, "user_info::reset_clantag", "reset_clantag");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
REGISTER_COMPONENT(user_info::component)
|
||||
Reference in New Issue
Block a user