diff --git a/src/component/io.cpp b/src/component/io.cpp index 9136bae..d7e5fb0 100644 --- a/src/component/io.cpp +++ b/src/component/io.cpp @@ -4,9 +4,76 @@ #include "scheduler.hpp" #include "gsc.hpp" #include "json.hpp" +#include "scripting.hpp" namespace io { + namespace + { + struct http_request_t + { + std::string url; + bool completed; + std::string result; + scripting::entity handle; + }; + + utils::concurrency::container> requests; + + void run_requests() + { + requests.access([&](std::vector& r) + { + for (auto& request : r) + { + const auto data = utils::http::get_data(request.url.data()); + if (data.has_value()) + { + request.result = data->substr(0, 0x5000); + } + else + { + request.result = ""; + } + + request.completed = true; + } + }); + } + + void check_requests() + { + requests.access([&](std::vector& r) + { + for (auto i = r.begin(); i != r.end(); ) + { + if (!i->completed) + { + ++i; + continue; + } + else + { + scripting::notify(i->handle, "done", {i->result}); + i = r.erase(i); + } + } + }); + } + + void add_request(const std::string& url, const scripting::entity& handle) + { + requests.access([&](std::vector& r) + { + http_request_t request{}; + request.handle = handle; + request.url = url; + request.completed = false; + r.emplace_back(request); + }); + } + } + class component final : public component_interface { public: @@ -24,6 +91,17 @@ namespace io void on_startup([[maybe_unused]] plugin::plugin* plugin) override { + scheduler::loop(run_requests, scheduler::async); + scheduler::loop(check_requests, scheduler::server); + + scripting::on_shutdown([]() + { + requests.access([&](std::vector& r) + { + r.clear(); + }); + }); + gsc::function::add("jsonprint", [](const gsc::function_args& args) -> scripting::script_value { std::string buffer; @@ -116,17 +194,7 @@ namespace io const auto url = args[0].as(); const auto object = scripting::entity(scripting::make_object()); - scheduler::once([object, url]() - { - const auto result = utils::http::get_data(url.data()); - scheduler::once([object, result]() - { - const auto value = result.has_value() - ? result.value().substr(0, 0x5000) - : ""; - scripting::notify(object, "done", {value}); - }); - }, scheduler::pipeline::async); + add_request(url, object); return object; }); diff --git a/src/component/scheduler.cpp b/src/component/scheduler.cpp index 8be9a1b..8c4461c 100644 --- a/src/component/scheduler.cpp +++ b/src/component/scheduler.cpp @@ -77,6 +77,7 @@ namespace scheduler }; std::thread thread; + std::atomic_bool killed; task_pipeline pipelines[pipeline::count]; void execute(const pipeline type) @@ -132,7 +133,7 @@ namespace scheduler { thread = std::thread([]() { - while (true) + while (!killed) { execute(pipeline::async); std::this_thread::sleep_for(10ms); @@ -141,6 +142,16 @@ namespace scheduler utils::hook::call(0x50CEDC, server_frame_stub); } + + void on_shutdown([[maybe_unused]] plugin::plugin* plugin) override + { + killed = true; + + if (thread.joinable()) + { + thread.join(); + } + } }; } diff --git a/src/game/scripting/execution.cpp b/src/game/scripting/execution.cpp index e89c17e..cce719c 100644 --- a/src/game/scripting/execution.cpp +++ b/src/game/scripting/execution.cpp @@ -1,6 +1,5 @@ #include #include "execution.hpp" -#include "safe_execution.hpp" #include "stack_isolation.hpp" #include "event.hpp" diff --git a/src/game/scripting/safe_execution.cpp b/src/game/scripting/safe_execution.cpp deleted file mode 100644 index de997c4..0000000 --- a/src/game/scripting/safe_execution.cpp +++ /dev/null @@ -1,74 +0,0 @@ -#include -#include "safe_execution.hpp" - -#pragma warning(push) -#pragma warning(disable: 4611) - -namespace scripting::safe_execution -{ - namespace - { - bool execute_with_seh(const script_function function, const game::scr_entref_t& entref) - { - __try - { - function(entref); - return true; - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - return false; - } - } - } - - bool call(const script_function function, const game::scr_entref_t& entref) - { - *game::g_script_error_level += 1; - if (game::_setjmp(&game::g_script_error[*game::g_script_error_level], 0, 0, 0)) - { - *game::g_script_error_level -= 1; - return false; - } - - const auto result = execute_with_seh(function, entref); - *game::g_script_error_level -= 1; - return result; - } - - bool set_entity_field(const game::scr_entref_t& entref, const int offset) - { - *game::g_script_error_level += 1; - if (game::_setjmp(&game::g_script_error[*game::g_script_error_level], 0, 0, 0)) - { - *game::g_script_error_level -= 1; - return false; - } - - game::Scr_SetObjectField(entref.classnum, entref.entnum, offset); - - *game::g_script_error_level -= 1; - return true; - } - - bool get_entity_field(const game::scr_entref_t& entref, const int offset, game::VariableValue* value) - { - *game::g_script_error_level += 1; - if (game::_setjmp(&game::g_script_error[*game::g_script_error_level], 0, 0, 0)) - { - value->type = game::SCRIPT_NONE; - value->u.intValue = 0; - *game::g_script_error_level -= 1; - return false; - } - - const auto _value = game::GetEntityFieldValue(entref.classnum, entref.entnum, offset); - value->type = _value.type; - value->u = _value.u; - - *game::g_script_error_level -= 1; - return true; - } -} - -#pragma warning(pop) diff --git a/src/game/scripting/safe_execution.hpp b/src/game/scripting/safe_execution.hpp deleted file mode 100644 index 6eea59d..0000000 --- a/src/game/scripting/safe_execution.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once -#include "functions.hpp" - -namespace scripting::safe_execution -{ - bool call(script_function function, const game::scr_entref_t& entref); - - bool set_entity_field(const game::scr_entref_t& entref, int offset); - bool get_entity_field(const game::scr_entref_t& entref, int offset, game::VariableValue* value); -} diff --git a/src/game/symbols.hpp b/src/game/symbols.hpp index a47fbb9..15efd47 100644 --- a/src/game/symbols.hpp +++ b/src/game/symbols.hpp @@ -25,8 +25,6 @@ namespace game WEAK symbol Dvar_FindVar{0x5BDCC0}; - WEAK symbol I_CleanStr{0x0}; - WEAK symbol GetEntityFieldValue{0x56AF20}; WEAK symbol FindVariable{0x5651F0}; WEAK symbol FindObject{0x565BD0};