diff --git a/.gitignore b/.gitignore
index 23718be..152c246 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,8 @@
.temp
.vscode
**/*.zip
+*.zip
vmf/bundleV1
vmf/bundleV2
-node_modules
\ No newline at end of file
+node_modules
+out/
diff --git a/.luacheckrc b/.luacheckrc
index fecfcdf..bbc55d1 100644
--- a/.luacheckrc
+++ b/.luacheckrc
@@ -1,16 +1,16 @@
max_line_length = 120
include_files = {
- "**/scripts/",
+ "scripts/",
}
ignore = {
- "12.", -- ignore "Setting a read-only global variable/Setting a read-only field of a global variable."
- "542", -- disable warnings for empty if branches. These are useful sometime and easy to notice otherwise.
- "21./.*_", -- disable unused warnings for variables ending with _
- "211/dmf", -- Disable warnings about unused mod object
+ "12.", -- ignore "Setting a read-only global variable/Setting a read-only field of a global variable."
+ "542", -- disable warnings for empty if branches. These are useful sometime and easy to notice otherwise.
+ "21./.*_", -- disable unused warnings for variables ending with _
+ "211/dmf", -- Disable warnings about unused mod object
"212/self", -- Disable unused self warnings.
- "611", -- disable "line contains only whitespace"
+ "611", -- disable "line contains only whitespace"
}
std = "+DT+DMF"
@@ -23,21 +23,52 @@ stds["DMF"] = {
stds["DT"] = {
read_globals = {
- string = { fields = { "split" }},
- table = { fields = {
- "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", "dump",
- "clear_array", "append_varargs", "find", "for_each", "crop", "mirror_array", "set", "create_copy", "clone",
- "contains", "add_meta_logging", "table_as_sorted_string_arrays", "clone_instance", "max", "clear", "find_by_key",
- }},
- 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",
- "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",
- "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",
- }},
- "Crashify","Keyboard","Mouse","Application","Color","Quarternion","Vector3","Vector2","RESOLUTION_LOOKUP"
+ string = { fields = { "split" } },
+ table = {
+ fields = {
+ "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",
+ "dump",
+ "clear_array", "append_varargs", "find", "for_each", "crop", "mirror_array", "set", "create_copy",
+ "clone",
+ "contains", "add_meta_logging", "table_as_sorted_string_arrays", "clone_instance", "max", "clear",
+ "find_by_key",
+ }
+ },
+ 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",
+ "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",
+ "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",
+ }
+ },
+ 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",
},
}
diff --git a/dmf/dmf.mod b/dmf/dmf.mod
deleted file mode 100644
index 75324e0..0000000
--- a/dmf/dmf.mod
+++ /dev/null
@@ -1,5 +0,0 @@
-return {
- run = function()
- return Mods.file.dofile("dmf/scripts/mods/dmf/dmf_loader")
- end
-}
diff --git a/dtmt.cfg b/dtmt.cfg
new file mode 100644
index 0000000..7d0b42a
--- /dev/null
+++ b/dtmt.cfg
@@ -0,0 +1,18 @@
+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"
+]
diff --git a/packages/dmf.package b/packages/dmf.package
new file mode 100644
index 0000000..4528468
--- /dev/null
+++ b/packages/dmf.package
@@ -0,0 +1,3 @@
+lua = [
+ "scripts/mods/dmf/*"
+]
diff --git a/dmf/scripts/mods/dmf/dmf_loader.lua b/scripts/mods/dmf/dmf_loader.lua
similarity index 55%
rename from dmf/scripts/mods/dmf/dmf_loader.lua
rename to scripts/mods/dmf/dmf_loader.lua
index c7faaf6..99a2bf4 100644
--- a/dmf/scripts/mods/dmf/dmf_loader.lua
+++ b/scripts/mods/dmf/dmf_loader.lua
@@ -3,9 +3,6 @@ local dmf
-- Native mod object used by Fatshark mod manager
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
local print = __print
@@ -14,44 +11,37 @@ local print = __print
-- #####################################################################################################################
function dmf_mod_object:init()
- io_dofile("dmf/scripts/mods/dmf/modules/dmf_mod_data")
- io_dofile("dmf/scripts/mods/dmf/modules/dmf_mod_manager")
- --io_dofile("dmf/scripts/mods/dmf/modules/dmf_dummy")
- io_dofile("dmf/scripts/mods/dmf/modules/dmf_package_manager")
- io_dofile("dmf/scripts/mods/dmf/modules/core/safe_calls")
- io_dofile("dmf/scripts/mods/dmf/modules/core/events")
- io_dofile("dmf/scripts/mods/dmf/modules/core/settings")
- io_dofile("dmf/scripts/mods/dmf/modules/core/logging")
- io_dofile("dmf/scripts/mods/dmf/modules/core/misc")
- io_dofile("dmf/scripts/mods/dmf/modules/core/persistent_tables")
- io_dofile("dmf/scripts/mods/dmf/modules/core/io")
+ dofile("scripts/mods/dmf/modules/dmf_mod_data")
+ dofile("scripts/mods/dmf/modules/dmf_mod_manager")
+ -- dofile("scripts/mods/dmf/modules/dmf_dummy")
+ dofile("scripts/mods/dmf/modules/dmf_package_manager")
+ dofile("scripts/mods/dmf/modules/core/safe_calls")
+ dofile("scripts/mods/dmf/modules/core/events")
+ dofile("scripts/mods/dmf/modules/core/settings")
+ dofile("scripts/mods/dmf/modules/core/logging")
+ dofile("scripts/mods/dmf/modules/core/misc")
+ dofile("scripts/mods/dmf/modules/core/persistent_tables")
+ dofile("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: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:hook(ModManager, "destroy", function(func, ...)
- dmf.mods_unload_event(true)
- func(...)
- end)
end
-- #####################################################################################################################
@@ -64,7 +54,7 @@ function dmf_mod_object:update(dt)
dmf.check_keybinds()
dmf.execute_queued_chat_command()
- if not dmf.all_mods_were_loaded and Managers.mod._state == "done" then
+ if not dmf.all_mods_were_loaded and Managers.mod:all_mods_loaded() then
dmf.generate_keybinds()
dmf.initialize_dmf_options_view()
@@ -97,8 +87,21 @@ function dmf_mod_object:on_reload()
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)
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.save_unsaved_settings_to_file()
dmf.apply_delayed_hooks()
diff --git a/dmf/localization/dmf.lua b/scripts/mods/dmf/localization/dmf.lua
similarity index 100%
rename from dmf/localization/dmf.lua
rename to scripts/mods/dmf/localization/dmf.lua
diff --git a/dmf/scripts/mods/dmf/modules/core/chat.lua b/scripts/mods/dmf/modules/core/chat.lua
similarity index 100%
rename from dmf/scripts/mods/dmf/modules/core/chat.lua
rename to scripts/mods/dmf/modules/core/chat.lua
diff --git a/dmf/scripts/mods/dmf/modules/core/commands.lua b/scripts/mods/dmf/modules/core/commands.lua
similarity index 100%
rename from dmf/scripts/mods/dmf/modules/core/commands.lua
rename to scripts/mods/dmf/modules/core/commands.lua
diff --git a/dmf/scripts/mods/dmf/modules/core/events.lua b/scripts/mods/dmf/modules/core/events.lua
similarity index 100%
rename from dmf/scripts/mods/dmf/modules/core/events.lua
rename to scripts/mods/dmf/modules/core/events.lua
diff --git a/dmf/scripts/mods/dmf/modules/core/hooks.lua b/scripts/mods/dmf/modules/core/hooks.lua
similarity index 100%
rename from dmf/scripts/mods/dmf/modules/core/hooks.lua
rename to scripts/mods/dmf/modules/core/hooks.lua
diff --git a/dmf/scripts/mods/dmf/modules/core/io.lua b/scripts/mods/dmf/modules/core/io.lua
similarity index 93%
rename from dmf/scripts/mods/dmf/modules/core/io.lua
rename to scripts/mods/dmf/modules/core/io.lua
index 13a5880..3e5e3ca 100644
--- a/dmf/scripts/mods/dmf/modules/core/io.lua
+++ b/scripts/mods/dmf/modules/core/io.lua
@@ -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 safe_call then
- status, result = pcall(function ()
+ status, result = pcall(function()
return read_or_execute(file_path, args, return_type)
end)
@@ -114,25 +114,12 @@ local function handle_io(mod, local_path, file_name, file_extension, args, safe_
-- If the initial open failed, report failure
else
- mod:error("Error opening '" .. file_path .. "': " .. tostring(err_io))
+ mod:error("Error during I/O: %s\n%s", tostring(err_io), Script.callstack())
return false
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 ########################################################################################################
-- #####################################################################################################################
@@ -142,25 +129,21 @@ 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")
end
-
-- 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)
return handle_io(self, local_path, file_name, file_extension, args, false, "exec_boolean")
end
-
-- 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)
return handle_io(self, local_path, file_name, file_extension, args, true, "exec_result")
end
-
-- 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)
return handle_io(self, local_path, file_name, file_extension, args, false, "exec_result")
end
-
-- 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.
-- IO version of the dofile method with a pcall.
@@ -168,7 +151,6 @@ function DMFMod:io_dofile(file_path)
return handle_io(self, file_path, nil, nil, nil, true, "exec_result")
end
-
-- 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.
-- IO version of the dofile method.
@@ -176,7 +158,6 @@ function DMFMod:io_dofile_unsafe(file_path)
return handle_io(self, file_path, nil, nil, nil, false, "exec_result")
end
-
-- Use the io library to return the contents of the given file
function DMFMod:io_read_content(file_path, file_extension)
return handle_io(self, file_path, nil, file_extension, nil, true, "data")
@@ -199,4 +180,4 @@ end
-- #####################################################################################################################
-- ##### Script ########################################################################################################
--- #####################################################################################################################
\ No newline at end of file
+-- #####################################################################################################################
diff --git a/dmf/scripts/mods/dmf/modules/core/keybindings.lua b/scripts/mods/dmf/modules/core/keybindings.lua
similarity index 100%
rename from dmf/scripts/mods/dmf/modules/core/keybindings.lua
rename to scripts/mods/dmf/modules/core/keybindings.lua
diff --git a/dmf/scripts/mods/dmf/modules/core/localization.lua b/scripts/mods/dmf/modules/core/localization.lua
similarity index 98%
rename from dmf/scripts/mods/dmf/modules/core/localization.lua
rename to scripts/mods/dmf/modules/core/localization.lua
index 00b8a46..3ffbf85 100644
--- a/dmf/scripts/mods/dmf/modules/core/localization.lua
+++ b/scripts/mods/dmf/modules/core/localization.lua
@@ -138,5 +138,5 @@ end
-- ##### Script #######################################################################################################
-- ####################################################################################################################
-local localization_table = dmf:io_dofile("dmf/localization/dmf")
+local localization_table = dmf:dofile("scripts/mods/dmf/localization/dmf")
dmf.initialize_mod_localization(dmf, localization_table)
diff --git a/dmf/scripts/mods/dmf/modules/core/logging.lua b/scripts/mods/dmf/modules/core/logging.lua
similarity index 99%
rename from dmf/scripts/mods/dmf/modules/core/logging.lua
rename to scripts/mods/dmf/modules/core/logging.lua
index 873b4ed..5781ab6 100644
--- a/dmf/scripts/mods/dmf/modules/core/logging.lua
+++ b/scripts/mods/dmf/modules/core/logging.lua
@@ -55,6 +55,7 @@ end
local function add_chat_message(message, sender)
local channel_sender = sender or "SYSTEM"
+ message = tostring(message)
-- Send to our stored chat element if it exists
if _chat_element then
diff --git a/dmf/scripts/mods/dmf/modules/core/misc.lua b/scripts/mods/dmf/modules/core/misc.lua
similarity index 83%
rename from dmf/scripts/mods/dmf/modules/core/misc.lua
rename to scripts/mods/dmf/modules/core/misc.lua
index b0c1f0c..7d1864e 100644
--- a/dmf/scripts/mods/dmf/modules/core/misc.lua
+++ b/scripts/mods/dmf/modules/core/misc.lua
@@ -14,8 +14,10 @@ function dmf.check_wrong_argument_type(mod, dmf_function_name, argument_name, ar
end
end
- mod:error("(%s): argument '%s' should have the '%s' type, not '%s'", dmf_function_name, argument_name,
- table.concat(allowed_types, "/"), argument_type)
+ mod:error(
+ "(%s): argument '%s' should have the '%s' type, not '%s'\n%s",
+ dmf_function_name, argument_name, table.concat(allowed_types, "/"), argument_type, Script.callstack()
+ )
return true
end
@@ -34,4 +36,4 @@ function dmf.deepcopy(original_table)
copy = original_table
end
return copy
-end
\ No newline at end of file
+end
diff --git a/dmf/scripts/mods/dmf/modules/core/mutators/mutators_default_config.lua b/scripts/mods/dmf/modules/core/mutators/mutators_default_config.lua
similarity index 100%
rename from dmf/scripts/mods/dmf/modules/core/mutators/mutators_default_config.lua
rename to scripts/mods/dmf/modules/core/mutators/mutators_default_config.lua
diff --git a/dmf/scripts/mods/dmf/modules/core/mutators/mutators_info.lua b/scripts/mods/dmf/modules/core/mutators/mutators_info.lua
similarity index 100%
rename from dmf/scripts/mods/dmf/modules/core/mutators/mutators_info.lua
rename to scripts/mods/dmf/modules/core/mutators/mutators_info.lua
diff --git a/dmf/scripts/mods/dmf/modules/core/mutators/mutators_manager.lua b/scripts/mods/dmf/modules/core/mutators/mutators_manager.lua
similarity index 97%
rename from dmf/scripts/mods/dmf/modules/core/mutators/mutators_manager.lua
rename to scripts/mods/dmf/modules/core/mutators/mutators_manager.lua
index f728962..9dde361 100644
--- a/dmf/scripts/mods/dmf/modules/core/mutators/mutators_manager.lua
+++ b/scripts/mods/dmf/modules/core/mutators/mutators_manager.lua
@@ -27,11 +27,11 @@ local _mutators_sorted = false
local _all_mutators_disabled = false
-- External modules
-local reward_manager = dmf:io_dofile("dmf/scripts/mods/dmf/modules/core/mutators/mutators_reward")
-local set_lobby_data = dmf:io_dofile("dmf/scripts/mods/dmf/modules/core/mutators/mutators_info")
+local reward_manager = dmf:dofile("scripts/mods/dmf/modules/core/mutators/mutators_reward")
+local set_lobby_data = dmf:dofile("scripts/mods/dmf/modules/core/mutators/mutators_info")
-- Get default configuration
-local _default_config = dmf:io_dofile("dmf/scripts/mods/dmf/modules/core/mutators/mutators_default_config")
+local _default_config = dmf:dofile("scripts/mods/dmf/modules/core/mutators/mutators_default_config")
-- List of enabled mutators in case DMF is reloaded in the middle of the game
local _enabled_mutators = dmf:persistent_table("enabled_mutators")
@@ -505,4 +505,4 @@ end
-- #####################################################################################################################
-- Testing
---dmf:io_dofile("dmf/scripts/mods/dmf/modules/core/mutators/test/mutators_test")
+--dmf:dofile("scripts/mods/dmf/modules/core/mutators/test/mutators_test")
diff --git a/dmf/scripts/mods/dmf/modules/core/mutators/mutators_reward.lua b/scripts/mods/dmf/modules/core/mutators/mutators_reward.lua
similarity index 100%
rename from dmf/scripts/mods/dmf/modules/core/mutators/mutators_reward.lua
rename to scripts/mods/dmf/modules/core/mutators/mutators_reward.lua
diff --git a/dmf/scripts/mods/dmf/modules/core/mutators/test/mutators_test.lua b/scripts/mods/dmf/modules/core/mutators/test/mutators_test.lua
similarity index 100%
rename from dmf/scripts/mods/dmf/modules/core/mutators/test/mutators_test.lua
rename to scripts/mods/dmf/modules/core/mutators/test/mutators_test.lua
diff --git a/dmf/scripts/mods/dmf/modules/core/network.lua b/scripts/mods/dmf/modules/core/network.lua
similarity index 100%
rename from dmf/scripts/mods/dmf/modules/core/network.lua
rename to scripts/mods/dmf/modules/core/network.lua
diff --git a/dmf/scripts/mods/dmf/modules/core/options.lua b/scripts/mods/dmf/modules/core/options.lua
similarity index 100%
rename from dmf/scripts/mods/dmf/modules/core/options.lua
rename to scripts/mods/dmf/modules/core/options.lua
diff --git a/dmf/scripts/mods/dmf/modules/core/persistent_tables.lua b/scripts/mods/dmf/modules/core/persistent_tables.lua
similarity index 100%
rename from dmf/scripts/mods/dmf/modules/core/persistent_tables.lua
rename to scripts/mods/dmf/modules/core/persistent_tables.lua
diff --git a/dmf/scripts/mods/dmf/modules/core/require.lua b/scripts/mods/dmf/modules/core/require.lua
similarity index 69%
rename from dmf/scripts/mods/dmf/modules/core/require.lua
rename to scripts/mods/dmf/modules/core/require.lua
index 2a5e08e..a52feb4 100644
--- a/dmf/scripts/mods/dmf/modules/core/require.lua
+++ b/scripts/mods/dmf/modules/core/require.lua
@@ -35,24 +35,63 @@ end
-- ##### DMFMod ########################################################################################################
-- #####################################################################################################################
--- Add a file path to be loaded through io instead of require()
+--- Loads the given file with the same semantics as Lua's `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)
add_io_require_path(path)
end
-
-- Remove a file path that was previously loaded through io instead of require()
function DMFMod:remove_require_path(path)
remove_io_require_path(path)
end
-
-- Get all instances of a file created through require()
function DMFMod:get_require_store(path)
return get_require_store(path)
end
-
-- Get a file through the original, unhooked require() function
function DMFMod:original_require(path, ...)
return original_require(path, ...)
@@ -63,9 +102,9 @@ end
-- #####################################################################################################################
-- 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
- return dmf:io_dofile(path)
+ return dmf:dofile(path)
else
local result = func(path, ...)
@@ -85,4 +124,4 @@ end)
-- #####################################################################################################################
-- ##### Script ########################################################################################################
--- #####################################################################################################################
\ No newline at end of file
+-- #####################################################################################################################
diff --git a/dmf/scripts/mods/dmf/modules/core/safe_calls.lua b/scripts/mods/dmf/modules/core/safe_calls.lua
similarity index 87%
rename from dmf/scripts/mods/dmf/modules/core/safe_calls.lua
rename to scripts/mods/dmf/modules/core/safe_calls.lua
index 866aaeb..e2b2777 100644
--- a/dmf/scripts/mods/dmf/modules/core/safe_calls.lua
+++ b/scripts/mods/dmf/modules/core/safe_calls.lua
@@ -8,16 +8,22 @@ local print = __print
-- #####################################################################################################################
local function pack_pcall(status, ...)
- return status, {n = select('#', ...), ...}
+ return status, { n = select('#', ...), ... }
end
-local function print_error_callstack(error_message)
- if type(error_message) == "table" and error_message.error then
- error_message = error_message.error
+local function print_error_callstack(err)
+ if type(err) == "table" and err.error then
+ Log.error(
+ "DMF",
+ "%s\n<>%s<>\n<>%s<>\n<>%s<>",
+ err.error, err.traceback, err.locals, err.self
+ )
+ else
+ Log.error("DMF", "Error: %s\n%s", tostring(err), Script.callstack())
end
- print("Error: " .. tostring(error_message) .. "\n" .. Script.callstack())
- return error_message
+
+ return err
end
@@ -40,12 +46,6 @@ function DMFMod:pcall(...)
return dmf.safe_call(self, "(pcall)", ...)
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 ##########################################################################
-- #####################################################################################################################
@@ -60,7 +60,6 @@ function dmf.safe_call(mod, error_prefix_data, func, ...)
return success, unpack(return_values, 1, return_values.n)
end
-
-- Safe Call [No return values]
function dmf.safe_call_nr(mod, error_prefix_data, func, ...)
local success, error_message = xpcall(func, print_error_callstack, ...)
@@ -70,7 +69,6 @@ function dmf.safe_call_nr(mod, error_prefix_data, func, ...)
return success
end
-
-- Safe Call [No return values and error callstack]
function dmf.safe_call_nrc(mod, error_prefix_data, func, ...)
local success, error_message = pcall(func, ...)
@@ -80,7 +78,6 @@ function dmf.safe_call_nrc(mod, error_prefix_data, func, ...)
return success
end
-
-- Safe Call [dofile]
function dmf.safe_call_dofile(mod, error_prefix_data, file_path)
if type(file_path) ~= "string" then
@@ -90,7 +87,6 @@ function dmf.safe_call_dofile(mod, error_prefix_data, file_path)
return dmf.safe_call(mod, error_prefix_data, dofile, file_path)
end
-
-- Safe Call [io_dofile]
function dmf.safe_call_io_dofile(mod, error_prefix_data, file_path)
if type(file_path) ~= "string" then
@@ -100,7 +96,6 @@ 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)
end
-
-- Format error message and throw error.
function dmf.throw_error(error_message, ...)
error(string.format(error_message, ...), 0)
diff --git a/dmf/scripts/mods/dmf/modules/core/settings.lua b/scripts/mods/dmf/modules/core/settings.lua
similarity index 100%
rename from dmf/scripts/mods/dmf/modules/core/settings.lua
rename to scripts/mods/dmf/modules/core/settings.lua
diff --git a/dmf/scripts/mods/dmf/modules/core/toggling.lua b/scripts/mods/dmf/modules/core/toggling.lua
similarity index 100%
rename from dmf/scripts/mods/dmf/modules/core/toggling.lua
rename to scripts/mods/dmf/modules/core/toggling.lua
diff --git a/dmf/scripts/mods/dmf/modules/debug/dev_console.lua b/scripts/mods/dmf/modules/debug/dev_console.lua
similarity index 100%
rename from dmf/scripts/mods/dmf/modules/debug/dev_console.lua
rename to scripts/mods/dmf/modules/debug/dev_console.lua
diff --git a/dmf/scripts/mods/dmf/modules/debug/table_dump.lua b/scripts/mods/dmf/modules/debug/table_dump.lua
similarity index 100%
rename from dmf/scripts/mods/dmf/modules/debug/table_dump.lua
rename to scripts/mods/dmf/modules/debug/table_dump.lua
diff --git a/dmf/scripts/mods/dmf/modules/dmf_dummy.lua b/scripts/mods/dmf/modules/dmf_dummy.lua
similarity index 100%
rename from dmf/scripts/mods/dmf/modules/dmf_dummy.lua
rename to scripts/mods/dmf/modules/dmf_dummy.lua
diff --git a/dmf/scripts/mods/dmf/modules/dmf_mod_data.lua b/scripts/mods/dmf/modules/dmf_mod_data.lua
similarity index 93%
rename from dmf/scripts/mods/dmf/modules/dmf_mod_data.lua
rename to scripts/mods/dmf/modules/dmf_mod_data.lua
index 0af0efa..43baaef 100644
--- a/dmf/scripts/mods/dmf/modules/dmf_mod_data.lua
+++ b/scripts/mods/dmf/modules/dmf_mod_data.lua
@@ -24,7 +24,7 @@ function DMFMod:init(mod_name)
self._data = setmetatable({}, {
__index = {},
- __newindex = function(t_, k)
+ __newindex = function(_, k)
self:warning("Attempt to change internal mod data value (\"%s\"). Changing internal mod data is forbidden.", k)
end
})
@@ -34,10 +34,11 @@ function DMFMod:init(mod_name)
set_internal_data(self, "is_togglable", false)
set_internal_data(self, "is_mutator", false)
- local vanilla_mod_data = Managers.mod._mods[Managers.mod._mod_load_index]
+ local vanilla_mod_data = Managers.mod:mod_data(mod_name)
set_internal_data(self, "workshop_id", vanilla_mod_data.id)
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,
vanilla_mod_data.id))
diff --git a/dmf/scripts/mods/dmf/modules/dmf_mod_manager.lua b/scripts/mods/dmf/modules/dmf_mod_manager.lua
similarity index 94%
rename from dmf/scripts/mods/dmf/modules/dmf_mod_manager.lua
rename to scripts/mods/dmf/modules/dmf_mod_manager.lua
index fe70f0b..31bc1f5 100644
--- a/dmf/scripts/mods/dmf/modules/dmf_mod_manager.lua
+++ b/scripts/mods/dmf/modules/dmf_mod_manager.lua
@@ -50,7 +50,11 @@ local function resolve_resource(mod, error_prefix_data, resource, resource_value
local type_value = type(resource_value)
if type_value == "string" then
- return dmf.safe_call_io_dofile(mod, error_prefix_data, resource_value)
+ 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)
+ end
elseif type_value == "function" then
return dmf.safe_call(mod, error_prefix_data, resource_value, mod)
elseif type_value == "table" then
@@ -131,7 +135,6 @@ function new_mod(mod_name, mod_resources)
return mod
end
-
function get_mod(mod_name)
return _mods[mod_name]
end
@@ -170,11 +173,13 @@ function dmf.initialize_mod_data(mod, mod_data)
-- Mod's options initialization
if mod_data.options or (not mod_data.is_mutator and not mod_data.options_widgets) then
- local success, error_message = pcall(dmf.initialize_mod_options, mod, mod_data.options)
- if not success then
- mod:error(ERRORS.REGULAR.mod_options_initializing_failed, error_message)
- return
- end
+ dmf.safe_call(
+ dmf,
+ ERRORS.REGULAR.mod_options_initializing_failed,
+ dmf.initialize_mod_options,
+ mod,
+ mod_data.options
+ )
end
-- Textures initialization @TODO: move to a separate function
diff --git a/dmf/scripts/mods/dmf/modules/dmf_options.lua b/scripts/mods/dmf/modules/dmf_options.lua
similarity index 90%
rename from dmf/scripts/mods/dmf/modules/dmf_options.lua
rename to scripts/mods/dmf/modules/dmf_options.lua
index c8ccf72..ab12726 100644
--- a/dmf/scripts/mods/dmf/modules/dmf_options.lua
+++ b/scripts/mods/dmf/modules/dmf_options.lua
@@ -249,32 +249,44 @@ dmf.on_setting_changed = function (setting_id)
end
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)
+
+ 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
-- ####################################################################################################################
-- ##### Script #######################################################################################################
-- ####################################################################################################################
-dmf.initialize_mod_data(dmf, dmf_mod_data)
+dmf.initialize_options = function()
+ dmf.initialize_mod_data(dmf, dmf_mod_data)
--- first DMF initialization
--- 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
+ -- first DMF initialization
+ -- 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
- dmf.load_logging_settings()
- dmf.load_developer_mode_settings()
- dmf.load_network_settings()
- dmf.load_custom_textures_settings()
- dmf.load_dev_console_settings()
- dmf.load_chat_history_settings()
+ dmf.load_logging_settings()
+ dmf.load_developer_mode_settings()
+ dmf.load_network_settings()
+ dmf.load_custom_textures_settings()
+ dmf.load_dev_console_settings()
+ dmf.load_chat_history_settings()
- -- Not necessary until the view is loaded
- if dmf.load_dmf_options_view_settings then
- dmf.load_dmf_options_view_settings()
+ -- Not necessary until the view is loaded
+ if dmf.load_dmf_options_view_settings then
+ dmf.load_dmf_options_view_settings()
+ end
+
+ dmf:notify(dmf:localize("dmf_first_run_notification"))
+ dmf:set("dmf_initialized", true)
end
-
- dmf:notify(dmf:localize("dmf_first_run_notification"))
- dmf:set("dmf_initialized", true)
+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
diff --git a/dmf/scripts/mods/dmf/modules/dmf_package_manager.lua b/scripts/mods/dmf/modules/dmf_package_manager.lua
similarity index 100%
rename from dmf/scripts/mods/dmf/modules/dmf_package_manager.lua
rename to scripts/mods/dmf/modules/dmf_package_manager.lua
diff --git a/dmf/scripts/mods/dmf/modules/gui/custom_textures.lua b/scripts/mods/dmf/modules/gui/custom_textures.lua
similarity index 100%
rename from dmf/scripts/mods/dmf/modules/gui/custom_textures.lua
rename to scripts/mods/dmf/modules/gui/custom_textures.lua
diff --git a/dmf/scripts/mods/dmf/modules/gui/custom_views.lua b/scripts/mods/dmf/modules/gui/custom_views.lua
similarity index 100%
rename from dmf/scripts/mods/dmf/modules/gui/custom_views.lua
rename to scripts/mods/dmf/modules/gui/custom_views.lua
diff --git a/dmf/scripts/mods/dmf/modules/ui/chat/chat_actions.lua b/scripts/mods/dmf/modules/ui/chat/chat_actions.lua
similarity index 98%
rename from dmf/scripts/mods/dmf/modules/ui/chat/chat_actions.lua
rename to scripts/mods/dmf/modules/ui/chat/chat_actions.lua
index 1778c19..9f93366 100644
--- a/dmf/scripts/mods/dmf/modules/ui/chat/chat_actions.lua
+++ b/scripts/mods/dmf/modules/ui/chat/chat_actions.lua
@@ -33,7 +33,7 @@ local _queued_command
local function initialize_drawing_function()
if not _commands_list_gui_draw then
- local commands_list_gui = dmf:io_dofile("dmf/scripts/mods/dmf/modules/ui/chat/commands_list_gui")
+ local commands_list_gui = dmf:dofile("scripts/mods/dmf/modules/ui/chat/commands_list_gui")
_commands_list_gui_draw = commands_list_gui.draw
_commands_list_gui_destroy = commands_list_gui.destroy
end
@@ -310,4 +310,4 @@ if _chat_history_save then
_chat_history = dmf:get("chat_history") or _chat_history
end
-initialize_drawing_function()
\ No newline at end of file
+initialize_drawing_function()
diff --git a/dmf/scripts/mods/dmf/modules/ui/chat/commands_list_gui.lua b/scripts/mods/dmf/modules/ui/chat/commands_list_gui.lua
similarity index 100%
rename from dmf/scripts/mods/dmf/modules/ui/chat/commands_list_gui.lua
rename to scripts/mods/dmf/modules/ui/chat/commands_list_gui.lua
diff --git a/dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view.lua b/scripts/mods/dmf/modules/ui/options/dmf_options_view.lua
similarity index 99%
rename from dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view.lua
rename to scripts/mods/dmf/modules/ui/options/dmf_options_view.lua
index dec9be4..badfdb9 100644
--- a/dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view.lua
+++ b/scripts/mods/dmf/modules/ui/options/dmf_options_view.lua
@@ -30,8 +30,8 @@ end
-- ##### DMF Options View Class #######################################################################################
-- ####################################################################################################################
-local _content_blueprints = dmf:io_dofile("dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view_content_blueprints")
-local _view_settings = dmf:io_dofile("dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view_settings")
+local _content_blueprints = dmf:dofile("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 InputUtils = require("scripts/managers/input/input_utils")
local ScriptWorld = require("scripts/foundation/utilities/script_world")
@@ -51,7 +51,7 @@ local _last_selected_category_widget
local DMFOptionsView = class("DMFOptionsView", "BaseView")
DMFOptionsView.init = function (self, settings)
- local definitions = dmf:io_dofile("dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view_definitions")
+ local definitions = dmf:dofile("scripts/mods/dmf/modules/ui/options/dmf_options_view_definitions")
DMFOptionsView.super.init(self, definitions, settings)
diff --git a/dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view_content_blueprints.lua b/scripts/mods/dmf/modules/ui/options/dmf_options_view_content_blueprints.lua
similarity index 99%
rename from dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view_content_blueprints.lua
rename to scripts/mods/dmf/modules/ui/options/dmf_options_view_content_blueprints.lua
index e1ef44a..bcceca0 100644
--- a/dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view_content_blueprints.lua
+++ b/scripts/mods/dmf/modules/ui/options/dmf_options_view_content_blueprints.lua
@@ -1,6 +1,6 @@
local dmf = get_mod("DMF")
-local _view_settings = dmf:io_dofile("dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view_settings")
+local _view_settings = dmf:dofile("scripts/mods/dmf/modules/ui/options/dmf_options_view_settings")
local ButtonPassTemplates = require("scripts/ui/pass_templates/button_pass_templates")
local CheckboxPassTemplates = require("scripts/ui/pass_templates/checkbox_pass_templates")
diff --git a/dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view_definitions.lua b/scripts/mods/dmf/modules/ui/options/dmf_options_view_definitions.lua
similarity index 98%
rename from dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view_definitions.lua
rename to scripts/mods/dmf/modules/ui/options/dmf_options_view_definitions.lua
index d6e5069..47a17e4 100644
--- a/dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view_definitions.lua
+++ b/scripts/mods/dmf/modules/ui/options/dmf_options_view_definitions.lua
@@ -1,6 +1,6 @@
local dmf = get_mod("DMF")
-local _view_settings = dmf:io_dofile("dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view_settings")
+local _view_settings = dmf:dofile("scripts/mods/dmf/modules/ui/options/dmf_options_view_settings")
local ScrollbarPassTemplates = require("scripts/ui/pass_templates/scrollbar_pass_templates")
local UIFontSettings = require("scripts/managers/ui/ui_font_settings")
diff --git a/dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view_settings.lua b/scripts/mods/dmf/modules/ui/options/dmf_options_view_settings.lua
similarity index 100%
rename from dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view_settings.lua
rename to scripts/mods/dmf/modules/ui/options/dmf_options_view_settings.lua
diff --git a/dmf/scripts/mods/dmf/modules/ui/options/mod_options.lua b/scripts/mods/dmf/modules/ui/options/mod_options.lua
similarity index 97%
rename from dmf/scripts/mods/dmf/modules/ui/options/mod_options.lua
rename to scripts/mods/dmf/modules/ui/options/mod_options.lua
index 940eb24..dce3694 100644
--- a/dmf/scripts/mods/dmf/modules/ui/options/mod_options.lua
+++ b/scripts/mods/dmf/modules/ui/options/mod_options.lua
@@ -568,10 +568,10 @@ end
dmf.initialize_dmf_options_view = function ()
- dmf:add_require_path("dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view")
- dmf:add_require_path("dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view_definitions")
- dmf:add_require_path("dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view_settings")
- dmf:add_require_path("dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view_content_blueprints")
+ dmf:add_require_path("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("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:register_view({
view_name = "dmf_options_view",
@@ -586,7 +586,7 @@ dmf.initialize_dmf_options_view = function ()
load_always = true,
load_in_hub = true,
package = "packages/ui/views/options_view/options_view",
- path = "dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view",
+ path = "scripts/mods/dmf/modules/ui/options/dmf_options_view",
state_bound = true,
enter_sound_events = {
"wwise/events/ui/play_ui_enter_short"
@@ -607,7 +607,7 @@ dmf.initialize_dmf_options_view = function ()
}
})
- dmf:io_dofile("dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view")
+ dmf:dofile("scripts/mods/dmf/modules/ui/options/dmf_options_view")
end
-- ####################################################################################################################