add http to lua [skip ci]
NOTE: THIS IS NOT WORKING IN ITS CURRENT STATE, i just need somewhere to put this for now
This commit is contained in:
parent
9da1ed34c6
commit
e5b0c3e411
173
src/client/component/http.cpp
Normal file
173
src/client/component/http.cpp
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
#include <std_include.hpp>
|
||||||
|
#include "loader/component_loader.hpp"
|
||||||
|
|
||||||
|
#include "game/structs.hpp"
|
||||||
|
#include "game/game.hpp"
|
||||||
|
|
||||||
|
#include "http.hpp"
|
||||||
|
#include "console.hpp"
|
||||||
|
#include "scheduler.hpp"
|
||||||
|
#include "scripting.hpp"
|
||||||
|
|
||||||
|
#include <utils/http.hpp>
|
||||||
|
#include <curl/curl.h>
|
||||||
|
|
||||||
|
namespace http
|
||||||
|
{
|
||||||
|
std::unordered_map<uint64_t, bool> active_requests{};
|
||||||
|
uint64_t request_id{};
|
||||||
|
|
||||||
|
unsigned int http_get(const std::string& url)
|
||||||
|
{
|
||||||
|
const auto id = request_id++;
|
||||||
|
active_requests[id] = true;
|
||||||
|
|
||||||
|
const auto object = scripting::array{};
|
||||||
|
const auto object_id = object.get_entity_id();
|
||||||
|
|
||||||
|
scheduler::once([id, object_id, url]()
|
||||||
|
{
|
||||||
|
const auto data = utils::http::get_data(url);
|
||||||
|
scheduler::once([id, object_id, data]()
|
||||||
|
{
|
||||||
|
if (active_requests.find(id) == active_requests.end())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!data.has_value())
|
||||||
|
{
|
||||||
|
scripting::notify(object_id, "done", {{}, false, "Unknown error"});
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& result = data.value();
|
||||||
|
const auto code = result.code;
|
||||||
|
const auto error = curl_easy_strerror(code);
|
||||||
|
|
||||||
|
if (code != CURLE_OK)
|
||||||
|
{
|
||||||
|
scripting::notify(object_id, "done", {{}, false, error});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.buffer.size() >= 0x5000)
|
||||||
|
{
|
||||||
|
console::warn("^3WARNING: HTTP result size bigger than 20480 bytes (%i), truncating!", static_cast<int>(result.buffer.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
scripting::notify(object_id, "done", {result.buffer.substr(0, 0x5000), true});
|
||||||
|
}, scheduler::pipeline::server);
|
||||||
|
}, scheduler::pipeline::async);
|
||||||
|
|
||||||
|
return object_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int http_request(const std::string& url, const sol::variadic_args& va)
|
||||||
|
{
|
||||||
|
const auto id = request_id++;
|
||||||
|
active_requests[id] = true;
|
||||||
|
|
||||||
|
const auto object = scripting::array{};
|
||||||
|
const auto object_id = object.get_entity_id();
|
||||||
|
|
||||||
|
std::string fields_string{};
|
||||||
|
std::unordered_map<std::string, std::string> headers_map{};
|
||||||
|
|
||||||
|
if (va.size() > 0)
|
||||||
|
{
|
||||||
|
const scripting::array options = va[0].as<scripting::array>();
|
||||||
|
|
||||||
|
const auto fields = options["parameters"];
|
||||||
|
const auto body = options["body"];
|
||||||
|
const auto headers = options["headers"];
|
||||||
|
|
||||||
|
if (fields.is<scripting::array>())
|
||||||
|
{
|
||||||
|
const auto fields_ = fields.as<scripting::array>();
|
||||||
|
const auto keys = fields_.get_keys();
|
||||||
|
|
||||||
|
for (const auto& key : keys)
|
||||||
|
{
|
||||||
|
if (!key.is<std::string>())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto key_ = key.as<std::string>();
|
||||||
|
const auto value = fields_[key].to_string();
|
||||||
|
fields_string += key_ + "=" + value + "&";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (body.is<std::string>())
|
||||||
|
{
|
||||||
|
fields_string = body.as<std::string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (headers.is<scripting::array>())
|
||||||
|
{
|
||||||
|
const auto headers_ = headers.as<scripting::array>();
|
||||||
|
const auto keys = headers_.get_keys();
|
||||||
|
|
||||||
|
for (const auto& key : keys)
|
||||||
|
{
|
||||||
|
if (!key.is<std::string>())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto key_ = key.as<std::string>();
|
||||||
|
const auto value = headers_[key].to_string();
|
||||||
|
|
||||||
|
headers_map[key_] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scheduler::once([id, object_id, url]()
|
||||||
|
{
|
||||||
|
const auto data = utils::http::get_data(url);
|
||||||
|
scheduler::once([id, object_id, data]()
|
||||||
|
{
|
||||||
|
if (active_requests.find(id) == active_requests.end())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!data.has_value())
|
||||||
|
{
|
||||||
|
scripting::notify(object_id, "done", {{}, false, "Unknown error"});
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& result = data.value();
|
||||||
|
const auto code = result.code;
|
||||||
|
const auto error = curl_easy_strerror(code);
|
||||||
|
|
||||||
|
if (code != CURLE_OK)
|
||||||
|
{
|
||||||
|
scripting::notify(object_id, "done", { {}, false, error });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.buffer.size() >= 0x5000)
|
||||||
|
{
|
||||||
|
console::warn("^3WARNING: HTTP result size bigger than 20480 bytes (%i), truncating!", static_cast<int>(result.buffer.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
scripting::notify(object_id, "done", {result.buffer.substr(0, 0x5000), true});
|
||||||
|
}, scheduler::pipeline::server);
|
||||||
|
}, scheduler::pipeline::async);
|
||||||
|
|
||||||
|
return object_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
class component final : public component_interface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void post_unpack() override
|
||||||
|
{
|
||||||
|
scripting::on_shutdown([]()
|
||||||
|
{
|
||||||
|
active_requests.clear();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
11
src/client/component/http.hpp
Normal file
11
src/client/component/http.hpp
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "game/scripting/lua/value_conversion.hpp"
|
||||||
|
#include "game/scripting/array.hpp"
|
||||||
|
#include "game/scripting/execution.hpp"
|
||||||
|
|
||||||
|
namespace http
|
||||||
|
{
|
||||||
|
unsigned int http_get(const std::string& url);
|
||||||
|
unsigned int http_request(const std::string& url, const sol::variadic_args& va);
|
||||||
|
}
|
@ -44,6 +44,8 @@ namespace scripting
|
|||||||
|
|
||||||
game::dvar_t* g_dump_scripts;
|
game::dvar_t* g_dump_scripts;
|
||||||
|
|
||||||
|
std::vector<std::function<void()>> shutdown_callbacks;
|
||||||
|
|
||||||
void vm_notify_stub(const unsigned int notify_list_owner_id, const game::scr_string_t string_value,
|
void vm_notify_stub(const unsigned int notify_list_owner_id, const game::scr_string_t string_value,
|
||||||
game::VariableValue* top)
|
game::VariableValue* top)
|
||||||
{
|
{
|
||||||
@ -94,6 +96,11 @@ namespace scripting
|
|||||||
script_function_table.clear();
|
script_function_table.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const auto& callback : shutdown_callbacks)
|
||||||
|
{
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
|
||||||
scripting::notify(*game::levelEntityId, "shutdownGame_called", {1});
|
scripting::notify(*game::levelEntityId, "shutdownGame_called", {1});
|
||||||
lua::engine::stop();
|
lua::engine::stop();
|
||||||
return g_shutdown_game_hook.invoke<void>(free_scripts);
|
return g_shutdown_game_hook.invoke<void>(free_scripts);
|
||||||
@ -162,6 +169,11 @@ namespace scripting
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void on_shutdown(const std::function<void()>& callback)
|
||||||
|
{
|
||||||
|
shutdown_callbacks.push_back(callback);
|
||||||
|
}
|
||||||
|
|
||||||
class component final : public component_interface
|
class component final : public component_interface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -8,4 +8,6 @@ namespace scripting
|
|||||||
extern std::unordered_map<int, std::unordered_map<std::string, int>> fields_table;
|
extern std::unordered_map<int, std::unordered_map<std::string, int>> fields_table;
|
||||||
extern std::unordered_map<std::string, std::unordered_map<std::string, const char*>> script_function_table;
|
extern std::unordered_map<std::string, std::unordered_map<std::string, const char*>> script_function_table;
|
||||||
extern utils::concurrency::container<shared_table_t> shared_table;
|
extern utils::concurrency::container<shared_table_t> shared_table;
|
||||||
|
|
||||||
|
void on_shutdown(const std::function<void()>& callback);
|
||||||
}
|
}
|
@ -76,6 +76,8 @@ namespace scripting
|
|||||||
{
|
{
|
||||||
return { this->id_, this->get_value_id(key.as<S>()) };
|
return { this->id_, this->get_value_id(key.as<S>()) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
throw std::runtime_error("Invalid key type");
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -7,12 +7,15 @@
|
|||||||
#include "../functions.hpp"
|
#include "../functions.hpp"
|
||||||
|
|
||||||
#include "../../../component/command.hpp"
|
#include "../../../component/command.hpp"
|
||||||
|
#include "../../../component/http.hpp"
|
||||||
#include "../../../component/logfile.hpp"
|
#include "../../../component/logfile.hpp"
|
||||||
#include "../../../component/scripting.hpp"
|
#include "../../../component/scripting.hpp"
|
||||||
#include "../../../component/fastfiles.hpp"
|
#include "../../../component/fastfiles.hpp"
|
||||||
|
#include "../../../component/scheduler.hpp"
|
||||||
|
|
||||||
#include <utils/string.hpp>
|
#include <utils/string.hpp>
|
||||||
#include <utils/io.hpp>
|
#include <utils/io.hpp>
|
||||||
|
#include <utils/http.hpp>
|
||||||
|
|
||||||
namespace scripting::lua
|
namespace scripting::lua
|
||||||
{
|
{
|
||||||
@ -567,6 +570,20 @@ namespace scripting::lua
|
|||||||
return sol::lua_value{s, sol::lua_nil};
|
return sol::lua_value{s, sol::lua_nil};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
game_type["httpget"] = [](const game& game, const sol::this_state s,
|
||||||
|
const std::string& url)
|
||||||
|
{
|
||||||
|
const auto request = http::http_get(url);
|
||||||
|
return convert(s, scripting::entity{request});
|
||||||
|
};
|
||||||
|
|
||||||
|
game_type["httprequest"] = [](const game& game, const sol::this_state s,
|
||||||
|
const std::string& url, sol::variadic_args va)
|
||||||
|
{
|
||||||
|
const auto request = http::http_request(url, va);
|
||||||
|
return convert(s, scripting::entity{request});
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include "script_value.hpp"
|
#include "script_value.hpp"
|
||||||
#include "entity.hpp"
|
#include "entity.hpp"
|
||||||
#include "array.hpp"
|
#include "array.hpp"
|
||||||
|
#include "functions.hpp"
|
||||||
|
|
||||||
namespace scripting
|
namespace scripting
|
||||||
{
|
{
|
||||||
@ -290,4 +291,39 @@ namespace scripting
|
|||||||
{
|
{
|
||||||
return this->value_.get();
|
return this->value_.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string script_value::to_string() const
|
||||||
|
{
|
||||||
|
if (this->is<int>())
|
||||||
|
{
|
||||||
|
return utils::string::va("%i", this->as<int>());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->is<float>())
|
||||||
|
{
|
||||||
|
return utils::string::va("%f", this->as<float>());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->is<std::string>())
|
||||||
|
{
|
||||||
|
return this->as<std::string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->is<vector>())
|
||||||
|
{
|
||||||
|
const auto vec = this->as<vector>();
|
||||||
|
return utils::string::va("(%g, %g, %g)",
|
||||||
|
vec.get_x(),
|
||||||
|
vec.get_y(),
|
||||||
|
vec.get_z()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->is<std::function<void()>>())
|
||||||
|
{
|
||||||
|
return utils::string::va("[[ function ]]");
|
||||||
|
}
|
||||||
|
|
||||||
|
return this->type_name();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
#include "variable_value.hpp"
|
#include "variable_value.hpp"
|
||||||
#include "vector.hpp"
|
#include "vector.hpp"
|
||||||
|
|
||||||
|
#include <utils/string.hpp>
|
||||||
|
|
||||||
namespace scripting
|
namespace scripting
|
||||||
{
|
{
|
||||||
class entity;
|
class entity;
|
||||||
@ -32,6 +34,14 @@ namespace scripting
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
bool is() const;
|
bool is() const;
|
||||||
|
|
||||||
|
// was gonna do this but no clue if this is the same on H1 so just return string (https://github.com/fedddddd/t6-gsc-utils/blob/main/src/game/scripting/script_value.hpp#L18)
|
||||||
|
std::string type_name() const
|
||||||
|
{
|
||||||
|
return utils::string::va("%s", this->get_raw().type);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string to_string() const;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T as() const
|
T as() const
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user