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:
2026-10-09 11:02:20 -04:00
parent b172086301
commit 1121b44857
253 changed files with 28028 additions and 59 deletions
@@ -0,0 +1,133 @@
#include <stdinc.hpp>
#include "loader/component_loader.hpp"
#include "game/game.hpp"
#include "gsc.hpp"
#include "io.hpp"
#include "scheduler.hpp"
#include "scripting.hpp"
#include <utils/hook.hpp>
#include <utils/http.hpp>
#include <utils/io.hpp>
#include <utils/file_watcher.hpp>
#include <utils/flags.hpp>
namespace io
{
namespace
{
struct watched_file
{
std::unique_ptr<utils::io::file_watcher> watcher;
scripting::object handle;
};
std::vector<watched_file> watched_files;
void poll_files()
{
for (auto& file : watched_files)
{
std::string data;
if (file.watcher->run(1ms, &data, true))
{
scripting::notify(file.handle.get_entity_id(), "data", {data});
}
}
}
}
class component final : public component_interface
{
public:
void on_after_dvar_init([[maybe_unused]] plugin::plugin* plugin) override
{
const auto fs_homepath = game::Dvar_FindVar("fs_homepath");
if (fs_homepath == nullptr)
{
return;
}
std::filesystem::current_path(fs_homepath->current.string);
printf("working directory: %s", fs_homepath->current.string);
}
void on_startup([[maybe_unused]] plugin::plugin* plugin) override
{
gsc::function::add("hashstring", [](const char* str)
{
return game::BG_StringHashValue(str);
});
gsc::function::add_multiple([](const std::string& file, const std::string& data,
const scripting::variadic_args& va)
{
auto append = false;
if (va.size() > 0)
{
append = va[0];
}
return utils::io::write_file(file, data, append);
}, "writefile", "io::write_file");
gsc::function::add_multiple([](const std::string& file, const std::string& data)
{
return utils::io::write_file(file, data, true);
}, "appendfile", "io::append_file");
gsc::function::add_multiple(utils::io::file_exists, "fileexists", "io::file_exists");
gsc::function::add_multiple(utils::io::move_file, "movefile", "io::move_file");
gsc::function::add_multiple(utils::io::file_size, "filesize", "io::file_size");
gsc::function::add_multiple(utils::io::create_directory, "createdirectory", "io::create_directory");
gsc::function::add_multiple(utils::io::directory_exists, "directoryexists", "io::directory_exists");
gsc::function::add_multiple(utils::io::directory_is_empty, "directoryisempty", "io::directory_is_empty");
gsc::function::add_multiple(utils::io::list_files, "listfiles", "io::list_files");
gsc::function::add_multiple(utils::io::remove_file, "removefile", "io::remove_file");
gsc::function::add_multiple([](const std::string& directory, const scripting::variadic_args& va)
{
auto recursive = false;
if (va.size() > 0)
{
recursive = va[0];
}
utils::io::remove_directory(directory, recursive);
}, "removedirectory", "io::remove_directory");
gsc::function::add_multiple(utils::io::copy_folder, "copyfolder", "io::copy_folder");
gsc::function::add_multiple(utils::io::copy_folder, "copydirectory", "io::copy_directory");
gsc::function::add_multiple(static_cast<std::string(*)(const std::string&)>(utils::io::read_file), "readfile", "io::read_file");
if (utils::flags::has_flag("experimental-utils"))
{
scheduler::loop(poll_files, scheduler::server_packet_loop);
scripting::on_shutdown([]()
{
watched_files.clear();
});
gsc::function::add("io::watch_file", [](const std::string& file)
{
scripting::object handle;
auto watcher = std::make_unique<utils::io::file_watcher>(file);
watcher->init();
watched_file watched_file{};
watched_file.watcher = std::move(watcher);
watched_file.handle = handle;
watched_files.emplace_back(std::move(watched_file));
return handle;
});
}
}
};
}
REGISTER_COMPONENT(io::component)