Skip to content

Commit

Permalink
Lua: Display errors in LuaLoader menu
Browse files Browse the repository at this point in the history
  • Loading branch information
praydog committed Oct 17, 2024
1 parent 4559bbe commit 2bea95c
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 55 deletions.
34 changes: 27 additions & 7 deletions lua-api/lib/include/ScriptContext.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,13 @@ class ScriptContext : public std::enable_shared_from_this<ScriptContext> {
}

static void log(const std::string& message);
void log_error(const std::string& message) {
log(message);

std::unique_lock _{m_script_error_mutex};
m_last_script_error_state.e = message;
m_last_script_error_state.t = std::chrono::system_clock::now();
}

template<typename T1, typename T2>
void add_callback(T1&& adder, T2&& cb) {
Expand All @@ -75,7 +82,7 @@ class ScriptContext : public std::enable_shared_from_this<ScriptContext> {
for (auto& cb : m_on_script_reset_callbacks) try {
handle_protected_result(cb());
} catch (const std::exception& e) {
log("Exception in on_script_reset: " + std::string(e.what()));
log_error("Exception in on_script_reset: " + std::string(e.what()));
} catch (...) {
log("Unknown exception in on_script_reset");
}
Expand All @@ -87,9 +94,9 @@ class ScriptContext : public std::enable_shared_from_this<ScriptContext> {
for (auto& cb : m_on_frame_callbacks) try {
handle_protected_result(cb());
} catch (const std::exception& e) {
log("Exception in on_frame: " + std::string(e.what()));
log_error("Exception in on_frame: " + std::string(e.what()));
} catch (...) {
log("Unknown exception in on_frame");
log_error("Unknown exception in on_frame");
}
}

Expand All @@ -99,9 +106,9 @@ class ScriptContext : public std::enable_shared_from_this<ScriptContext> {
for (auto& cb : m_on_draw_ui_callbacks) try {
handle_protected_result(cb());
} catch (const std::exception& e) {
log("Exception in on_draw_ui: " + std::string(e.what()));
log_error("Exception in on_draw_ui: " + std::string(e.what()));
} catch (...) {
log("Unknown exception in on_draw_ui");
log_error("Unknown exception in on_draw_ui");
}
}

Expand All @@ -111,12 +118,22 @@ class ScriptContext : public std::enable_shared_from_this<ScriptContext> {
for (auto& cb : m_on_lua_event_callbacks) try {
handle_protected_result(cb(event_name, event_data));
} catch (const std::exception& e) {
log("Exception in on_lua_event: " + std::string(e.what()));
log_error("Exception in on_lua_event: " + std::string(e.what()));
} catch (...) {
log("Unknown exception in on_lua_event");
log_error("Unknown exception in on_lua_event");
}
}

struct ScriptErrorState {
std::string e{};
std::chrono::system_clock::time_point t{};
};

auto get_last_script_error() const {
std::shared_lock _{m_script_error_mutex};
return m_last_script_error_state;
}

private:
// Private constructor to prevent direct instantiation
ScriptContext(lua_State* l, UEVR_PluginInitializeParam* param = nullptr);
Expand All @@ -127,6 +144,9 @@ class ScriptContext : public std::enable_shared_from_this<ScriptContext> {

sol::state_view m_lua;
std::shared_ptr<sol::state> m_lua_shared{}; // This allows us to keep the state alive (if it was created by ScriptState)
ScriptErrorState m_last_script_error_state{};
mutable std::shared_mutex m_script_error_mutex{};

std::recursive_mutex m_mtx{};
UEVR_PluginInitializeParam* m_plugin_initialize_param{nullptr};
std::vector<sol::protected_function> m_on_xinput_get_state_callbacks{};
Expand Down
8 changes: 8 additions & 0 deletions lua-api/lib/include/ScriptState.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,14 @@ class ScriptState {
return m_context;
}

std::optional<ScriptContext::ScriptErrorState> get_last_script_error() const {
if (m_context != nullptr) {
return m_context->get_last_script_error();
}

return std::nullopt;
}

auto& lua() { return m_lua; }

private:
Expand Down
74 changes: 38 additions & 36 deletions lua-api/lib/src/ScriptContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,10 @@ ScriptContext::~ScriptContext() {
}

void ScriptContext::log(const std::string& message) {
std::cout << "[LuaVR] " << message << std::endl;
API::get()->log_info("[LuaVR] %s", message.c_str());
auto msg = std::format("[LuaVR] {}", message);
OutputDebugStringA((msg + "\n").c_str());
fprintf(stderr, "%s\n", msg.c_str());
API::get()->log_info("%s", msg.c_str());
}

void ScriptContext::setup_callback_bindings() {
Expand Down Expand Up @@ -830,9 +832,9 @@ bool ScriptContext::global_ufunction_pre_handler(uevr::API::UFunction* fn, uevr:
any_false = true;
}
} catch (const std::exception& e) {
ScriptContext::log("Exception in global_ufunction_pre_handler: " + std::string(e.what()));
ctx->log_error("Exception in global_ufunction_pre_handler: " + std::string(e.what()));
} catch (...) {
ScriptContext::log("Unknown exception in global_ufunction_pre_handler");
ctx->log_error("Unknown exception in global_ufunction_pre_handler");
}
}
});
Expand All @@ -855,9 +857,9 @@ void ScriptContext::global_ufunction_post_handler(uevr::API::UFunction* fn, uevr
for (auto& cb : it->second->post_hooks) try {
ctx->handle_protected_result(cb(fn, obj, locals_obj, result));
} catch (const std::exception& e) {
ScriptContext::log("Exception in global_ufunction_post_handler: " + std::string(e.what()));
ctx->log_error("Exception in global_ufunction_post_handler: " + std::string(e.what()));
} catch (...) {
ScriptContext::log("Unknown exception in global_ufunction_post_handler");
ctx->log_error("Unknown exception in global_ufunction_post_handler");
}
}
});
Expand All @@ -870,9 +872,9 @@ void ScriptContext::on_xinput_get_state(uint32_t* retval, uint32_t user_index, v
for (auto& fn : ctx->m_on_xinput_get_state_callbacks) try {
ctx->handle_protected_result(fn(retval, user_index, (XINPUT_STATE*)state));
} catch (const std::exception& e) {
ScriptContext::log("Exception in on_xinput_get_state: " + std::string(e.what()));
ctx->log_error("Exception in on_xinput_get_state: " + std::string(e.what()));
} catch (...) {
ScriptContext::log("Unknown exception in on_xinput_get_state");
ctx->log_error("Unknown exception in on_xinput_get_state");
}
});
}
Expand All @@ -884,9 +886,9 @@ void ScriptContext::on_xinput_set_state(uint32_t* retval, uint32_t user_index, v
for (auto& fn : ctx->m_on_xinput_set_state_callbacks) try {
ctx->handle_protected_result(fn(retval, user_index, (XINPUT_VIBRATION*)vibration));
} catch (const std::exception& e) {
ScriptContext::log("Exception in on_xinput_set_state: " + std::string(e.what()));
ctx->log_error("Exception in on_xinput_set_state: " + std::string(e.what()));
} catch (...) {
ScriptContext::log("Unknown exception in on_xinput_set_state");
ctx->log_error("Unknown exception in on_xinput_set_state");
}
});
}
Expand All @@ -898,9 +900,9 @@ void ScriptContext::on_pre_engine_tick(UEVR_UGameEngineHandle engine, float delt
for (auto& fn : ctx->m_on_pre_engine_tick_callbacks) try {
ctx->handle_protected_result(fn(engine, delta_seconds));
} catch (const std::exception& e) {
ScriptContext::log("Exception in on_pre_engine_tick: " + std::string(e.what()));
ctx->log_error("Exception in on_pre_engine_tick: " + std::string(e.what()));
} catch (...) {
ScriptContext::log("Unknown exception in on_pre_engine_tick");
ctx->log_error("Unknown exception in on_pre_engine_tick");
}
});
}
Expand All @@ -912,9 +914,9 @@ void ScriptContext::on_post_engine_tick(UEVR_UGameEngineHandle engine, float del
for (auto& fn : ctx->m_on_post_engine_tick_callbacks) try {
ctx->handle_protected_result(fn(engine, delta_seconds));
} catch (const std::exception& e) {
ScriptContext::log("Exception in on_post_engine_tick: " + std::string(e.what()));
ctx->log_error("Exception in on_post_engine_tick: " + std::string(e.what()));
} catch (...) {
ScriptContext::log("Unknown exception in on_post_engine_tick");
ctx->log_error("Unknown exception in on_post_engine_tick");
}
});
}
Expand All @@ -926,9 +928,9 @@ void ScriptContext::on_pre_slate_draw_window_render_thread(UEVR_FSlateRHIRendere
for (auto& fn : ctx->m_on_pre_slate_draw_window_render_thread_callbacks) try {
ctx->handle_protected_result(fn(renderer, viewport_info));
} catch (const std::exception& e) {
ScriptContext::log("Exception in on_pre_slate_draw_window_render_thread: " + std::string(e.what()));
ctx->log_error("Exception in on_pre_slate_draw_window_render_thread: " + std::string(e.what()));
} catch (...) {
ScriptContext::log("Unknown exception in on_pre_slate_draw_window_render_thread");
ctx->log_error("Unknown exception in on_pre_slate_draw_window_render_thread");
}
});
}
Expand All @@ -940,9 +942,9 @@ void ScriptContext::on_post_slate_draw_window_render_thread(UEVR_FSlateRHIRender
for (auto& fn : ctx->m_on_post_slate_draw_window_render_thread_callbacks) try {
ctx->handle_protected_result(fn(renderer, viewport_info));
} catch (const std::exception& e) {
ScriptContext::log("Exception in on_post_slate_draw_window_render_thread: " + std::string(e.what()));
ctx->log_error("Exception in on_post_slate_draw_window_render_thread: " + std::string(e.what()));
} catch (...) {
ScriptContext::log("Unknown exception in on_post_slate_draw_window_render_thread");
ctx->log_error("Unknown exception in on_post_slate_draw_window_render_thread");
}
});
}
Expand Down Expand Up @@ -970,9 +972,9 @@ void ScriptContext::on_early_calculate_stereo_view_offset(UEVR_StereoRenderingDe
ctx->handle_protected_result(fn(device, view_index, world_to_meters, ue4_position, ue4_rotation, is_double));
}
} catch (const std::exception& e) {
ScriptContext::log("Exception in on_early_calculate_stereo_view_offset: " + std::string(e.what()));
ctx->log_error("Exception in on_early_calculate_stereo_view_offset: " + std::string(e.what()));
} catch (...) {
ScriptContext::log("Unknown exception in on_early_calculate_stereo_view_offset");
ctx->log_error("Unknown exception in on_early_calculate_stereo_view_offset");
}
});
}
Expand Down Expand Up @@ -1000,9 +1002,9 @@ void ScriptContext::on_pre_calculate_stereo_view_offset(UEVR_StereoRenderingDevi
ctx->handle_protected_result(fn(device, view_index, world_to_meters, ue4_position, ue4_rotation, is_double));
}
} catch (const std::exception& e) {
ScriptContext::log("Exception in on_pre_calculate_stereo_view_offset: " + std::string(e.what()));
ctx->log_error("Exception in on_pre_calculate_stereo_view_offset: " + std::string(e.what()));
} catch (...) {
ScriptContext::log("Unknown exception in on_pre_calculate_stereo_view_offset");
ctx->log_error("Unknown exception in on_pre_calculate_stereo_view_offset");
}
});
}
Expand Down Expand Up @@ -1030,9 +1032,9 @@ void ScriptContext::on_post_calculate_stereo_view_offset(UEVR_StereoRenderingDev
ctx->handle_protected_result(fn(device, view_index, world_to_meters, ue4_position, ue4_rotation, is_double));
}
} catch (const std::exception& e) {
ScriptContext::log("Exception in on_post_calculate_stereo_view_offset: " + std::string(e.what()));
ctx->log_error("Exception in on_post_calculate_stereo_view_offset: " + std::string(e.what()));
} catch (...) {
ScriptContext::log("Unknown exception in on_post_calculate_stereo_view_offset");
ctx->log_error("Unknown exception in on_post_calculate_stereo_view_offset");
}
});
}
Expand All @@ -1044,9 +1046,9 @@ void ScriptContext::on_pre_viewport_client_draw(UEVR_UGameViewportClientHandle v
for (auto& fn : ctx->m_on_pre_viewport_client_draw_callbacks) try {
ctx->handle_protected_result(fn(viewport_client, viewport, canvas));
} catch (const std::exception& e) {
ScriptContext::log("Exception in on_pre_viewport_client_draw: " + std::string(e.what()));
ctx->log_error("Exception in on_pre_viewport_client_draw: " + std::string(e.what()));
} catch (...) {
ScriptContext::log("Unknown exception in on_pre_viewport_client_draw");
ctx->log_error("Unknown exception in on_pre_viewport_client_draw");
}
});
}
Expand All @@ -1058,9 +1060,9 @@ void ScriptContext::on_post_viewport_client_draw(UEVR_UGameViewportClientHandle
for (auto& fn : ctx->m_on_post_viewport_client_draw_callbacks) try {
ctx->handle_protected_result(fn(viewport_client, viewport, canvas));
} catch (const std::exception& e) {
ScriptContext::log("Exception in on_post_viewport_client_draw: " + std::string(e.what()));
ctx->log_error("Exception in on_post_viewport_client_draw: " + std::string(e.what()));
} catch (...) {
ScriptContext::log("Unknown exception in on_post_viewport_client_draw");
ctx->log_error("Unknown exception in on_post_viewport_client_draw");
}
});
}
Expand All @@ -1072,9 +1074,9 @@ void ScriptContext::on_frame() {
for (auto& fn : ctx->m_on_frame_callbacks) try {
ctx->handle_protected_result(fn());
} catch (const std::exception& e) {
ScriptContext::log("Exception in on_frame: " + std::string(e.what()));
ctx->log_error("Exception in on_frame: " + std::string(e.what()));
} catch (...) {
ScriptContext::log("Unknown exception in on_frame");
ctx->log_error("Unknown exception in on_frame");
}
});
}
Expand All @@ -1086,9 +1088,9 @@ void ScriptContext::on_draw_ui() {
for (auto& fn : ctx->m_on_draw_ui_callbacks) try {
ctx->handle_protected_result(fn());
} catch (const std::exception& e) {
ScriptContext::log("Exception in on_draw_ui: " + std::string(e.what()));
ctx->log_error("Exception in on_draw_ui: " + std::string(e.what()));
} catch (...) {
ScriptContext::log("Unknown exception in on_draw_ui");
ctx->log_error("Unknown exception in on_draw_ui");
}
});
}
Expand All @@ -1100,9 +1102,9 @@ void ScriptContext::on_script_reset() {
for (auto& fn : ctx->m_on_script_reset_callbacks) try {
ctx->handle_protected_result(fn());
} catch (const std::exception& e) {
ScriptContext::log("Exception in on_script_reset: " + std::string(e.what()));
ctx->log_error("Exception in on_script_reset: " + std::string(e.what()));
} catch (...) {
ScriptContext::log("Unknown exception in on_script_reset");
ctx->log_error("Unknown exception in on_script_reset");
}
});
}
Expand All @@ -1117,9 +1119,9 @@ void ScriptContext::on_lua_event(std::string_view event_name, std::string_view e
for (auto& fn : ctx->m_on_lua_event_callbacks) try {
ctx->handle_protected_result(fn(event_name_data, event_data_data));
} catch (const std::exception& e) {
ScriptContext::log("Exception in on_lua_event: " + std::string(e.what()));
ctx->log_error("Exception in on_lua_event: " + std::string(e.what()));
} catch (...) {
ScriptContext::log("Unknown exception in on_lua_event");
ctx->log_error("Unknown exception in on_lua_event");
}
});
}
Expand Down
13 changes: 4 additions & 9 deletions src/mods/LuaLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,17 +171,17 @@ void LuaLoader::on_draw_sidebar_entry(std::string_view in_entry) {

m_log_to_disk->draw("Log Lua Errors to Disk");

if (!m_last_script_error.empty()) {
std::shared_lock _{m_script_error_mutex};
auto last_script_error = m_main_state != nullptr ? m_main_state->get_last_script_error() : std::nullopt;

if (last_script_error.has_value() && !last_script_error->e.empty()) {
const auto now = std::chrono::system_clock::now();
const auto diff = now - m_last_script_error_time;
const auto diff = now - last_script_error->t;
const auto sec = std::chrono::duration<float>(diff).count();

ImGui::TextWrapped("Last Error Time: %.2f seconds ago", sec);

ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.0f, 0.0f, 1.0f));
ImGui::TextWrapped("Last Script Error: %s", m_last_script_error.data());
ImGui::TextWrapped("Last Script Error: %s", last_script_error->e.c_str());
ImGui::PopStyleColor();
} else {
ImGui::TextWrapped("No Script Errors... yet!");
Expand Down Expand Up @@ -224,11 +224,6 @@ void LuaLoader::reset_scripts() {

std::scoped_lock _{ m_access_mutex };

{
std::unique_lock _{ m_script_error_mutex };
m_last_script_error.clear();
}

if (m_main_state != nullptr) {
/*auto& mods = g_framework->get_mods()->get_mods();
Expand Down
3 changes: 0 additions & 3 deletions src/mods/LuaLoader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,6 @@ class LuaLoader : public Mod {
std::vector<std::string> m_known_scripts{};
std::unordered_map<std::string, bool> m_loaded_scripts_map{};
std::vector<lua_State*> m_states_to_delete{};
std::string m_last_script_error{};
std::shared_mutex m_script_error_mutex{};
std::chrono::system_clock::time_point m_last_script_error_time{};

bool m_console_spawned{false};
bool m_needs_first_reset{true};
Expand Down

0 comments on commit 2bea95c

Please sign in to comment.