[Safe Calls] methods migration and renaming

This commit is contained in:
Azumgi 2018-11-10 15:53:40 +03:00
parent ad3d2a8767
commit da2cdc669d
9 changed files with 58 additions and 40 deletions

View file

@ -154,7 +154,7 @@ function vmf.run_command(command_name, ...)
local command_data = _commands[command_name] local command_data = _commands[command_name]
if command_data then if command_data then
local error_prefix = "(commands) " .. tostring(command_name) 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 else
vmf:error("(commands): command '%s' wasn't found.", command_name) -- Should never see this vmf:error("(commands): command '%s' wasn't found.", command_name) -- Should never see this
end end

View file

@ -10,7 +10,7 @@ local _mods_unloading_order = vmf.mods_unloading_order
local function run_event(mod, event_name, ...) local function run_event(mod, event_name, ...)
local event = mod[event_name] local event = mod[event_name]
if event then if event then
vmf.xpcall_no_return_values(mod, "(event) " .. event_name, event, ...) vmf.safe_call_nr(mod, "(event) " .. event_name, event, ...)
end end
end end

View file

@ -164,7 +164,7 @@ local function create_specialized_hook(mod, orig, hook_type)
elseif hook_type == HOOK_TYPE_SAFE then elseif hook_type == HOOK_TYPE_SAFE then
func = function(...) func = function(...)
if hook_data.active then 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 end
end end

View file

@ -197,7 +197,7 @@ end
local function call_function(mod, function_name, keybind_is_pressed) local function call_function(mod, function_name, keybind_is_pressed)
if type(mod[function_name]) == "function" then if type(mod[function_name]) == "function" then
local error_prefix = string.format("(keybindings) function_call 'mod.%s'", function_name) 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 else
mod:error("(keybindings) function_call 'mod.%s': function was not found.", tostring(function_name)) mod:error("(keybindings) function_call 'mod.%s': function was not found.", tostring(function_name))
end end

View file

@ -18,18 +18,3 @@ function vmf.check_wrong_argument_type(mod, vmf_function_name, argument_name, ar
table.concat(allowed_types, "/"), argument_type) table.concat(allowed_types, "/"), argument_type)
return true return true
end 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

View file

@ -176,7 +176,7 @@ local function send_rpc_vmf_data_local(mod_name, rpc_name, ...)
network_debug("data", "local", nil, mod_name, rpc_name, {...}) network_debug("data", "local", nil, mod_name, rpc_name, {...})
local error_prefix = "(local rpc) " .. tostring(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
end end
@ -307,7 +307,7 @@ vmf:hook("ChatManager", "rpc_chat_message",
-- can be error in both callback_function() and deserialize_data() -- can be error in both callback_function() and deserialize_data()
local error_prefix = "(network) " .. tostring(rpc_name) local error_prefix = "(network) " .. tostring(rpc_name)
vmf.xpcall_no_return_values( vmf.safe_call_nr(
get_mod(mod_name), get_mod(mod_name),
error_prefix, error_prefix,
function() _rpc_callbacks[mod_name][rpc_name](sender, deserialize_data(rpc_data2)) end function() _rpc_callbacks[mod_name][rpc_name](sender, deserialize_data(rpc_data2)) end

View file

@ -17,17 +17,29 @@ local function print_error_callstack(error_message)
return error_message return error_message
end 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 ######################################################################################################## -- ##### VMFMod ########################################################################################################
-- ##################################################################################################################### -- #####################################################################################################################
function VMFMod:pcall(...) function VMFMod:pcall(...)
return vmf.xpcall(self, "(pcall)", ...) return vmf.safe_call(self, "(pcall)", ...)
end end
function VMFMod:dofile(file_path) 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) return unpack(return_values, 1, return_values.n)
end end
@ -35,29 +47,48 @@ end
-- ##### VMF internal functions and variables ########################################################################## -- ##### 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, ...)) local success, return_values = pack_pcall(xpcall(func, print_error_callstack, ...))
if not success then if not success then
mod:error("%s: %s", error_prefix, return_values[1]) show_error(mod, error_prefix_data, return_values[1])
return success return success
end end
return success, unpack(return_values, 1, return_values.n) return success, unpack(return_values, 1, return_values.n)
end 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, ...) local success, error_message = xpcall(func, print_error_callstack, ...)
if not success then if not success then
mod:error("%s: %s", error_prefix, error_message) show_error(mod, error_prefix_data, error_message)
end end
return success return success
end 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 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 return false
end 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 end

View file

@ -84,7 +84,8 @@ local function inject_view(view_name)
end end
-- Initialize and inject view. -- 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 if success then
_ingame_ui.views[view_name] = view _ingame_ui.views[view_name] = view
else else
@ -116,7 +117,7 @@ local function remove_injected_views(on_reload)
local view = _ingame_ui.views[view_name] local view = _ingame_ui.views[view_name]
if view then if view then
if type(view.destroy) == "function" 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 end
_ingame_ui.views[view_name] = nil _ingame_ui.views[view_name] = nil
end end
@ -279,7 +280,8 @@ function VMFMod:register_view(view_data)
local view_name = view_data.view_name 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 return
end end
@ -290,7 +292,7 @@ function VMFMod:register_view(view_data)
} }
if _ingame_ui then 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 _views_data[view_data.view_name] = nil
end end
end end
@ -303,7 +305,7 @@ end
vmf:hook_safe(IngameUI, "init", function(self) vmf:hook_safe(IngameUI, "init", function(self)
_ingame_ui = self _ingame_ui = self
for view_name, _ in pairs(_views_data) do 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 _views_data[view_name] = nil
end end
end end

View file

@ -53,7 +53,7 @@ function new_mod(mod_name, mod_resources)
-- Load localization data file -- Load localization data file
if mod_resources.mod_localization then if mod_resources.mod_localization then
local success, localization_table = vmf.xpcall_dofile(mod, "(new_mod)('mod_localization' initialization)", local success, localization_table = vmf.safe_call_dofile(mod, "(new_mod)('mod_localization' initialization)",
mod_resources.mod_localization) mod_resources.mod_localization)
if success then if success then
vmf.load_mod_localization(mod, localization_table) -- @TODO: return here if not sucessful? rename to "initialize_" vmf.load_mod_localization(mod, localization_table) -- @TODO: return here if not sucessful? rename to "initialize_"
@ -64,7 +64,7 @@ function new_mod(mod_name, mod_resources)
-- Load mod data file -- Load mod data file
if mod_resources.mod_data then if mod_resources.mod_data then
local success, mod_data_table = vmf.xpcall_dofile(mod, "(new_mod)('mod_data' initialization)", local success, mod_data_table = vmf.safe_call_dofile(mod, "(new_mod)('mod_data' initialization)",
mod_resources.mod_data) mod_resources.mod_data)
if success and not vmf.initialize_mod_data(mod, mod_data_table) then if success and not vmf.initialize_mod_data(mod, mod_data_table) then
return return
@ -72,7 +72,7 @@ function new_mod(mod_name, mod_resources)
end end
-- Load mod @TODO: what will happen if mod_resources.mod_script == nil? -- 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 return
end end