Compare commits
No commits in common. "feat/mod-bundles" and "master" have entirely different histories.
feat/mod-b
...
master
44 changed files with 160 additions and 248 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,8 +1,6 @@
|
||||||
.temp
|
.temp
|
||||||
.vscode
|
.vscode
|
||||||
**/*.zip
|
**/*.zip
|
||||||
*.zip
|
|
||||||
vmf/bundleV1
|
vmf/bundleV1
|
||||||
vmf/bundleV2
|
vmf/bundleV2
|
||||||
node_modules
|
node_modules
|
||||||
out/
|
|
||||||
|
|
53
.luacheckrc
53
.luacheckrc
|
@ -1,7 +1,7 @@
|
||||||
max_line_length = 120
|
max_line_length = 120
|
||||||
|
|
||||||
include_files = {
|
include_files = {
|
||||||
"scripts/",
|
"**/scripts/",
|
||||||
}
|
}
|
||||||
|
|
||||||
ignore = {
|
ignore = {
|
||||||
|
@ -23,52 +23,21 @@ stds["DMF"] = {
|
||||||
|
|
||||||
stds["DT"] = {
|
stds["DT"] = {
|
||||||
read_globals = {
|
read_globals = {
|
||||||
string = { fields = { "split" } },
|
string = { fields = { "split" }},
|
||||||
table = {
|
table = { fields = {
|
||||||
fields = {
|
|
||||||
"merge", "table_to_array", "mirror_table", "tostring", "is_empty", "array_to_table", "reverse", "shuffle",
|
"merge", "table_to_array", "mirror_table", "tostring", "is_empty", "array_to_table", "reverse", "shuffle",
|
||||||
"merge_recursive", "unpack_map", "remove_unordered_items", "append", "mirror_array_inplace", "size",
|
"merge_recursive", "unpack_map", "remove_unordered_items", "append", "mirror_array_inplace", "size", "dump",
|
||||||
"dump",
|
"clear_array", "append_varargs", "find", "for_each", "crop", "mirror_array", "set", "create_copy", "clone",
|
||||||
"clear_array", "append_varargs", "find", "for_each", "crop", "mirror_array", "set", "create_copy",
|
"contains", "add_meta_logging", "table_as_sorted_string_arrays", "clone_instance", "max", "clear", "find_by_key",
|
||||||
"clone",
|
}},
|
||||||
"contains", "add_meta_logging", "table_as_sorted_string_arrays", "clone_instance", "max", "clear",
|
math = { fields = {
|
||||||
"find_by_key",
|
"ease_exp", "lerp", "polar_to_cartesian", "smoothstep", "easeCubic", "round", "point_is_inside_2d_triangle",
|
||||||
}
|
|
||||||
},
|
|
||||||
math = {
|
|
||||||
fields = {
|
|
||||||
"ease_exp", "lerp", "polar_to_cartesian", "smoothstep", "easeCubic", "round",
|
|
||||||
"point_is_inside_2d_triangle",
|
|
||||||
"radians_to_degrees", "circular_to_square_coordinates", "uuid", "easeInCubic", "round_with_precision",
|
"radians_to_degrees", "circular_to_square_coordinates", "uuid", "easeInCubic", "round_with_precision",
|
||||||
"clamp", "get_uniformly_random_point_inside_sector", "angle_lerp", "ease_out_exp", "rand_normal",
|
"clamp", "get_uniformly_random_point_inside_sector", "angle_lerp", "ease_out_exp", "rand_normal",
|
||||||
"bounce", "point_is_inside_2d_box", "catmullrom", "clamp_direction", "ease_in_exp", "random_seed",
|
"bounce", "point_is_inside_2d_box", "catmullrom", "clamp_direction", "ease_in_exp", "random_seed",
|
||||||
"sign", "degrees_to_radians", "sirp", "ease_pulse", "cartesian_to_polar", "ease_out_quad",
|
"sign", "degrees_to_radians", "sirp", "ease_pulse", "cartesian_to_polar", "ease_out_quad",
|
||||||
"easeOutCubic", "radian_lerp", "auto_lerp", "rand_utf8_string", "point_is_inside_oobb",
|
"easeOutCubic", "radian_lerp", "auto_lerp", "rand_utf8_string", "point_is_inside_oobb",
|
||||||
}
|
}},
|
||||||
},
|
"Crashify","Keyboard","Mouse","Application","Color","Quarternion","Vector3","Vector2","RESOLUTION_LOOKUP"
|
||||||
Managers = {
|
|
||||||
fields = {
|
|
||||||
"mod", "event", "ui",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Mods = {
|
|
||||||
fields = {
|
|
||||||
lua = { fields = { "debug", "io", "ffi", "os" } },
|
|
||||||
"original_require",
|
|
||||||
"require_store",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Crashify",
|
|
||||||
"Keyboard",
|
|
||||||
"Mouse",
|
|
||||||
"Application",
|
|
||||||
"Color",
|
|
||||||
"Quarternion",
|
|
||||||
"Vector3",
|
|
||||||
"Vector2",
|
|
||||||
"RESOLUTION_LOOKUP",
|
|
||||||
"ModManager",
|
|
||||||
"Utf8",
|
|
||||||
"Main",
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
5
dmf/dmf.mod
Normal file
5
dmf/dmf.mod
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
return {
|
||||||
|
run = function()
|
||||||
|
return Mods.file.dofile("dmf/scripts/mods/dmf/dmf_loader")
|
||||||
|
end
|
||||||
|
}
|
|
@ -3,6 +3,9 @@ local dmf
|
||||||
-- Native mod object used by Fatshark mod manager
|
-- Native mod object used by Fatshark mod manager
|
||||||
local dmf_mod_object = {}
|
local dmf_mod_object = {}
|
||||||
|
|
||||||
|
-- Global method to load a file through iowith a return
|
||||||
|
local io_dofile = Mods.file.dofile
|
||||||
|
|
||||||
-- Global backup of original print() method
|
-- Global backup of original print() method
|
||||||
local print = __print
|
local print = __print
|
||||||
|
|
||||||
|
@ -11,37 +14,44 @@ local print = __print
|
||||||
-- #####################################################################################################################
|
-- #####################################################################################################################
|
||||||
|
|
||||||
function dmf_mod_object:init()
|
function dmf_mod_object:init()
|
||||||
dofile("scripts/mods/dmf/modules/dmf_mod_data")
|
io_dofile("dmf/scripts/mods/dmf/modules/dmf_mod_data")
|
||||||
dofile("scripts/mods/dmf/modules/dmf_mod_manager")
|
io_dofile("dmf/scripts/mods/dmf/modules/dmf_mod_manager")
|
||||||
-- dofile("scripts/mods/dmf/modules/dmf_dummy")
|
--io_dofile("dmf/scripts/mods/dmf/modules/dmf_dummy")
|
||||||
dofile("scripts/mods/dmf/modules/dmf_package_manager")
|
io_dofile("dmf/scripts/mods/dmf/modules/dmf_package_manager")
|
||||||
dofile("scripts/mods/dmf/modules/core/safe_calls")
|
io_dofile("dmf/scripts/mods/dmf/modules/core/safe_calls")
|
||||||
dofile("scripts/mods/dmf/modules/core/events")
|
io_dofile("dmf/scripts/mods/dmf/modules/core/events")
|
||||||
dofile("scripts/mods/dmf/modules/core/settings")
|
io_dofile("dmf/scripts/mods/dmf/modules/core/settings")
|
||||||
dofile("scripts/mods/dmf/modules/core/logging")
|
io_dofile("dmf/scripts/mods/dmf/modules/core/logging")
|
||||||
dofile("scripts/mods/dmf/modules/core/misc")
|
io_dofile("dmf/scripts/mods/dmf/modules/core/misc")
|
||||||
dofile("scripts/mods/dmf/modules/core/persistent_tables")
|
io_dofile("dmf/scripts/mods/dmf/modules/core/persistent_tables")
|
||||||
dofile("scripts/mods/dmf/modules/core/io")
|
io_dofile("dmf/scripts/mods/dmf/modules/core/io")
|
||||||
dofile("scripts/mods/dmf/modules/debug/dev_console")
|
|
||||||
dofile("scripts/mods/dmf/modules/debug/table_dump")
|
|
||||||
dofile("scripts/mods/dmf/modules/core/hooks")
|
|
||||||
dofile("scripts/mods/dmf/modules/core/require")
|
|
||||||
dofile("scripts/mods/dmf/modules/core/toggling")
|
|
||||||
dofile("scripts/mods/dmf/modules/core/keybindings")
|
|
||||||
dofile("scripts/mods/dmf/modules/core/chat")
|
|
||||||
dofile("scripts/mods/dmf/modules/core/localization")
|
|
||||||
dofile("scripts/mods/dmf/modules/core/options")
|
|
||||||
dofile("scripts/mods/dmf/modules/core/network")
|
|
||||||
dofile("scripts/mods/dmf/modules/core/commands")
|
|
||||||
dofile("scripts/mods/dmf/modules/gui/custom_textures")
|
|
||||||
dofile("scripts/mods/dmf/modules/gui/custom_views")
|
|
||||||
dofile("scripts/mods/dmf/modules/ui/chat/chat_actions")
|
|
||||||
dofile("scripts/mods/dmf/modules/ui/options/mod_options")
|
|
||||||
dofile("scripts/mods/dmf/modules/dmf_options")
|
|
||||||
dofile("scripts/mods/dmf/modules/core/mutators/mutators_manager")
|
|
||||||
|
|
||||||
|
-- DMF's internal io module is now loaded:
|
||||||
dmf = get_mod("DMF")
|
dmf = get_mod("DMF")
|
||||||
|
|
||||||
|
dmf:io_dofile("dmf/scripts/mods/dmf/modules/debug/dev_console")
|
||||||
|
dmf:io_dofile("dmf/scripts/mods/dmf/modules/debug/table_dump")
|
||||||
|
dmf:io_dofile("dmf/scripts/mods/dmf/modules/core/hooks")
|
||||||
|
dmf:io_dofile("dmf/scripts/mods/dmf/modules/core/require")
|
||||||
|
dmf:io_dofile("dmf/scripts/mods/dmf/modules/core/toggling")
|
||||||
|
dmf:io_dofile("dmf/scripts/mods/dmf/modules/core/keybindings")
|
||||||
|
dmf:io_dofile("dmf/scripts/mods/dmf/modules/core/chat")
|
||||||
|
dmf:io_dofile("dmf/scripts/mods/dmf/modules/core/localization")
|
||||||
|
dmf:io_dofile("dmf/scripts/mods/dmf/modules/core/options")
|
||||||
|
dmf:io_dofile("dmf/scripts/mods/dmf/modules/core/network")
|
||||||
|
dmf:io_dofile("dmf/scripts/mods/dmf/modules/core/commands")
|
||||||
|
dmf:io_dofile("dmf/scripts/mods/dmf/modules/gui/custom_textures")
|
||||||
|
dmf:io_dofile("dmf/scripts/mods/dmf/modules/gui/custom_views")
|
||||||
|
dmf:io_dofile("dmf/scripts/mods/dmf/modules/ui/chat/chat_actions")
|
||||||
|
dmf:io_dofile("dmf/scripts/mods/dmf/modules/ui/options/mod_options")
|
||||||
|
dmf:io_dofile("dmf/scripts/mods/dmf/modules/dmf_options")
|
||||||
|
dmf:io_dofile("dmf/scripts/mods/dmf/modules/core/mutators/mutators_manager")
|
||||||
|
|
||||||
dmf.delayed_chat_messages_hook()
|
dmf.delayed_chat_messages_hook()
|
||||||
|
dmf:hook(ModManager, "destroy", function(func, ...)
|
||||||
|
dmf.mods_unload_event(true)
|
||||||
|
func(...)
|
||||||
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- #####################################################################################################################
|
-- #####################################################################################################################
|
||||||
|
@ -54,7 +64,7 @@ function dmf_mod_object:update(dt)
|
||||||
dmf.check_keybinds()
|
dmf.check_keybinds()
|
||||||
dmf.execute_queued_chat_command()
|
dmf.execute_queued_chat_command()
|
||||||
|
|
||||||
if not dmf.all_mods_were_loaded and Managers.mod:all_mods_loaded() then
|
if not dmf.all_mods_were_loaded and Managers.mod._state == "done" then
|
||||||
|
|
||||||
dmf.generate_keybinds()
|
dmf.generate_keybinds()
|
||||||
dmf.initialize_dmf_options_view()
|
dmf.initialize_dmf_options_view()
|
||||||
|
@ -87,21 +97,8 @@ function dmf_mod_object:on_reload()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function dmf_mod_object:on_destroy()
|
|
||||||
print("DMF:ON_DESTROY()")
|
|
||||||
dmf.mods_unload_event(true)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function dmf_mod_object:on_game_state_changed(status, state)
|
function dmf_mod_object:on_game_state_changed(status, state)
|
||||||
print("DMF:ON_GAME_STATE_CHANGED(), status: " .. tostring(status) .. ", state: " .. tostring(state))
|
print("DMF:ON_GAME_STATE_CHANGED(), status: " .. tostring(status) .. ", state: " .. tostring(state))
|
||||||
|
|
||||||
-- Certain intialization procedures need to be delayed until the game's core systems are
|
|
||||||
-- fully initialized and running
|
|
||||||
if status == "enter" and state == "StateTitle" then
|
|
||||||
dmf.initialize_options()
|
|
||||||
end
|
|
||||||
|
|
||||||
dmf.mods_game_state_changed_event(status, state)
|
dmf.mods_game_state_changed_event(status, state)
|
||||||
dmf.save_unsaved_settings_to_file()
|
dmf.save_unsaved_settings_to_file()
|
||||||
dmf.apply_delayed_hooks()
|
dmf.apply_delayed_hooks()
|
|
@ -95,7 +95,7 @@ local function handle_io(mod, local_path, file_name, file_extension, args, safe_
|
||||||
|
|
||||||
-- If this is a safe call, wrap it in a pcall
|
-- If this is a safe call, wrap it in a pcall
|
||||||
if safe_call then
|
if safe_call then
|
||||||
status, result = pcall(function()
|
status, result = pcall(function ()
|
||||||
return read_or_execute(file_path, args, return_type)
|
return read_or_execute(file_path, args, return_type)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
@ -114,12 +114,25 @@ local function handle_io(mod, local_path, file_name, file_extension, args, safe_
|
||||||
|
|
||||||
-- If the initial open failed, report failure
|
-- If the initial open failed, report failure
|
||||||
else
|
else
|
||||||
mod:error("Error during I/O: %s\n%s", tostring(err_io), Script.callstack())
|
mod:error("Error opening '" .. file_path .. "': " .. tostring(err_io))
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Return whether the file exists at the given path
|
||||||
|
local function file_exists(local_path, file_name, file_extension)
|
||||||
|
local file_path = get_file_path(local_path, file_name, file_extension)
|
||||||
|
local f = _io.open(file_path,"r")
|
||||||
|
|
||||||
|
if f ~= nil then
|
||||||
|
_io.close(f)
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- #####################################################################################################################
|
-- #####################################################################################################################
|
||||||
-- ##### DMFMod ########################################################################################################
|
-- ##### DMFMod ########################################################################################################
|
||||||
-- #####################################################################################################################
|
-- #####################################################################################################################
|
||||||
|
@ -129,21 +142,25 @@ function DMFMod:io_exec(local_path, file_name, file_extension, args)
|
||||||
return handle_io(self, local_path, file_name, file_extension, args, true, "exec_boolean")
|
return handle_io(self, local_path, file_name, file_extension, args, true, "exec_boolean")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Use the io library to execute the given file without a pcall, without return
|
-- Use the io library to execute the given file without a pcall, without return
|
||||||
function DMFMod:io_exec_unsafe(local_path, file_name, file_extension, args)
|
function DMFMod:io_exec_unsafe(local_path, file_name, file_extension, args)
|
||||||
return handle_io(self, local_path, file_name, file_extension, args, false, "exec_boolean")
|
return handle_io(self, local_path, file_name, file_extension, args, false, "exec_boolean")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Use the io library to execute the given file with a pcall and return the result
|
-- Use the io library to execute the given file with a pcall and return the result
|
||||||
function DMFMod:io_exec_with_return(local_path, file_name, file_extension, args)
|
function DMFMod:io_exec_with_return(local_path, file_name, file_extension, args)
|
||||||
return handle_io(self, local_path, file_name, file_extension, args, true, "exec_result")
|
return handle_io(self, local_path, file_name, file_extension, args, true, "exec_result")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Use the io library to execute the given file without a pcall and return the result
|
-- Use the io library to execute the given file without a pcall and return the result
|
||||||
function DMFMod:io_exec_unsafe_with_return(local_path, file_name, file_extension, args)
|
function DMFMod:io_exec_unsafe_with_return(local_path, file_name, file_extension, args)
|
||||||
return handle_io(self, local_path, file_name, file_extension, args, false, "exec_result")
|
return handle_io(self, local_path, file_name, file_extension, args, false, "exec_result")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Use the io library to execute the given file with a pcall and return the result,
|
-- Use the io library to execute the given file with a pcall and return the result,
|
||||||
-- but treat the first parameter as the entire path to the file, and assume .lua.
|
-- but treat the first parameter as the entire path to the file, and assume .lua.
|
||||||
-- IO version of the dofile method with a pcall.
|
-- IO version of the dofile method with a pcall.
|
||||||
|
@ -151,6 +168,7 @@ function DMFMod:io_dofile(file_path)
|
||||||
return handle_io(self, file_path, nil, nil, nil, true, "exec_result")
|
return handle_io(self, file_path, nil, nil, nil, true, "exec_result")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Use the io library to execute the given file without a pcall and return the result,
|
-- Use the io library to execute the given file without a pcall and return the result,
|
||||||
-- but treat the first parameter as the entire path to the file, and assume .lua.
|
-- but treat the first parameter as the entire path to the file, and assume .lua.
|
||||||
-- IO version of the dofile method.
|
-- IO version of the dofile method.
|
||||||
|
@ -158,6 +176,7 @@ function DMFMod:io_dofile_unsafe(file_path)
|
||||||
return handle_io(self, file_path, nil, nil, nil, false, "exec_result")
|
return handle_io(self, file_path, nil, nil, nil, false, "exec_result")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Use the io library to return the contents of the given file
|
-- Use the io library to return the contents of the given file
|
||||||
function DMFMod:io_read_content(file_path, file_extension)
|
function DMFMod:io_read_content(file_path, file_extension)
|
||||||
return handle_io(self, file_path, nil, file_extension, nil, true, "data")
|
return handle_io(self, file_path, nil, file_extension, nil, true, "data")
|
|
@ -138,5 +138,5 @@ end
|
||||||
-- ##### Script #######################################################################################################
|
-- ##### Script #######################################################################################################
|
||||||
-- ####################################################################################################################
|
-- ####################################################################################################################
|
||||||
|
|
||||||
local localization_table = dmf:dofile("scripts/mods/dmf/localization/dmf")
|
local localization_table = dmf:io_dofile("dmf/localization/dmf")
|
||||||
dmf.initialize_mod_localization(dmf, localization_table)
|
dmf.initialize_mod_localization(dmf, localization_table)
|
|
@ -55,7 +55,6 @@ end
|
||||||
|
|
||||||
local function add_chat_message(message, sender)
|
local function add_chat_message(message, sender)
|
||||||
local channel_sender = sender or "SYSTEM"
|
local channel_sender = sender or "SYSTEM"
|
||||||
message = tostring(message)
|
|
||||||
|
|
||||||
-- Send to our stored chat element if it exists
|
-- Send to our stored chat element if it exists
|
||||||
if _chat_element then
|
if _chat_element then
|
|
@ -14,10 +14,8 @@ function dmf.check_wrong_argument_type(mod, dmf_function_name, argument_name, ar
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
mod:error(
|
mod:error("(%s): argument '%s' should have the '%s' type, not '%s'", dmf_function_name, argument_name,
|
||||||
"(%s): argument '%s' should have the '%s' type, not '%s'\n%s",
|
table.concat(allowed_types, "/"), argument_type)
|
||||||
dmf_function_name, argument_name, table.concat(allowed_types, "/"), argument_type, Script.callstack()
|
|
||||||
)
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
|
@ -27,11 +27,11 @@ local _mutators_sorted = false
|
||||||
local _all_mutators_disabled = false
|
local _all_mutators_disabled = false
|
||||||
|
|
||||||
-- External modules
|
-- External modules
|
||||||
local reward_manager = dmf:dofile("scripts/mods/dmf/modules/core/mutators/mutators_reward")
|
local reward_manager = dmf:io_dofile("dmf/scripts/mods/dmf/modules/core/mutators/mutators_reward")
|
||||||
local set_lobby_data = dmf:dofile("scripts/mods/dmf/modules/core/mutators/mutators_info")
|
local set_lobby_data = dmf:io_dofile("dmf/scripts/mods/dmf/modules/core/mutators/mutators_info")
|
||||||
|
|
||||||
-- Get default configuration
|
-- Get default configuration
|
||||||
local _default_config = dmf:dofile("scripts/mods/dmf/modules/core/mutators/mutators_default_config")
|
local _default_config = dmf:io_dofile("dmf/scripts/mods/dmf/modules/core/mutators/mutators_default_config")
|
||||||
|
|
||||||
-- List of enabled mutators in case DMF is reloaded in the middle of the game
|
-- List of enabled mutators in case DMF is reloaded in the middle of the game
|
||||||
local _enabled_mutators = dmf:persistent_table("enabled_mutators")
|
local _enabled_mutators = dmf:persistent_table("enabled_mutators")
|
||||||
|
@ -505,4 +505,4 @@ end
|
||||||
-- #####################################################################################################################
|
-- #####################################################################################################################
|
||||||
|
|
||||||
-- Testing
|
-- Testing
|
||||||
--dmf:dofile("scripts/mods/dmf/modules/core/mutators/test/mutators_test")
|
--dmf:io_dofile("dmf/scripts/mods/dmf/modules/core/mutators/test/mutators_test")
|
|
@ -35,63 +35,24 @@ end
|
||||||
-- ##### DMFMod ########################################################################################################
|
-- ##### DMFMod ########################################################################################################
|
||||||
-- #####################################################################################################################
|
-- #####################################################################################################################
|
||||||
|
|
||||||
--- Loads the given file with the same semantics as Lua's `require`.
|
-- Add a file path to be loaded through io instead of require()
|
||||||
---
|
|
||||||
--- This provides a unified API for both bundled and non-bundled mods.
|
|
||||||
---
|
|
||||||
--- @param path string The file to load
|
|
||||||
function DMFMod:require(path)
|
|
||||||
local is_bundled = self:get_internal_data("is_bundled")
|
|
||||||
|
|
||||||
if is_bundled then
|
|
||||||
return require(path)
|
|
||||||
else
|
|
||||||
local loaded = self:io_dofile_unsafe(path)
|
|
||||||
if loaded then
|
|
||||||
package.loaded[path] = loaded
|
|
||||||
end
|
|
||||||
return loaded
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Loads the given file with the same semantics as Lua's `dofile`.
|
|
||||||
---
|
|
||||||
--- This provides a unified API for both bundled and non-bundled mods.
|
|
||||||
---
|
|
||||||
--- @param path string The file to load
|
|
||||||
function DMFMod:dofile(path)
|
|
||||||
local is_bundled = self:get_internal_data("is_bundled")
|
|
||||||
|
|
||||||
if is_bundled then
|
|
||||||
return dofile(path)
|
|
||||||
else
|
|
||||||
return dmf.io_dofile_unsafe(self, path)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Add a file path to be loaded through `io` instead of `require`.
|
|
||||||
--
|
|
||||||
-- Certain game systems will be given a path value and then call `require`
|
|
||||||
-- internally, where a mod cannot easily hook and replace the call.
|
|
||||||
--
|
|
||||||
-- This function allows non-bundled mods to inject a file such that these systems
|
|
||||||
-- can `require` them without additional hooks.
|
|
||||||
--
|
|
||||||
-- Bundled mods already have all their files available through regular `require`.
|
|
||||||
function DMFMod:add_require_path(path)
|
function DMFMod:add_require_path(path)
|
||||||
add_io_require_path(path)
|
add_io_require_path(path)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Remove a file path that was previously loaded through io instead of require()
|
-- Remove a file path that was previously loaded through io instead of require()
|
||||||
function DMFMod:remove_require_path(path)
|
function DMFMod:remove_require_path(path)
|
||||||
remove_io_require_path(path)
|
remove_io_require_path(path)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Get all instances of a file created through require()
|
-- Get all instances of a file created through require()
|
||||||
function DMFMod:get_require_store(path)
|
function DMFMod:get_require_store(path)
|
||||||
return get_require_store(path)
|
return get_require_store(path)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Get a file through the original, unhooked require() function
|
-- Get a file through the original, unhooked require() function
|
||||||
function DMFMod:original_require(path, ...)
|
function DMFMod:original_require(path, ...)
|
||||||
return original_require(path, ...)
|
return original_require(path, ...)
|
||||||
|
@ -102,9 +63,9 @@ end
|
||||||
-- #####################################################################################################################
|
-- #####################################################################################################################
|
||||||
|
|
||||||
-- Handles the swap to io for registered files and the application of file hooks
|
-- Handles the swap to io for registered files and the application of file hooks
|
||||||
dmf:hook(_G, "require", function(func, path, ...)
|
dmf:hook(_G, "require", function (func, path, ...)
|
||||||
if _io_requires[path] then
|
if _io_requires[path] then
|
||||||
return dmf:dofile(path)
|
return dmf:io_dofile(path)
|
||||||
else
|
else
|
||||||
local result = func(path, ...)
|
local result = func(path, ...)
|
||||||
|
|
|
@ -8,22 +8,16 @@ local print = __print
|
||||||
-- #####################################################################################################################
|
-- #####################################################################################################################
|
||||||
|
|
||||||
local function pack_pcall(status, ...)
|
local function pack_pcall(status, ...)
|
||||||
return status, { n = select('#', ...), ... }
|
return status, {n = select('#', ...), ...}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local function print_error_callstack(err)
|
local function print_error_callstack(error_message)
|
||||||
if type(err) == "table" and err.error then
|
if type(error_message) == "table" and error_message.error then
|
||||||
Log.error(
|
error_message = error_message.error
|
||||||
"DMF",
|
|
||||||
"%s\n<<Lua Stack>>%s<</Lua Stack>>\n<<Lua Locals>>%s<</Lua Locals>>\n<<Lua Self>>%s<</Lua Self>>",
|
|
||||||
err.error, err.traceback, err.locals, err.self
|
|
||||||
)
|
|
||||||
else
|
|
||||||
Log.error("DMF", "Error: %s\n%s", tostring(err), Script.callstack())
|
|
||||||
end
|
end
|
||||||
|
print("Error: " .. tostring(error_message) .. "\n" .. Script.callstack())
|
||||||
return err
|
return error_message
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -46,6 +40,12 @@ function DMFMod:pcall(...)
|
||||||
return dmf.safe_call(self, "(pcall)", ...)
|
return dmf.safe_call(self, "(pcall)", ...)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function DMFMod:dofile(file_path)
|
||||||
|
local _, return_values = pack_pcall(dmf.safe_call_dofile(self, "(dofile)", file_path))
|
||||||
|
return unpack(return_values, 1, return_values.n)
|
||||||
|
end
|
||||||
|
|
||||||
-- #####################################################################################################################
|
-- #####################################################################################################################
|
||||||
-- ##### DMF internal functions and variables ##########################################################################
|
-- ##### DMF internal functions and variables ##########################################################################
|
||||||
-- #####################################################################################################################
|
-- #####################################################################################################################
|
||||||
|
@ -60,6 +60,7 @@ function dmf.safe_call(mod, error_prefix_data, func, ...)
|
||||||
return success, unpack(return_values, 1, return_values.n)
|
return success, unpack(return_values, 1, return_values.n)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Safe Call [No return values]
|
-- Safe Call [No return values]
|
||||||
function dmf.safe_call_nr(mod, error_prefix_data, func, ...)
|
function dmf.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, ...)
|
||||||
|
@ -69,6 +70,7 @@ function dmf.safe_call_nr(mod, error_prefix_data, func, ...)
|
||||||
return success
|
return success
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Safe Call [No return values and error callstack]
|
-- Safe Call [No return values and error callstack]
|
||||||
function dmf.safe_call_nrc(mod, error_prefix_data, func, ...)
|
function dmf.safe_call_nrc(mod, error_prefix_data, func, ...)
|
||||||
local success, error_message = pcall(func, ...)
|
local success, error_message = pcall(func, ...)
|
||||||
|
@ -78,6 +80,7 @@ function dmf.safe_call_nrc(mod, error_prefix_data, func, ...)
|
||||||
return success
|
return success
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Safe Call [dofile]
|
-- Safe Call [dofile]
|
||||||
function dmf.safe_call_dofile(mod, error_prefix_data, file_path)
|
function dmf.safe_call_dofile(mod, error_prefix_data, file_path)
|
||||||
if type(file_path) ~= "string" then
|
if type(file_path) ~= "string" then
|
||||||
|
@ -87,6 +90,7 @@ function dmf.safe_call_dofile(mod, error_prefix_data, file_path)
|
||||||
return dmf.safe_call(mod, error_prefix_data, dofile, file_path)
|
return dmf.safe_call(mod, error_prefix_data, dofile, file_path)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Safe Call [io_dofile]
|
-- Safe Call [io_dofile]
|
||||||
function dmf.safe_call_io_dofile(mod, error_prefix_data, file_path)
|
function dmf.safe_call_io_dofile(mod, error_prefix_data, file_path)
|
||||||
if type(file_path) ~= "string" then
|
if type(file_path) ~= "string" then
|
||||||
|
@ -96,6 +100,7 @@ function dmf.safe_call_io_dofile(mod, error_prefix_data, file_path)
|
||||||
return dmf.safe_call(mod, error_prefix_data, mod.io_dofile_unsafe, mod, file_path)
|
return dmf.safe_call(mod, error_prefix_data, mod.io_dofile_unsafe, mod, file_path)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Format error message and throw error.
|
-- Format error message and throw error.
|
||||||
function dmf.throw_error(error_message, ...)
|
function dmf.throw_error(error_message, ...)
|
||||||
error(string.format(error_message, ...), 0)
|
error(string.format(error_message, ...), 0)
|
|
@ -24,7 +24,7 @@ function DMFMod:init(mod_name)
|
||||||
|
|
||||||
self._data = setmetatable({}, {
|
self._data = setmetatable({}, {
|
||||||
__index = {},
|
__index = {},
|
||||||
__newindex = function(_, k)
|
__newindex = function(t_, k)
|
||||||
self:warning("Attempt to change internal mod data value (\"%s\"). Changing internal mod data is forbidden.", k)
|
self:warning("Attempt to change internal mod data value (\"%s\"). Changing internal mod data is forbidden.", k)
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
|
@ -34,11 +34,10 @@ function DMFMod:init(mod_name)
|
||||||
set_internal_data(self, "is_togglable", false)
|
set_internal_data(self, "is_togglable", false)
|
||||||
set_internal_data(self, "is_mutator", false)
|
set_internal_data(self, "is_mutator", false)
|
||||||
|
|
||||||
local vanilla_mod_data = Managers.mod:mod_data(mod_name)
|
local vanilla_mod_data = Managers.mod._mods[Managers.mod._mod_load_index]
|
||||||
set_internal_data(self, "workshop_id", vanilla_mod_data.id)
|
set_internal_data(self, "workshop_id", vanilla_mod_data.id)
|
||||||
set_internal_data(self, "workshop_name", vanilla_mod_data.name)
|
set_internal_data(self, "workshop_name", vanilla_mod_data.name)
|
||||||
set_internal_data(self, "mod_handle", vanilla_mod_data.handle)
|
set_internal_data(self, "mod_handle", vanilla_mod_data.handle)
|
||||||
set_internal_data(self, "is_bundled", vanilla_mod_data.bundled or false)
|
|
||||||
|
|
||||||
print(string.format("Init DMF mod '%s' [workshop_name: '%s', workshop_id: %s]", mod_name, vanilla_mod_data.name,
|
print(string.format("Init DMF mod '%s' [workshop_name: '%s', workshop_id: %s]", mod_name, vanilla_mod_data.name,
|
||||||
vanilla_mod_data.id))
|
vanilla_mod_data.id))
|
|
@ -50,11 +50,7 @@ local function resolve_resource(mod, error_prefix_data, resource, resource_value
|
||||||
local type_value = type(resource_value)
|
local type_value = type(resource_value)
|
||||||
|
|
||||||
if type_value == "string" then
|
if type_value == "string" then
|
||||||
if mod:get_internal_data("is_bundled") then
|
|
||||||
return dmf.safe_call_dofile(mod, error_prefix_data, resource_value)
|
|
||||||
else
|
|
||||||
return dmf.safe_call_io_dofile(mod, error_prefix_data, resource_value)
|
return dmf.safe_call_io_dofile(mod, error_prefix_data, resource_value)
|
||||||
end
|
|
||||||
elseif type_value == "function" then
|
elseif type_value == "function" then
|
||||||
return dmf.safe_call(mod, error_prefix_data, resource_value, mod)
|
return dmf.safe_call(mod, error_prefix_data, resource_value, mod)
|
||||||
elseif type_value == "table" then
|
elseif type_value == "table" then
|
||||||
|
@ -135,6 +131,7 @@ function new_mod(mod_name, mod_resources)
|
||||||
return mod
|
return mod
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function get_mod(mod_name)
|
function get_mod(mod_name)
|
||||||
return _mods[mod_name]
|
return _mods[mod_name]
|
||||||
end
|
end
|
||||||
|
@ -173,13 +170,11 @@ function dmf.initialize_mod_data(mod, mod_data)
|
||||||
|
|
||||||
-- Mod's options initialization
|
-- Mod's options initialization
|
||||||
if mod_data.options or (not mod_data.is_mutator and not mod_data.options_widgets) then
|
if mod_data.options or (not mod_data.is_mutator and not mod_data.options_widgets) then
|
||||||
dmf.safe_call(
|
local success, error_message = pcall(dmf.initialize_mod_options, mod, mod_data.options)
|
||||||
dmf,
|
if not success then
|
||||||
ERRORS.REGULAR.mod_options_initializing_failed,
|
mod:error(ERRORS.REGULAR.mod_options_initializing_failed, error_message)
|
||||||
dmf.initialize_mod_options,
|
return
|
||||||
mod,
|
end
|
||||||
mod_data.options
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Textures initialization @TODO: move to a separate function
|
-- Textures initialization @TODO: move to a separate function
|
|
@ -249,24 +249,19 @@ dmf.on_setting_changed = function (setting_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
dmf.load_developer_mode_settings = function () --@TODO: maybe move it to somewhere else?
|
dmf.load_developer_mode_settings = function () --@TODO: maybe move it to somewhere else?
|
||||||
|
Managers.mod._settings.developer_mode = dmf:get("developer_mode")
|
||||||
Application.set_user_setting("mod_manager_settings", Managers.mod._settings)
|
Application.set_user_setting("mod_manager_settings", Managers.mod._settings)
|
||||||
|
|
||||||
local mod_manager = Managers.mod
|
|
||||||
if mod_manager and mod_manager.set_developer_mode then
|
|
||||||
mod_manager:set_developer_mode(dmf:get("developer_mode"))
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- ####################################################################################################################
|
-- ####################################################################################################################
|
||||||
-- ##### Script #######################################################################################################
|
-- ##### Script #######################################################################################################
|
||||||
-- ####################################################################################################################
|
-- ####################################################################################################################
|
||||||
|
|
||||||
dmf.initialize_options = function()
|
dmf.initialize_mod_data(dmf, dmf_mod_data)
|
||||||
dmf.initialize_mod_data(dmf, dmf_mod_data)
|
|
||||||
|
|
||||||
-- first DMF initialization
|
-- first DMF initialization
|
||||||
-- it will be run only 1 time, when the player launch the game with DMF for the first time
|
-- it will be run only 1 time, when the player launch the game with DMF for the first time
|
||||||
if not dmf:get("dmf_initialized") then
|
if not dmf:get("dmf_initialized") then
|
||||||
|
|
||||||
dmf.load_logging_settings()
|
dmf.load_logging_settings()
|
||||||
dmf.load_developer_mode_settings()
|
dmf.load_developer_mode_settings()
|
||||||
|
@ -282,11 +277,4 @@ dmf.initialize_options = function()
|
||||||
|
|
||||||
dmf:notify(dmf:localize("dmf_first_run_notification"))
|
dmf:notify(dmf:localize("dmf_first_run_notification"))
|
||||||
dmf:set("dmf_initialized", true)
|
dmf:set("dmf_initialized", true)
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- If we're already in the game (likely a mod reload), we
|
|
||||||
-- can run the initialization immediately.
|
|
||||||
if Main._sm:current_state_name() == "StateGame" then
|
|
||||||
dmf.initialize_options()
|
|
||||||
end
|
end
|
|
@ -33,7 +33,7 @@ local _queued_command
|
||||||
|
|
||||||
local function initialize_drawing_function()
|
local function initialize_drawing_function()
|
||||||
if not _commands_list_gui_draw then
|
if not _commands_list_gui_draw then
|
||||||
local commands_list_gui = dmf:dofile("scripts/mods/dmf/modules/ui/chat/commands_list_gui")
|
local commands_list_gui = dmf:io_dofile("dmf/scripts/mods/dmf/modules/ui/chat/commands_list_gui")
|
||||||
_commands_list_gui_draw = commands_list_gui.draw
|
_commands_list_gui_draw = commands_list_gui.draw
|
||||||
_commands_list_gui_destroy = commands_list_gui.destroy
|
_commands_list_gui_destroy = commands_list_gui.destroy
|
||||||
end
|
end
|
|
@ -30,8 +30,8 @@ end
|
||||||
-- ##### DMF Options View Class #######################################################################################
|
-- ##### DMF Options View Class #######################################################################################
|
||||||
-- ####################################################################################################################
|
-- ####################################################################################################################
|
||||||
|
|
||||||
local _content_blueprints = dmf:dofile("scripts/mods/dmf/modules/ui/options/dmf_options_view_content_blueprints")
|
local _content_blueprints = dmf:io_dofile("dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view_content_blueprints")
|
||||||
local _view_settings = dmf:dofile("scripts/mods/dmf/modules/ui/options/dmf_options_view_settings")
|
local _view_settings = dmf:io_dofile("dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view_settings")
|
||||||
|
|
||||||
local InputUtils = require("scripts/managers/input/input_utils")
|
local InputUtils = require("scripts/managers/input/input_utils")
|
||||||
local ScriptWorld = require("scripts/foundation/utilities/script_world")
|
local ScriptWorld = require("scripts/foundation/utilities/script_world")
|
||||||
|
@ -51,7 +51,7 @@ local _last_selected_category_widget
|
||||||
local DMFOptionsView = class("DMFOptionsView", "BaseView")
|
local DMFOptionsView = class("DMFOptionsView", "BaseView")
|
||||||
|
|
||||||
DMFOptionsView.init = function (self, settings)
|
DMFOptionsView.init = function (self, settings)
|
||||||
local definitions = dmf:dofile("scripts/mods/dmf/modules/ui/options/dmf_options_view_definitions")
|
local definitions = dmf:io_dofile("dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view_definitions")
|
||||||
|
|
||||||
DMFOptionsView.super.init(self, definitions, settings)
|
DMFOptionsView.super.init(self, definitions, settings)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
local dmf = get_mod("DMF")
|
local dmf = get_mod("DMF")
|
||||||
|
|
||||||
local _view_settings = dmf:dofile("scripts/mods/dmf/modules/ui/options/dmf_options_view_settings")
|
local _view_settings = dmf:io_dofile("dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view_settings")
|
||||||
|
|
||||||
local ButtonPassTemplates = require("scripts/ui/pass_templates/button_pass_templates")
|
local ButtonPassTemplates = require("scripts/ui/pass_templates/button_pass_templates")
|
||||||
local CheckboxPassTemplates = require("scripts/ui/pass_templates/checkbox_pass_templates")
|
local CheckboxPassTemplates = require("scripts/ui/pass_templates/checkbox_pass_templates")
|
|
@ -1,6 +1,6 @@
|
||||||
local dmf = get_mod("DMF")
|
local dmf = get_mod("DMF")
|
||||||
|
|
||||||
local _view_settings = dmf:dofile("scripts/mods/dmf/modules/ui/options/dmf_options_view_settings")
|
local _view_settings = dmf:io_dofile("dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view_settings")
|
||||||
|
|
||||||
local ScrollbarPassTemplates = require("scripts/ui/pass_templates/scrollbar_pass_templates")
|
local ScrollbarPassTemplates = require("scripts/ui/pass_templates/scrollbar_pass_templates")
|
||||||
local UIFontSettings = require("scripts/managers/ui/ui_font_settings")
|
local UIFontSettings = require("scripts/managers/ui/ui_font_settings")
|
|
@ -568,10 +568,10 @@ end
|
||||||
|
|
||||||
|
|
||||||
dmf.initialize_dmf_options_view = function ()
|
dmf.initialize_dmf_options_view = function ()
|
||||||
dmf:add_require_path("scripts/mods/dmf/modules/ui/options/dmf_options_view")
|
dmf:add_require_path("dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view")
|
||||||
dmf:add_require_path("scripts/mods/dmf/modules/ui/options/dmf_options_view_definitions")
|
dmf:add_require_path("dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view_definitions")
|
||||||
dmf:add_require_path("scripts/mods/dmf/modules/ui/options/dmf_options_view_settings")
|
dmf:add_require_path("dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view_settings")
|
||||||
dmf:add_require_path("scripts/mods/dmf/modules/ui/options/dmf_options_view_content_blueprints")
|
dmf:add_require_path("dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view_content_blueprints")
|
||||||
|
|
||||||
dmf:register_view({
|
dmf:register_view({
|
||||||
view_name = "dmf_options_view",
|
view_name = "dmf_options_view",
|
||||||
|
@ -586,7 +586,7 @@ dmf.initialize_dmf_options_view = function ()
|
||||||
load_always = true,
|
load_always = true,
|
||||||
load_in_hub = true,
|
load_in_hub = true,
|
||||||
package = "packages/ui/views/options_view/options_view",
|
package = "packages/ui/views/options_view/options_view",
|
||||||
path = "scripts/mods/dmf/modules/ui/options/dmf_options_view",
|
path = "dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view",
|
||||||
state_bound = true,
|
state_bound = true,
|
||||||
enter_sound_events = {
|
enter_sound_events = {
|
||||||
"wwise/events/ui/play_ui_enter_short"
|
"wwise/events/ui/play_ui_enter_short"
|
||||||
|
@ -607,7 +607,7 @@ dmf.initialize_dmf_options_view = function ()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
dmf:dofile("scripts/mods/dmf/modules/ui/options/dmf_options_view")
|
dmf:io_dofile("dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- ####################################################################################################################
|
-- ####################################################################################################################
|
18
dtmt.cfg
18
dtmt.cfg
|
@ -1,18 +0,0 @@
|
||||||
id = "DMF"
|
|
||||||
name = "Darktide Mod Framework"
|
|
||||||
summary = "An open-source, community-run framework that provides enhanced Darktide modding support."
|
|
||||||
version = "2023-05-10"
|
|
||||||
author = "Aussiemon"
|
|
||||||
image = "assets/dmf_logo_black.png"
|
|
||||||
|
|
||||||
categories = [
|
|
||||||
Tools
|
|
||||||
]
|
|
||||||
|
|
||||||
resources = {
|
|
||||||
init = "scripts/mods/dmf/dmf_loader"
|
|
||||||
}
|
|
||||||
|
|
||||||
packages = [
|
|
||||||
"packages/dmf"
|
|
||||||
]
|
|
|
@ -1,3 +0,0 @@
|
||||||
lua = [
|
|
||||||
"scripts/mods/dmf/*"
|
|
||||||
]
|
|
Loading…
Add table
Reference in a new issue