diff --git a/vmf/scripts/mods/vmf/modules/core/commands.lua b/vmf/scripts/mods/vmf/modules/core/commands.lua index 459e4fa..c3aa42d 100644 --- a/vmf/scripts/mods/vmf/modules/core/commands.lua +++ b/vmf/scripts/mods/vmf/modules/core/commands.lua @@ -154,7 +154,7 @@ function vmf.run_command(command_name, ...) local command_data = _commands[command_name] if command_data then local error_prefix = "(commands) " .. tostring(command_name) - vmf.xpcall_no_return_values(command_data.mod, error_prefix, command_data.exec_function, ...) + vmf.safe_call_nr(command_data.mod, error_prefix, command_data.exec_function, ...) else vmf:error("(commands): command '%s' wasn't found.", command_name) -- Should never see this end diff --git a/vmf/scripts/mods/vmf/modules/core/events.lua b/vmf/scripts/mods/vmf/modules/core/events.lua index 0ba7c2b..329d864 100644 --- a/vmf/scripts/mods/vmf/modules/core/events.lua +++ b/vmf/scripts/mods/vmf/modules/core/events.lua @@ -10,7 +10,7 @@ local _mods_unloading_order = vmf.mods_unloading_order local function run_event(mod, event_name, ...) local event = mod[event_name] if event then - vmf.xpcall_no_return_values(mod, "(event) " .. event_name, event, ...) + vmf.safe_call_nr(mod, "(event) " .. event_name, event, ...) end end diff --git a/vmf/scripts/mods/vmf/modules/core/hooks.lua b/vmf/scripts/mods/vmf/modules/core/hooks.lua index d083bc1..6233d96 100644 --- a/vmf/scripts/mods/vmf/modules/core/hooks.lua +++ b/vmf/scripts/mods/vmf/modules/core/hooks.lua @@ -164,7 +164,7 @@ local function create_specialized_hook(mod, orig, hook_type) elseif hook_type == HOOK_TYPE_SAFE then func = function(...) if hook_data.active then - vmf.xpcall_no_return_values(mod, "(safe_hook)", hook_data.handler, ...) + vmf.safe_call_nr(mod, "(safe_hook)", hook_data.handler, ...) end end end diff --git a/vmf/scripts/mods/vmf/modules/core/keybindings.lua b/vmf/scripts/mods/vmf/modules/core/keybindings.lua index 17ff342..82a7595 100644 --- a/vmf/scripts/mods/vmf/modules/core/keybindings.lua +++ b/vmf/scripts/mods/vmf/modules/core/keybindings.lua @@ -197,7 +197,7 @@ end local function call_function(mod, function_name, keybind_is_pressed) if type(mod[function_name]) == "function" then local error_prefix = string.format("(keybindings) function_call 'mod.%s'", function_name) - vmf.xpcall_no_return_values(mod, error_prefix, mod[function_name], keybind_is_pressed) + vmf.safe_call_nr(mod, error_prefix, mod[function_name], keybind_is_pressed) else mod:error("(keybindings) function_call 'mod.%s': function was not found.", tostring(function_name)) end diff --git a/vmf/scripts/mods/vmf/modules/core/misc.lua b/vmf/scripts/mods/vmf/modules/core/misc.lua index 8a6a95f..3d45c99 100644 --- a/vmf/scripts/mods/vmf/modules/core/misc.lua +++ b/vmf/scripts/mods/vmf/modules/core/misc.lua @@ -17,19 +17,4 @@ function vmf.check_wrong_argument_type(mod, vmf_function_name, argument_name, ar mod:error("(%s): argument '%s' should have the '%s' type, not '%s'", vmf_function_name, argument_name, table.concat(allowed_types, "/"), argument_type) return true -end - - -function vmf.throw_error(error_message, ...) - error(string.format(error_message, ...), 0) -end - - -function vmf.catch_errors(mod, error_prefix, additional_error_prefix_info, exec_function, ...) - local success, error_message = pcall(exec_function, ...) - if not success then - error_prefix = string.format(error_prefix, additional_error_prefix_info) - mod:error(string.format("%s: %s", error_prefix, error_message)) - return true - end end \ No newline at end of file diff --git a/vmf/scripts/mods/vmf/modules/core/network.lua b/vmf/scripts/mods/vmf/modules/core/network.lua index aa3fdd2..a57a7aa 100644 --- a/vmf/scripts/mods/vmf/modules/core/network.lua +++ b/vmf/scripts/mods/vmf/modules/core/network.lua @@ -176,7 +176,7 @@ local function send_rpc_vmf_data_local(mod_name, rpc_name, ...) network_debug("data", "local", nil, mod_name, rpc_name, {...}) local error_prefix = "(local rpc) " .. tostring(rpc_name) - vmf.xpcall_no_return_values(mod, error_prefix, _rpc_callbacks[mod_name][rpc_name], Network.peer_id(), ...) + vmf.safe_call_nr(mod, error_prefix, _rpc_callbacks[mod_name][rpc_name], Network.peer_id(), ...) end end @@ -307,7 +307,7 @@ vmf:hook("ChatManager", "rpc_chat_message", -- can be error in both callback_function() and deserialize_data() local error_prefix = "(network) " .. tostring(rpc_name) - vmf.xpcall_no_return_values( + vmf.safe_call_nr( get_mod(mod_name), error_prefix, function() _rpc_callbacks[mod_name][rpc_name](sender, deserialize_data(rpc_data2)) end diff --git a/vmf/scripts/mods/vmf/modules/core/safe_calls.lua b/vmf/scripts/mods/vmf/modules/core/safe_calls.lua index f07d52e..d2eaf00 100644 --- a/vmf/scripts/mods/vmf/modules/core/safe_calls.lua +++ b/vmf/scripts/mods/vmf/modules/core/safe_calls.lua @@ -17,17 +17,29 @@ local function print_error_callstack(error_message) return error_message end + +local function show_error(mod, error_prefix_data, error_message) + local error_prefix + if type(error_prefix_data) == "table" then + error_prefix = string.format(error_prefix_data[1], error_prefix_data[2], error_prefix_data[3], error_prefix_data[4]) + else + error_prefix = error_prefix_data + end + + mod:error("%s: %s", error_prefix, error_message) +end + -- ##################################################################################################################### -- ##### VMFMod ######################################################################################################## -- ##################################################################################################################### function VMFMod:pcall(...) - return vmf.xpcall(self, "(pcall)", ...) + return vmf.safe_call(self, "(pcall)", ...) end function VMFMod:dofile(file_path) - local _, return_values = pack_pcall(vmf.xpcall_dofile(self, "(dofile)", file_path)) + local _, return_values = pack_pcall(vmf.safe_call_dofile(self, "(dofile)", file_path)) return unpack(return_values, 1, return_values.n) end @@ -35,29 +47,48 @@ end -- ##### VMF internal functions and variables ########################################################################## -- ##################################################################################################################### -function vmf.xpcall(mod, error_prefix, func, ...) +-- Safe Call +function vmf.safe_call(mod, error_prefix_data, func, ...) local success, return_values = pack_pcall(xpcall(func, print_error_callstack, ...)) if not success then - mod:error("%s: %s", error_prefix, return_values[1]) + show_error(mod, error_prefix_data, return_values[1]) return success end return success, unpack(return_values, 1, return_values.n) end -function vmf.xpcall_no_return_values(mod, error_prefix, func, ...) +-- Safe Call [No return values] +function vmf.safe_call_nr(mod, error_prefix_data, func, ...) local success, error_message = xpcall(func, print_error_callstack, ...) if not success then - mod:error("%s: %s", error_prefix, error_message) + show_error(mod, error_prefix_data, error_message) end return success end -function vmf.xpcall_dofile(mod, error_prefix, file_path) +-- Safe Call [No return values and error callstack] +function vmf.safe_call_nrc(mod, error_prefix_data, func, ...) + local success, error_message = pcall(func, ...) + if not success then + show_error(mod, error_prefix_data, error_message) + end + return success +end + + +-- Safe Call [dofile] +function vmf.safe_call_dofile(mod, error_prefix_data, file_path) if type(file_path) ~= "string" then - mod:error("%s: file path should be a string.", error_prefix) + show_error(mod, error_prefix_data, "file path should be a string.") return false end - return vmf.xpcall(mod, error_prefix, dofile, file_path) + return vmf.safe_call(mod, error_prefix_data, dofile, file_path) +end + + +-- Format error message and throw error. +function vmf.throw_error(error_message, ...) + error(string.format(error_message, ...), 0) end \ No newline at end of file diff --git a/vmf/scripts/mods/vmf/modules/gui/custom_views.lua b/vmf/scripts/mods/vmf/modules/gui/custom_views.lua index 72e0c9a..50faaec 100644 --- a/vmf/scripts/mods/vmf/modules/gui/custom_views.lua +++ b/vmf/scripts/mods/vmf/modules/gui/custom_views.lua @@ -84,7 +84,8 @@ local function inject_view(view_name) end -- Initialize and inject view. - local success, view = vmf.xpcall(mod, "calling init_view_function", init_view_function, _ingame_ui.ingame_ui_context) + local success, view = vmf.safe_call(mod, "calling init_view_function", init_view_function, + _ingame_ui.ingame_ui_context) if success then _ingame_ui.views[view_name] = view else @@ -116,7 +117,7 @@ local function remove_injected_views(on_reload) local view = _ingame_ui.views[view_name] if view then if type(view.destroy) == "function" then - vmf.xpcall_no_return_values(view_data.mod, "(custom menus) destroy view", view.destroy) + vmf.safe_call_nr(view_data.mod, "(custom menus) destroy view", view.destroy) end _ingame_ui.views[view_name] = nil end @@ -279,7 +280,8 @@ function VMFMod:register_view(view_data) local view_name = view_data.view_name - if vmf.catch_errors(self, ERRORS.PREFIX["register_view_validating"], view_name, validate_view_data, view_data) then + if not vmf.safe_call_nrc(self, {ERRORS.PREFIX["register_view_validating"], view_name}, validate_view_data, + view_data) then return end @@ -290,7 +292,7 @@ function VMFMod:register_view(view_data) } if _ingame_ui then - if vmf.catch_errors(self, ERRORS.PREFIX["register_view_injection"], view_name, inject_view, view_name) then + if not vmf.safe_call_nrc(self, {ERRORS.PREFIX["register_view_injection"], view_name}, inject_view, view_name) then _views_data[view_data.view_name] = nil end end @@ -303,7 +305,7 @@ end vmf:hook_safe(IngameUI, "init", function(self) _ingame_ui = self for view_name, _ in pairs(_views_data) do - if vmf.catch_errors(self, ERRORS.PREFIX["ingameui_hook_injection"], view_name, inject_view, view_name) then + if not vmf.safe_call_nrc(self, {ERRORS.PREFIX["ingameui_hook_injection"], view_name}, inject_view, view_name) then _views_data[view_name] = nil end end diff --git a/vmf/scripts/mods/vmf/modules/vmf_mod_manager.lua b/vmf/scripts/mods/vmf/modules/vmf_mod_manager.lua index 33fd992..a64a6fe 100644 --- a/vmf/scripts/mods/vmf/modules/vmf_mod_manager.lua +++ b/vmf/scripts/mods/vmf/modules/vmf_mod_manager.lua @@ -53,8 +53,8 @@ function new_mod(mod_name, mod_resources) -- Load localization data file if mod_resources.mod_localization then - local success, localization_table = vmf.xpcall_dofile(mod, "(new_mod)('mod_localization' initialization)", - mod_resources.mod_localization) + local success, localization_table = vmf.safe_call_dofile(mod, "(new_mod)('mod_localization' initialization)", + mod_resources.mod_localization) if success then vmf.load_mod_localization(mod, localization_table) -- @TODO: return here if not sucessful? rename to "initialize_" else @@ -64,15 +64,15 @@ function new_mod(mod_name, mod_resources) -- Load mod data file if mod_resources.mod_data then - local success, mod_data_table = vmf.xpcall_dofile(mod, "(new_mod)('mod_data' initialization)", - mod_resources.mod_data) + local success, mod_data_table = vmf.safe_call_dofile(mod, "(new_mod)('mod_data' initialization)", + mod_resources.mod_data) if success and not vmf.initialize_mod_data(mod, mod_data_table) then return end end -- Load mod @TODO: what will happen if mod_resources.mod_script == nil? - if not vmf.xpcall_dofile(mod, "(new_mod)('mod_script' initialization)", mod_resources.mod_script) then + if not vmf.safe_call_dofile(mod, "(new_mod)('mod_script' initialization)", mod_resources.mod_script) then return end