mirror of
https://github.com/Mr-X-GTA/YimMenu.git
synced 2025-01-03 16:13:36 +08:00
fix(lua): better exception handling (#1734)
This commit is contained in:
parent
8d01f497e7
commit
0417fbf0f9
@ -88,7 +88,7 @@ namespace lua::event
|
|||||||
// Param: menu_event: menu_event: The menu_event that we want to respond to.
|
// Param: menu_event: menu_event: The menu_event that we want to respond to.
|
||||||
// Param: func: function: The function that will be called.
|
// Param: func: function: The function that will be called.
|
||||||
// Register a function that will be called each time the corresponding menu_event is triggered.
|
// Register a function that will be called each time the corresponding menu_event is triggered.
|
||||||
static void register_handler(const menu_event& menu_event, sol::function func, sol::this_state state)
|
static void register_handler(const menu_event& menu_event, sol::protected_function func, sol::this_state state)
|
||||||
{
|
{
|
||||||
const auto module = sol::state_view(state)["!this"].get<big::lua_module*>();
|
const auto module = sol::state_view(state)["!this"].get<big::lua_module*>();
|
||||||
|
|
||||||
|
@ -166,7 +166,7 @@ namespace lua::gui
|
|||||||
// Param: name: string: Text written inside the button.
|
// Param: name: string: Text written inside the button.
|
||||||
// Param: callback: function: function that will be called when the button is clicked.
|
// Param: callback: function: function that will be called when the button is clicked.
|
||||||
// Add a button to the gui tab.
|
// Add a button to the gui tab.
|
||||||
std::shared_ptr<lua::gui::button> add_button(const std::string& name, sol::function callback, sol::this_state state)
|
std::shared_ptr<lua::gui::button> add_button(const std::string& name, sol::protected_function callback, sol::this_state state)
|
||||||
{
|
{
|
||||||
auto element = std::make_shared<lua::gui::button>(name, callback);
|
auto element = std::make_shared<lua::gui::button>(name, callback);
|
||||||
add_element(state, m_tab_hash, element);
|
add_element(state, m_tab_hash, element);
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
namespace lua::gui
|
namespace lua::gui
|
||||||
{
|
{
|
||||||
button::button(std::string text, sol::function callback) :
|
button::button(std::string text, sol::protected_function callback) :
|
||||||
base_text_element(text),
|
base_text_element(text),
|
||||||
m_callback(callback)
|
m_callback(callback)
|
||||||
{
|
{
|
||||||
|
@ -10,11 +10,11 @@ namespace lua::gui
|
|||||||
// Class representing a gui button.
|
// Class representing a gui button.
|
||||||
class button : public base_text_element
|
class button : public base_text_element
|
||||||
{
|
{
|
||||||
sol::function m_callback;
|
sol::protected_function m_callback;
|
||||||
bool m_execute_in_fiber_pool = true;
|
bool m_execute_in_fiber_pool = true;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
button(std::string text, sol::function callback);
|
button(std::string text, sol::protected_function callback);
|
||||||
|
|
||||||
void draw() override;
|
void draw() override;
|
||||||
};
|
};
|
||||||
|
@ -70,14 +70,13 @@ namespace lua::script
|
|||||||
// ENTITY.DELETE_ENTITY(spawnedVehicle)
|
// ENTITY.DELETE_ENTITY(spawnedVehicle)
|
||||||
// end)
|
// end)
|
||||||
// ```
|
// ```
|
||||||
static void register_looped(const std::string& name, sol::function func_, sol::this_state state)
|
static void register_looped(const std::string& name, sol::protected_function func_, sol::this_state state)
|
||||||
{
|
{
|
||||||
auto module = sol::state_view(state)["!this"].get<big::lua_module*>();
|
auto module = sol::state_view(state)["!this"].get<big::lua_module*>();
|
||||||
|
|
||||||
std::unique_ptr<big::script> lua_script = std::make_unique<big::script>(
|
std::unique_ptr<big::script> lua_script = std::make_unique<big::script>(
|
||||||
[func_, state]() mutable {
|
[func_, state]() mutable {
|
||||||
|
sol::thread t = sol::thread::create(state);
|
||||||
sol::thread t = sol::thread::create(state);
|
|
||||||
sol::coroutine func = sol::coroutine(t.state(), func_);
|
sol::coroutine func = sol::coroutine(t.state(), func_);
|
||||||
|
|
||||||
while (big::g_running)
|
while (big::g_running)
|
||||||
@ -97,8 +96,7 @@ namespace lua::script
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
name
|
name);
|
||||||
);
|
|
||||||
|
|
||||||
const auto registered_script = big::g_script_mgr.add_script(std::move(lua_script));
|
const auto registered_script = big::g_script_mgr.add_script(std::move(lua_script));
|
||||||
|
|
||||||
@ -115,25 +113,25 @@ namespace lua::script
|
|||||||
// script.run_in_fiber(function (script)
|
// script.run_in_fiber(function (script)
|
||||||
// -- sleep until next game frame
|
// -- sleep until next game frame
|
||||||
// script:yield()
|
// script:yield()
|
||||||
//
|
//
|
||||||
// local ModelHash = joaat("adder")
|
// local ModelHash = joaat("adder")
|
||||||
// if not STREAMING.IS_MODEL_IN_CDIMAGE(ModelHash) then return end
|
// if not STREAMING.IS_MODEL_IN_CDIMAGE(ModelHash) then return end
|
||||||
// STREAMING.REQUEST_MODEL(ModelHash) -- Request the model
|
// STREAMING.REQUEST_MODEL(ModelHash) -- Request the model
|
||||||
// while not STREAMING.HAS_MODEL_LOADED(ModelHash) do -- Waits for the model to load
|
// while not STREAMING.HAS_MODEL_LOADED(ModelHash) do -- Waits for the model to load
|
||||||
// script:yield()
|
// script:yield()
|
||||||
// end
|
// end
|
||||||
// local myPed = PLAYER.PLAYER_PED_ID()
|
// local myPed = PLAYER.PLAYER_PED_ID()
|
||||||
// local myCoords = ENTITY.GET_ENTITY_COORDS(myPed, true)
|
// local myCoords = ENTITY.GET_ENTITY_COORDS(myPed, true)
|
||||||
// -- Spawns a networked vehicle on your current coords
|
// -- Spawns a networked vehicle on your current coords
|
||||||
// local spawnedVehicle = VEHICLE.CREATE_VEHICLE(ModelHash, myCoords.x, myCoords.y, myCoords.z, ENTITY.GET_ENTITY_HEADING(myPed), true, false)
|
// local spawnedVehicle = VEHICLE.CREATE_VEHICLE(ModelHash, myCoords.x, myCoords.y, myCoords.z, ENTITY.GET_ENTITY_HEADING(myPed), true, false)
|
||||||
// -- removes model from game memory as we no longer need it
|
// -- removes model from game memory as we no longer need it
|
||||||
// STREAMING.SET_MODEL_AS_NO_LONGER_NEEDED(ModelHash)
|
// STREAMING.SET_MODEL_AS_NO_LONGER_NEEDED(ModelHash)
|
||||||
// -- sleep for 2s
|
// -- sleep for 2s
|
||||||
// script:sleep(2000)
|
// script:sleep(2000)
|
||||||
// ENTITY.DELETE_ENTITY(spawnedVehicle)
|
// ENTITY.DELETE_ENTITY(spawnedVehicle)
|
||||||
// end)
|
// end)
|
||||||
// ```
|
// ```
|
||||||
static void run_in_fiber(sol::function func_, sol::this_state state)
|
static void run_in_fiber(sol::protected_function func_, sol::this_state state)
|
||||||
{
|
{
|
||||||
auto module = sol::state_view(state)["!this"].get<big::lua_module*>();
|
auto module = sol::state_view(state)["!this"].get<big::lua_module*>();
|
||||||
|
|
||||||
|
@ -157,7 +157,8 @@ namespace big
|
|||||||
|
|
||||||
void lua_manager::handle_error(const sol::error& error, const sol::state_view& state)
|
void lua_manager::handle_error(const sol::error& error, const sol::state_view& state)
|
||||||
{
|
{
|
||||||
LOG(WARNING) << state["!module_name"].get<std::string_view>() << ": " << error.what();
|
LOG(FATAL) << state["!module_name"].get<std::string_view>() << ": " << error.what();
|
||||||
|
Logger::FlushQueue();
|
||||||
}
|
}
|
||||||
|
|
||||||
void lua_manager::load_all_modules()
|
void lua_manager::load_all_modules()
|
||||||
|
@ -18,30 +18,41 @@
|
|||||||
|
|
||||||
namespace big
|
namespace big
|
||||||
{
|
{
|
||||||
inline int exception_handler(lua_State* L, sol::optional<const std::exception&> exception, std::string_view what)
|
// https://sol2.readthedocs.io/en/latest/exceptions.html
|
||||||
|
int exception_handler(lua_State* L, sol::optional<const std::exception&> maybe_exception, sol::string_view description)
|
||||||
{
|
{
|
||||||
if (exception)
|
// L is the lua state, which you can wrap in a state_view if necessary
|
||||||
LOG(WARNING) << exception->what();
|
// maybe_exception will contain exception, if it exists
|
||||||
|
// description will either be the what() of the exception or a description saying that we hit the general-case catch(...)
|
||||||
|
if (maybe_exception)
|
||||||
|
{
|
||||||
|
const std::exception& ex = *maybe_exception;
|
||||||
|
LOG(FATAL) << ex.what();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
LOG(WARNING) << what;
|
{
|
||||||
|
LOG(FATAL) << description;
|
||||||
|
}
|
||||||
|
Logger::FlushQueue();
|
||||||
|
|
||||||
lua_pushlstring(L, what.data(), what.size());
|
// you must push 1 element onto the stack to be
|
||||||
return 1;
|
// transported through as the error object in Lua
|
||||||
|
// note that Lua -- and 99.5% of all Lua users and libraries -- expects a string
|
||||||
|
// so we push a single string (in our case, the description of the error)
|
||||||
|
return sol::stack::push(L, description);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int panic_handler(lua_State* L)
|
inline void panic_handler(sol::optional<std::string> maybe_msg)
|
||||||
{
|
{
|
||||||
size_t messagesize;
|
LOG(FATAL) << "Lua is in a panic state and will now abort() the application";
|
||||||
const char* message = lua_tolstring(L, -1, &messagesize);
|
if (maybe_msg)
|
||||||
if (message)
|
|
||||||
{
|
{
|
||||||
std::string err(message, messagesize);
|
const std::string& msg = maybe_msg.value();
|
||||||
lua_settop(L, 0);
|
LOG(FATAL) << "error message: " << msg;
|
||||||
LOG(FATAL) << err;
|
|
||||||
}
|
}
|
||||||
lua_settop(L, 0);
|
Logger::FlushQueue();
|
||||||
LOG(FATAL) << "An unexpected error occurred and panic has been invoked";
|
|
||||||
return 1;
|
// When this function exits, Lua will exhibit default behavior and abort()
|
||||||
}
|
}
|
||||||
|
|
||||||
lua_module::lua_module(std::string module_name) :
|
lua_module::lua_module(std::string module_name) :
|
||||||
@ -71,20 +82,18 @@ namespace big
|
|||||||
state["!module_name"] = module_name;
|
state["!module_name"] = module_name;
|
||||||
state["!this"] = this;
|
state["!this"] = this;
|
||||||
|
|
||||||
state.set_exception_handler((sol::exception_handler_function)exception_handler);
|
state.set_exception_handler(exception_handler);
|
||||||
state.set_panic(panic_handler);
|
state.set_panic(sol::c_call<decltype(&panic_handler), &panic_handler>);
|
||||||
|
|
||||||
const auto script_file_path = g_lua_manager->get_scripts_folder().get_file(module_name).get_path();
|
const auto script_file_path = g_lua_manager->get_scripts_folder().get_file(module_name).get_path();
|
||||||
m_last_write_time = std::filesystem::last_write_time(script_file_path);
|
m_last_write_time = std::filesystem::last_write_time(script_file_path);
|
||||||
auto result = state.load_file(script_file_path.string());
|
|
||||||
|
auto result = state.safe_script_file(script_file_path.string(), &sol::script_pass_on_error, sol::load_mode::text);
|
||||||
|
|
||||||
if (!result.valid())
|
if (!result.valid())
|
||||||
{
|
{
|
||||||
LOG(WARNING) << module_name << " failed to load: " << result.get<sol::error>().what();
|
LOG(FATAL) << module_name << " failed to load: " << result.get<sol::error>().what();
|
||||||
}
|
Logger::FlushQueue();
|
||||||
else
|
|
||||||
{
|
|
||||||
result();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,6 +166,7 @@ namespace big
|
|||||||
const auto module = sol::state_view(current_state)["!this"].get<big::lua_module*>();
|
const auto module = sol::state_view(current_state)["!this"].get<big::lua_module*>();
|
||||||
|
|
||||||
LOG(FATAL) << module->module_name() << " tried calling a currently not supported lua function: " << function_name;
|
LOG(FATAL) << module->module_name() << " tried calling a currently not supported lua function: " << function_name;
|
||||||
|
Logger::FlushQueue();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ namespace big
|
|||||||
std::unordered_map<big::tabs, std::vector<big::tabs>> m_tab_to_sub_tabs;
|
std::unordered_map<big::tabs, std::vector<big::tabs>> m_tab_to_sub_tabs;
|
||||||
|
|
||||||
std::unordered_map<rage::joaat_t, std::vector<std::shared_ptr<lua::gui::gui_element>>> m_gui;
|
std::unordered_map<rage::joaat_t, std::vector<std::shared_ptr<lua::gui::gui_element>>> m_gui;
|
||||||
std::unordered_map<menu_event, std::vector<sol::function>> m_event_callbacks;
|
std::unordered_map<menu_event, std::vector<sol::protected_function>> m_event_callbacks;
|
||||||
std::vector<void*> m_allocated_memory;
|
std::vector<void*> m_allocated_memory;
|
||||||
|
|
||||||
lua_module(std::string module_name);
|
lua_module(std::string module_name);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user