From 234f29690fbb1c1945a04a78dd9c2b94c9c22ff5 Mon Sep 17 00:00:00 2001 From: fed <58637860+fedddddd@users.noreply.github.com> Date: Wed, 24 May 2023 17:06:48 +0200 Subject: [PATCH] Better mod stats + add some gsc funcs --- src/client/component/gsc/script_error.cpp | 62 ++--- src/client/component/gsc/script_error.hpp | 2 + src/client/component/gsc/script_extension.cpp | 152 +++++++++++ src/client/component/gui/debug.cpp | 95 +++++++ src/client/component/gui/debug.hpp | 10 + src/client/component/mod_stats.cpp | 245 ++++++++++++++++++ src/client/component/mod_stats.hpp | 21 ++ src/client/component/mods.cpp | 97 +------ src/client/component/mods.hpp | 3 - src/client/component/scripting.cpp | 8 + src/client/component/ui_scripting.cpp | 28 +- src/client/game/scripting/lua/context.cpp | 69 ++++- 12 files changed, 644 insertions(+), 148 deletions(-) create mode 100644 src/client/component/gui/debug.hpp create mode 100644 src/client/component/mod_stats.cpp create mode 100644 src/client/component/mod_stats.hpp diff --git a/src/client/component/gsc/script_error.cpp b/src/client/component/gsc/script_error.cpp index e237ec6a..7b192f52 100644 --- a/src/client/component/gsc/script_error.cpp +++ b/src/client/component/gsc/script_error.cpp @@ -12,6 +12,37 @@ namespace gsc { + std::array var_typename = + { + "undefined", + "object", + "string", + "localized string", + "vector", + "float", + "int", + "codepos", + "precodepos", + "function", + "builtin function", + "builtin method", + "stack", + "animation", + "pre animation", + "thread", + "thread", + "thread", + "thread", + "struct", + "removed entity", + "entity", + "array", + "removed thread", + "", + "thread list", + "endon list", + }; + namespace { utils::hook::detour scr_emit_function_hook; @@ -20,37 +51,6 @@ namespace gsc std::string unknown_function_error; - std::array var_typename = - { - "undefined", - "object", - "string", - "localized string", - "vector", - "float", - "int", - "codepos", - "precodepos", - "function", - "builtin function", - "builtin method", - "stack", - "animation", - "pre animation", - "thread", - "thread", - "thread", - "thread", - "struct", - "removed entity", - "entity", - "array", - "removed thread", - "", - "thread list", - "endon list", - }; - void scr_emit_function_stub(unsigned int filename, unsigned int thread_name, char* code_pos) { current_filename = filename; diff --git a/src/client/component/gsc/script_error.hpp b/src/client/component/gsc/script_error.hpp index 284af439..54ad80b9 100644 --- a/src/client/component/gsc/script_error.hpp +++ b/src/client/component/gsc/script_error.hpp @@ -2,5 +2,7 @@ namespace gsc { + extern std::array var_typename; + std::optional> find_function(const char* pos); } diff --git a/src/client/component/gsc/script_extension.cpp b/src/client/component/gsc/script_extension.cpp index c5b35981..b7fa2e2f 100644 --- a/src/client/component/gsc/script_extension.cpp +++ b/src/client/component/gsc/script_extension.cpp @@ -10,8 +10,15 @@ #include "component/console.hpp" #include "component/command.hpp" #include "component/notifies.hpp" +#include "component/scheduler.hpp" +#include "component/mods.hpp" +#include "component/mod_stats.hpp" +#include "component/scripting.hpp" #include "game/scripting/script_value.hpp" +#include "game/scripting/execution.hpp" + +#include "game/ui_scripting/execution.hpp" #include #include @@ -225,6 +232,42 @@ namespace gsc return game::scr_VmPub->top[-index]; } + + nlohmann::json gsc_to_json(const scripting::script_value& value) + { +#define CHECK_TYPE(__type__) \ + if (value.is<__type__>()) \ + { \ + return value.as<__type__>(); \ + } \ + + CHECK_TYPE(std::string); + CHECK_TYPE(int); + CHECK_TYPE(float); + CHECK_TYPE(bool); + + return {}; + +#undef CHECK_TYPE + } + + scripting::script_value json_to_gsc(const nlohmann::json& value) + { +#define CHECK_TYPE(__func__, __type__) \ + if (value.__func__()) \ + { \ + return value.get<__type__>(); \ + } \ + + CHECK_TYPE(is_string, std::string); + CHECK_TYPE(is_number_integer, int); + CHECK_TYPE(is_number_float, float); + CHECK_TYPE(is_boolean, bool); + + return {}; + +#undef CHECK_TYPE + } } void scr_error(bool force_print, const char* fmt, ...) @@ -322,6 +365,115 @@ namespace gsc const auto cmd = game::Scr_GetString(0); command::execute(cmd); }); + + add_function("luinotify", []() + { + const std::string name = game::Scr_GetString(0); + const std::string data = game::Scr_GetString(1); + + scheduler::once([=]() + { + ui_scripting::notify(name, {{"data", data}}); + }, scheduler::pipeline::lui); + }); + + add_function("statsset", []() + { + const auto key = game::Scr_GetString(0); + const auto value = get_argument(1); + const auto json_value = gsc_to_json(value); + mod_stats::set(key, json_value); + }); + + add_function("statssetstruct", []() + { + const auto struct_ = game::Scr_GetString(0); + const auto field = game::Scr_GetString(1); + const auto value = get_argument(2); + const auto json_value = gsc_to_json(value); + mod_stats::set_struct(struct_, field, json_value); + }); + + add_function("statsget", []() + { + const auto key = game::Scr_GetString(0); + const auto& value = mod_stats::get(key); + scripting::push_value(json_to_gsc(value)); + }); + + add_function("statsgetor", []() + { + const auto key = game::Scr_GetString(0); + const auto default_value = get_argument(1); + const auto json_default_value = gsc_to_json(default_value); + const auto value = mod_stats::get(key, json_default_value); + scripting::push_value(json_to_gsc(value)); + }); + + add_function("statsgetstruct", []() + { + const auto struct_ = game::Scr_GetString(0); + const auto field = game::Scr_GetString(1); + const auto value = mod_stats::get_struct(struct_, field); + scripting::push_value(json_to_gsc(value)); + }); + + add_function("statsgetstructor", []() + { + const auto struct_ = game::Scr_GetString(0); + const auto field = game::Scr_GetString(1); + const auto default_value = get_argument(2); + const auto json_default_value = gsc_to_json(default_value); + const auto value = mod_stats::get_struct(struct_, field, json_default_value); + scripting::push_value(json_to_gsc(value)); + }); + + add_function("typeof", []() + { + const auto arg = get_argument(0); + const auto type = arg.get_raw().type; + + if (type < var_typename.size()) + { + game::Scr_AddString(var_typename[type]); + } + else + { + game::Scr_AddString("unknown"); + } + }); + + add_function("sharedset", []() + { + const std::string key = game::Scr_GetString(0); + const std::string value = game::Scr_GetString(1); + + scripting::shared_table.access([&](scripting::shared_table_t& table) + { + table[key] = value; + }); + }); + + add_function("sharedget", []() + { + const std::string key = game::Scr_GetString(0); + const auto value = scripting::shared_table.access( + [&](scripting::shared_table_t& table) + { + return table[key]; + } + ); + + game::Scr_AddString(value.data()); + }); + + add_function("sharedclear", []() + { + scripting::shared_table.access([&](scripting::shared_table_t& table) + { + table.clear(); + }); + }); } }; } diff --git a/src/client/component/gui/debug.cpp b/src/client/component/gui/debug.cpp index 9291672c..60bf6ea9 100644 --- a/src/client/component/gui/debug.cpp +++ b/src/client/component/gui/debug.cpp @@ -20,6 +20,23 @@ namespace gui::debug { namespace { + struct debug_line + { + float start[3]; + float end[3]; + float color[4]; + }; + + struct debug_square + { + float origin[3]; + float color[4]; + }; + + std::vector debug_lines; + std::vector debug_squares; + std::mutex debug_items_mutex; + game::dvar_t* cl_paused = nullptr; enum object_type @@ -570,6 +587,12 @@ namespace gui::debug continue; } + float screen_center[2]{}; + ImGuiWindow* window = ImGui::GetCurrentWindow(); + world_pos_to_screen_pos(origin, screen_center); + window->DrawList->AddText(ImGui::GetDefaultFont(), ImGui::GetFontSize(), ImVec2(screen_center[0], + screen_center[1]), ImColor(255, 255, 0, 255), utils::string::va("%i", node->constant.type), 0, 0.f, 0); + switch (path_node_settings.type) { case object_type::square: @@ -654,6 +677,21 @@ namespace gui::debug } } + void draw_debug_items() + { + std::lock_guard _0(debug_items_mutex); + + for (auto& line : debug_lines) + { + draw_line(line.start, line.end, line.color, 1.f); + } + + for (auto& square : debug_squares) + { + draw_square(square.origin, 100.f, square.color); + } + } + void update_camera() { camera[0] = game::refdef->org[0]; @@ -688,6 +726,62 @@ namespace gui::debug } } + size_t add_debug_line(const float* start, const float* end, const float* color) + { + debug_line line{}; + std::memcpy(line.start, start, sizeof(float[3])); + std::memcpy(line.end, end, sizeof(float[3])); + std::memcpy(line.color, color, sizeof(float[4])); + + std::lock_guard _0(debug_items_mutex); + const auto index = debug_squares.size(); + debug_lines.emplace_back(line); + return index; + } + + void set_debug_line_color(size_t line, const float* color) + { + std::lock_guard _0(debug_items_mutex); + if (line >= debug_lines.size()) + { + return; + } + + auto& line_ = debug_lines.at(line); + std::memcpy(line_.color, color, sizeof(float[4])); + } + + size_t add_debug_square(const float* origin, const float* color) + { + debug_square line{}; + std::memcpy(line.origin, origin, sizeof(float[3])); + std::memcpy(line.color, color, sizeof(float[4])); + + std::lock_guard _0(debug_items_mutex); + const auto index = debug_squares.size(); + debug_squares.emplace_back(line); + return index; + } + + void set_debug_square_color(size_t square, const float* color) + { + std::lock_guard _0(debug_items_mutex); + if (square >= debug_squares.size()) + { + return; + } + + auto& square_ = debug_squares.at(square); + std::memcpy(square_.color, color, sizeof(float[4])); + } + + void reset_debug_items() + { + std::lock_guard _0(debug_items_mutex); + debug_lines.clear(); + debug_squares.clear(); + } + class component final : public component_interface { public: @@ -705,6 +799,7 @@ namespace gui::debug begin_render_window(); draw_nodes(); draw_triggers(); + draw_debug_items(); end_render_window(); }, true); diff --git a/src/client/component/gui/debug.hpp b/src/client/component/gui/debug.hpp new file mode 100644 index 00000000..a5c8c24a --- /dev/null +++ b/src/client/component/gui/debug.hpp @@ -0,0 +1,10 @@ +namespace gui::debug +{ + size_t add_debug_line(const float* start, const float* end, const float* color); + void set_debug_line_color(size_t line, const float* color); + + size_t add_debug_square(const float* origin, const float* color); + void set_debug_square_color(size_t square, const float* color); + + void reset_debug_items(); +} diff --git a/src/client/component/mod_stats.cpp b/src/client/component/mod_stats.cpp new file mode 100644 index 00000000..70185fc2 --- /dev/null +++ b/src/client/component/mod_stats.cpp @@ -0,0 +1,245 @@ +#include +#include "loader/component_loader.hpp" + +#include "game/game.hpp" + +#include "console.hpp" +#include "filesystem.hpp" +#include "mods.hpp" +#include "mod_stats.hpp" + +#include +#include +#include +#include +#include +#include + +namespace mod_stats +{ + namespace + { + struct + { + utils::concurrency::container current_stats; + std::atomic_bool modified_stats; + std::atomic_bool kill_thread; + std::thread stats_write_thread; + } globals{}; + + std::optional get_mod_basename() + { + const auto mod = mods::get_mod(); + if (!mod.has_value()) + { + return {}; + } + + const auto& value = mod.value(); + const auto last_index = value.find_last_of('/'); + const auto basename = value.substr(last_index + 1); + return {basename}; + } + + std::optional get_stats_path() + { + const auto current_mod = get_mod_basename(); + if (!current_mod.has_value()) + { + return {}; + } + + const auto path = utils::properties::get_appdata_path() / + "player/modstats" / (current_mod.value() + ".json"); + return {path.generic_string()}; + } + + nlohmann::json default_mod_stats() + { + nlohmann::json json; + json["maps"] = {}; + return json; + } + + nlohmann::json verify_mod_stats(nlohmann::json& json) + { + if (!json.is_object()) + { + json = {}; + } + + if (!json.contains("maps") || !json["maps"].is_object()) + { + json["maps"] = {}; + } + + return json; + } + + nlohmann::json parse_mod_stats() + { + const auto stats_file = get_stats_path(); + if (!stats_file.has_value()) + { + return default_mod_stats(); + } + + const auto& stats_file_value = stats_file.value(); + if (!utils::io::file_exists(stats_file_value)) + { + return default_mod_stats(); + } + + const auto data = utils::io::read_file(stats_file_value); + try + { + auto json = nlohmann::json::parse(data); + return verify_mod_stats(json); + } + catch (const std::exception& e) + { + console::error("Failed to parse json mod stats file \"%s\": %s", + stats_file_value.data(), e.what()); + } + + return default_mod_stats(); + } + } + + void initialize() + { + globals.modified_stats = false; + globals.current_stats.access([](mod_stats_t& stats) + { + stats = parse_mod_stats(); + }); + } + + utils::concurrency::container& get_stats() + { + return globals.current_stats; + } + + void set_modified() + { + globals.modified_stats = true; + } + + void write() + { + const auto path = get_stats_path(); + if (!path.has_value()) + { + return; + } + + console::debug("[Mod stats] writing stats\n"); + globals.current_stats.access([&](mod_stats_t& stats) + { + const auto dump = stats.dump(4); + const auto& path_value = path.value(); + utils::io::write_file(path_value, dump, false); + globals.modified_stats = false; + }); + } + + nlohmann::json get(const std::string& key, const nlohmann::json& default_value) + { + return get_stats().access([&](mod_stats_t& stats) + -> nlohmann::json + { + if (!stats.is_object() || stats[key].is_null()) + { + return default_value; + } + + return stats[key]; + }); + } + + nlohmann::json get_all() + { + return get_stats().access([&](mod_stats_t& stats) + -> nlohmann::json + { + return stats; + }); + } + + nlohmann::json get_struct(const std::string& name, const std::string& field, const nlohmann::json& default_value) + { + return get_stats().access([&](mod_stats_t& stats) + -> nlohmann::json + { + if (!stats.is_object() || !stats[name].is_object() || stats[name].is_null()) + { + return default_value; + } + + return stats[name][field]; + }); + } + + void set(const std::string& key, const nlohmann::json& value) + { + get_stats().access([&](mod_stats_t& stats) + { + stats[key] = value; + set_modified(); + }); + } + + void set_struct(const std::string& name, const std::string& field, const nlohmann::json& value) + { + get_stats().access([&](mod_stats_t& stats) + { + stats[name][field] = value; + set_modified(); + }); + } + + void set_all(const nlohmann::json& value) + { + get_stats().access([&](mod_stats_t& stats) + { + stats = value; + set_modified(); + }); + } + + class component final : public component_interface + { + public: + void post_unpack() override + { + globals.stats_write_thread = utils::thread::create_named_thread("Stats Write (H2-Mod)", []() + { + while (!globals.kill_thread) + { + const auto _0 = gsl::finally([] + { + std::this_thread::sleep_for(50ms); + }); + + if (!globals.modified_stats) + { + continue; + } + + write(); + } + }); + } + + void pre_destroy() override + { + globals.kill_thread = true; + if (globals.stats_write_thread.joinable()) + { + globals.stats_write_thread.join(); + } + } + }; +} + +REGISTER_COMPONENT(mod_stats::component) diff --git a/src/client/component/mod_stats.hpp b/src/client/component/mod_stats.hpp new file mode 100644 index 00000000..957b9d11 --- /dev/null +++ b/src/client/component/mod_stats.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include + +namespace mod_stats +{ + using mod_stats_t = nlohmann::ordered_json; + utils::concurrency::container& get_stats(); + + void initialize(); + void set_modified(); + void write(); + + nlohmann::json get(const std::string& key, const nlohmann::json& default_value = {}); + nlohmann::json get_struct(const std::string& name, const std::string& field, const nlohmann::json& default_value = {}); + nlohmann::json get_all(); + + void set(const std::string& key, const nlohmann::json& value); + void set_struct(const std::string& name, const std::string& field, const nlohmann::json& value); + void set_all(const nlohmann::json& value); +} diff --git a/src/client/component/mods.cpp b/src/client/component/mods.cpp index 49328546..776ca429 100644 --- a/src/client/component/mods.cpp +++ b/src/client/component/mods.cpp @@ -9,11 +9,13 @@ #include "filesystem.hpp" #include "fonts.hpp" #include "mods.hpp" +#include "mod_stats.hpp" #include "loadscreen.hpp" #include #include #include +#include #define MOD_FOLDER "mods" #define MOD_STATS_FOLDER "players2/modstats" @@ -174,97 +176,6 @@ namespace mods } } } - - std::optional get_mod_basename() - { - const auto mod = get_mod(); - if (!mod.has_value()) - { - return {}; - } - - const auto& value = mod.value(); - const auto last_index = value.find_last_of('/'); - const auto basename = value.substr(last_index + 1); - return {basename}; - } - - nlohmann::json default_mod_stats() - { - nlohmann::json json; - json["maps"] = {}; - return json; - } - - nlohmann::json verify_mod_stats(nlohmann::json& json) - { - if (!json.is_object()) - { - json = {}; - } - - if (!json.contains("maps") || !json["maps"].is_object()) - { - json["maps"] = {}; - } - - return json; - } - - nlohmann::json parse_mod_stats() - { - const auto name = get_mod_basename(); - if (!name.has_value()) - { - return default_mod_stats(); - } - - const auto& name_value = name.value(); - const auto stat_file = MOD_STATS_FOLDER "/" + name_value + ".json"; - if (!utils::io::file_exists(stat_file)) - { - return default_mod_stats(); - } - - const auto data = utils::io::read_file(stat_file); - try - { - auto json = nlohmann::json::parse(data); - return verify_mod_stats(json); - } - catch (const std::exception& e) - { - console::error("Failed to parse json mod stat file \"%s.json\": %s", - name_value.data(), e.what()); - } - - return default_mod_stats(); - } - - void initialize_stats() - { - get_current_stats() = parse_mod_stats(); - } - } - - nlohmann::json& get_current_stats() - { - static nlohmann::json stats; - stats = verify_mod_stats(stats); - return stats; - } - - void write_mod_stats() - { - const auto name = get_mod_basename(); - if (!name.has_value()) - { - return; - } - - const auto& name_value = name.value(); - const auto stat_file = MOD_STATS_FOLDER "/" + name_value + ".json"; - utils::io::write_file(stat_file, get_current_stats().dump(), false); } bool mod_requires_restart(const std::string& path) @@ -281,9 +192,9 @@ namespace mods filesystem::unregister_path(mod_info.path.value()); } - write_mod_stats(); - initialize_stats(); + mod_stats::write(); mod_info.path = path; + mod_stats::initialize(); filesystem::register_path(path); parse_mod_zones(); } diff --git a/src/client/component/mods.hpp b/src/client/component/mods.hpp index 77e3eacf..e0be23a8 100644 --- a/src/client/component/mods.hpp +++ b/src/client/component/mods.hpp @@ -34,7 +34,4 @@ namespace mods std::vector get_mod_list(); std::optional get_mod_info(const std::string& mod); bool mod_exists(const std::string& folder); - - nlohmann::json& get_current_stats(); - void write_mod_stats(); } \ No newline at end of file diff --git a/src/client/component/scripting.cpp b/src/client/component/scripting.cpp index a5c409f9..d9c25ede 100644 --- a/src/client/component/scripting.cpp +++ b/src/client/component/scripting.cpp @@ -7,6 +7,7 @@ #include "scheduler.hpp" #include "scripting.hpp" #include "console.hpp" +#include "command.hpp" #include "gsc/script_loading.hpp" @@ -173,6 +174,7 @@ namespace scripting void add_function_sort(unsigned int id, const char* pos) { + std::string filename = current_file; if (current_file_id) { @@ -369,6 +371,12 @@ namespace scripting utils::hook::call(0x1404B07D2, get_spawn_point_stub); + command::add("getfunctionptr", [](const command::params& params) + { + const auto func = find_function(params.get(1), false); + console::info("%p\n", func); + }); + scheduler::loop([]() { lua::engine::run_frame(); diff --git a/src/client/component/ui_scripting.cpp b/src/client/component/ui_scripting.cpp index ccfabad4..484b9428 100644 --- a/src/client/component/ui_scripting.cpp +++ b/src/client/component/ui_scripting.cpp @@ -11,6 +11,7 @@ #include "scripting.hpp" #include "fastfiles.hpp" #include "mods.hpp" +#include "mod_stats.hpp" #include "updater.hpp" #include "console.hpp" #include "language.hpp" @@ -505,41 +506,37 @@ namespace ui_scripting mods_stats_table["set"] = [](const std::string& key, const script_value& value) { const auto json_value = lua_to_json(value); - mods::get_current_stats()[key] = json_value; - mods::write_mod_stats(); + mod_stats::set(key, json_value); }; mods_stats_table["get"] = [](const std::string& key) { - return json_to_lua(mods::get_current_stats()); + return json_to_lua(mod_stats::get(key)); }; - mods_stats_table["mapset"] = [](const std::string& mapname, + mods_stats_table["setstruct"] = [](const std::string& mapname, const std::string& key, const script_value& value) { const auto json_value = lua_to_json(value); - auto& stats = mods::get_current_stats(); - stats["maps"][mapname][key] = json_value; - mods::write_mod_stats(); + mod_stats::set_struct(mapname, key, json_value); }; - mods_stats_table["mapget"] = [](const std::string& mapname, + mods_stats_table["getstruct"] = [](const std::string& mapname, const std::string& key) { - auto& stats = mods::get_current_stats(); - return json_to_lua(stats["maps"][mapname][key]); + return json_to_lua(mod_stats::get_struct(mapname, key)); }; - mods_stats_table["save"] = mods::write_mod_stats; + mods_stats_table["save"] = mod_stats::write; mods_stats_table["getall"] = []() { - return json_to_lua(mods::get_current_stats()); + return json_to_lua(mod_stats::get_all()); }; mods_stats_table["setfromjson"] = [](const std::string& data) { const auto json = nlohmann::json::parse(data); - mods::get_current_stats() = json; + mod_stats::set_all(json); }; auto config_table = table(); @@ -742,6 +739,11 @@ namespace ui_scripting lua["table"]["unpack"] = lua["unpack"]; lua["luiglobals"] = lua; + lua["printmemoryusage"] = []() + { + utils::hook::invoke(0x14031F470); + }; + load_script("lui_common", lui_common); load_script("lui_updater", lui_updater); load_script("lua_json", lua_json); diff --git a/src/client/game/scripting/lua/context.cpp b/src/client/game/scripting/lua/context.cpp index 44de5fca..e207ce2c 100644 --- a/src/client/game/scripting/lua/context.cpp +++ b/src/client/game/scripting/lua/context.cpp @@ -12,6 +12,7 @@ #include "component/mods.hpp" #include "component/scheduler.hpp" #include "component/filesystem.hpp" +#include "component/gui/debug.hpp" #include "component/gsc/script_loading.hpp" @@ -478,6 +479,64 @@ namespace scripting::lua return sol::as_returns(returns); }; } + + void setup_debug_funcs(sol::state& state) + { + struct debug + { + }; + auto debug_type = state.new_usertype("debug_"); + state["debug"] = debug(); + + debug_type["reset"] = [](const debug&) + { + gui::debug::reset_debug_items(); + }; + + debug_type["addline"] = [](const debug&, const vector& start, const vector& end, const vector& color) + { + float color_[4]{}; + color_[0] = color[0]; + color_[1] = color[1]; + color_[2] = color[2]; + color_[3] = 1.f; + + return gui::debug::add_debug_line(start, end, color_); + }; + + debug_type["addsquare"] = [](const debug&, const vector& origin, const vector& color) + { + float color_[4]{}; + color_[0] = color[0]; + color_[1] = color[1]; + color_[2] = color[2]; + color_[3] = 1.f; + + return gui::debug::add_debug_square(origin, color_); + }; + + debug_type["setsquarecolor"] = [](const debug&, const size_t& square, const vector& color) + { + float color_[4]{}; + color_[0] = color[0]; + color_[1] = color[1]; + color_[2] = color[2]; + color_[3] = 1.f; + + gui::debug::set_debug_square_color(square, color_); + }; + + debug_type["setlinecolor"] = [](const debug&, const size_t& line, const vector& color) + { + float color_[4]{}; + color_[0] = color[0]; + color_[1] = color[1]; + color_[2] = color[2]; + color_[3] = 1.f; + + gui::debug::set_debug_line_color(line, color_); + }; + } void setup_game_type(sol::state& state, event_handler& handler, scheduler& scheduler) { @@ -793,14 +852,6 @@ namespace scripting::lua scripting::get_dvar_int_overrides.erase(dvar); }; - game_type["luinotify"] = [](const game&, const std::string& name, const std::string& data) - { - ::scheduler::once([=]() - { - ui_scripting::notify(name, {{"data", data}}); - }, ::scheduler::pipeline::lui); - }; - auto function_ptr_type = state.new_usertype("functionptr", sol::constructors()); @@ -845,6 +896,7 @@ namespace scripting::lua setup_io(this->state_); setup_json(this->state_); setup_vector_type(this->state_); + setup_debug_funcs(this->state_); setup_entity_type(this->state_, this->event_handler_, this->scheduler_); setup_game_type(this->state_, this->event_handler_, this->scheduler_); @@ -877,6 +929,7 @@ namespace scripting::lua setup_io(this->state_); setup_json(this->state_); setup_vector_type(this->state_); + setup_debug_funcs(this->state_); setup_entity_type(this->state_, this->event_handler_, this->scheduler_); setup_game_type(this->state_, this->event_handler_, this->scheduler_); }