refactor: Move indexed objects to local and change whitespace

This commit is contained in:
Lucas Schwiderski 2023-02-22 10:23:06 +01:00
parent a36e6f4adb
commit 15dc40b9ab
Signed by: lucas
GPG key ID: AA12679AAA6DF4D8
5 changed files with 327 additions and 302 deletions

View file

@ -10,7 +10,30 @@ ignore = {
"212/self", -- Disable unused self warnings. "212/self", -- Disable unused self warnings.
} }
std = "+DT" std = "+DT+DML"
stds["DML"] = {
read_globals = {
"MODS_HOOKS", "MODS_HOOKS_BY_FILE", "Log",
Mods = { fields = {
lua = { fields = { "debug", "io", "ffi", "os" }},
hook = { fields = {
"set",
"set_on_file",
"enable",
"enable_by_file",
"remove",
"front",
"_get_item",
"_get_item_hook",
"_patch",
}},
"original_require",
"require_store",
"original_class",
}},
},
}
stds["DT"] = { stds["DT"] = {
read_globals = { read_globals = {
@ -32,13 +55,9 @@ stds["DT"] = {
Managers = { fields = { Managers = { fields = {
"mod", "event", "chat" "mod", "event", "chat"
}}, }},
Mods = { fields = {
lua = { fields = { "debug", "io", "ffi", "os" }},
"original_require",
"require_store",
}},
"Crashify","Keyboard","Mouse","Application","Color","Quarternion","Vector3","Vector2","RESOLUTION_LOOKUP", "Crashify","Keyboard","Mouse","Application","Color","Quarternion","Vector3","Vector2","RESOLUTION_LOOKUP",
"ModManager", "Utf8", "StateGame", "ResourcePackage", "class", "Gui", "fassert", "printf", "__print", "ffi", "ModManager", "Utf8", "StateGame", "ResourcePackage", "class", "Gui", "fassert", "printf", "__print", "ffi",
"class",
}, },
} }

View file

@ -1,9 +1,13 @@
Mods.original_class = Mods.original_class or class local original_class = Mods.original_class or class
Mods.original_class = original_class
local _G = _G local _G = _G
local rawget = rawget local rawget = rawget
local rawset = rawset local rawset = rawset
-- The `__index` metamethod maps a proper identifier `CLASS.MyClassName` to the
-- stringified version of the key: `"MyClassName"`.
-- This allows using LuaCheck for the stringified class names in hook parameters.
_G.CLASS = _G.CLASS or setmetatable({}, { _G.CLASS = _G.CLASS or setmetatable({}, {
__index = function(_, key) __index = function(_, key)
return key return key
@ -11,7 +15,7 @@ _G.CLASS = _G.CLASS or setmetatable({}, {
}) })
class = function(class_name, super_name, ...) class = function(class_name, super_name, ...)
local result = Mods.original_class(class_name, super_name, ...) local result = original_class(class_name, super_name, ...)
if not rawget(_G, class_name) then if not rawget(_G, class_name) then
rawset(_G, class_name, result) rawset(_G, class_name, result)
end end

View file

@ -1,27 +1,24 @@
--[[
Mods Hook v2:
New version with better control
--]]
-- Hook structure -- Hook structure
MODS_HOOKS = MODS_HOOKS or {} MODS_HOOKS = MODS_HOOKS or {}
MODS_HOOKS_BY_FILE = MODS_HOOKS_BY_FILE or {} MODS_HOOKS_BY_FILE = MODS_HOOKS_BY_FILE or {}
local function NOOP() end
local item_template = { local item_template = {
name = "", name = "",
func = EMPTY_FUNC, func = NOOP,
hooks = {}, hooks = {},
} }
local item_hook_template = { local item_hook_template = {
name = "", name = "",
func = EMPTY_FUNC, func = NOOP,
enable = false, enable = false,
exec = EMPTY_FUNC, exec = NOOP,
} }
local Log = Log local Log = Log
local print_log_info = function(mod_name, message) local function print_log_info(mod_name, message)
Log = Log or rawget(_G, "Log") Log = Log or rawget(_G, "Log")
if Log then if Log then
Log._info(mod_name, message) Log._info(mod_name, message)
@ -30,151 +27,17 @@ local print_log_info = function(mod_name, message)
end end
end end
local print_log_warning = function(mod_name, message)
Log = Log or rawget(_G, "Log")
if Log then
Log._warning(mod_name, message)
else
print("[" .. mod_name .. "]: " .. message)
end
end
Mods.hook = {
--
-- Set hook
--
set = function(mod_name, func_name, hook_func)
local item = Mods.hook._get_item(func_name)
local item_hook = Mods.hook._get_item_hook(item, mod_name)
print_log_info(mod_name, "Hooking " .. func_name)
item_hook.enable = true
item_hook.func = hook_func
Mods.hook._patch()
end,
--
-- Set hook on every instance of the given file
--
set_on_file = function(mod_name, filepath, func_name, hook_func)
-- Add hook create function to list for the file
MODS_HOOKS_BY_FILE[filepath] = MODS_HOOKS_BY_FILE[filepath] or {}
local hook_create_func = function(this_filepath, this_index)
local dynamic_func_name = "Mods.require_store[\"" .. this_filepath .. "\"][" .. tostring(this_index) .. "]." .. func_name
Mods.hook.set(mod_name, dynamic_func_name, hook_func, false)
end
table.insert(MODS_HOOKS_BY_FILE[filepath], hook_create_func)
-- Add the new hook to every instance of the file
local all_file_instances = Mods.require_store[filepath]
if all_file_instances then
for i, item in ipairs(all_file_instances) do
if item then
hook_create_func(filepath, i)
end
end
end
end,
--
-- Enable/Disable hook
--
enable = function(value, mod_name, func_name)
for _, item in ipairs(MODS_HOOKS) do
if item.name == func_name or func_name == nil then
for _, hook in ipairs(item.hooks) do
if hook.name == mod_name then
hook.enable = value
Mods.hook._patch()
end
end
end
end
return
end,
--
-- Enable all hooks on a stored file
--
enable_by_file = function(filepath, store_index)
local all_file_instances = Mods.require_store[filepath]
local file_instance = all_file_instances and all_file_instances[store_index]
local all_file_hooks = MODS_HOOKS_BY_FILE[filepath]
if all_file_hooks and file_instance then
for i, hook_create_func in ipairs(all_file_hooks) do
hook_create_func(filepath, store_index)
end
end
end,
--
-- Remove hook from chain
--
["remove"] = function(func_name, mod_name)
for i, item in ipairs(MODS_HOOKS) do
if item.name == func_name then
if mod_name ~= nil then
for j, hook in ipairs(item.hooks) do
if hook.name == mod_name then
table.remove(item.hooks, j)
Mods.hook._patch()
end
end
else
local item_name = "MODS_HOOKS[" .. tostring(i) .. "]"
-- Restore orginal function
assert(loadstring(item.name .. " = " .. item_name .. ".func"))()
-- Remove hook function
table.remove(MODS_HOOKS, i)
return
end
end
end
return
end,
--
-- Move hook to front of the hook chain
--
front = function(mod_name, func_name)
for _, item in ipairs(MODS_HOOKS) do
if item.name == func_name or func_name == nil then
for i, hook in ipairs(item.hooks) do
if hook.name == mod_name then
local saved_hook = table.clone(hook)
table.remove(item.hooks, i)
table.insert(item.hooks, saved_hook)
Mods.hook._patch()
end
end
end
end
return
end,
-- --
-- Get function by function name -- Get function by function name
-- --
_get_func = function(func_name) local function get_func(func_name)
return assert(loadstring("return " .. func_name))() return assert(loadstring("return " .. func_name))()
end, end
-- --
-- Get item by function name -- Get item by function name
-- --
_get_item = function(func_name) local function get_item(func_name)
-- Find existing item -- Find existing item
for _, item in ipairs(MODS_HOOKS) do for _, item in ipairs(MODS_HOOKS) do
if item.name == func_name then if item.name == func_name then
@ -185,18 +48,18 @@ Mods.hook = {
-- Create new item -- Create new item
local item = table.clone(item_template) local item = table.clone(item_template)
item.name = func_name item.name = func_name
item.func = Mods.hook._get_func(func_name) item.func = get_func(func_name)
-- Save -- Save
table.insert(MODS_HOOKS, item) table.insert(MODS_HOOKS, item)
return item return item
end, end
-- --
-- Get item hook by mod name -- Get item hook by mod name
-- --
_get_item_hook = function(item, mod_name) local function get_item_hook(item, mod_name)
-- Find existing item -- Find existing item
for _, hook in ipairs(item.hooks) do for _, hook in ipairs(item.hooks) do
if hook.name == mod_name then if hook.name == mod_name then
@ -212,12 +75,12 @@ Mods.hook = {
table.insert(item.hooks, 1, item_hook) table.insert(item.hooks, 1, item_hook)
return item_hook return item_hook
end, end
-- --
-- If settings are changed the hook itself needs to be updated -- If settings are changed the hook itself needs to be updated
-- --
_patch = function(mods_hook_item) local function patch()
for i, item in ipairs(MODS_HOOKS) do for i, item in ipairs(MODS_HOOKS) do
local item_name = "MODS_HOOKS[" .. i .. "]" local item_name = "MODS_HOOKS[" .. i .. "]"
@ -270,5 +133,143 @@ Mods.hook = {
-- Patch orginal function call -- Patch orginal function call
assert(loadstring(item.name .. " = " .. item_name .. ".hooks[" .. last_j .. "].exec"))() assert(loadstring(item.name .. " = " .. item_name .. ".hooks[" .. last_j .. "].exec"))()
end end
end, end
--
-- Set hook
--
local function set(mod_name, func_name, hook_func)
local item = get_item(func_name)
local item_hook = get_item_hook(item, mod_name)
print_log_info(mod_name, "Hooking " .. func_name)
item_hook.enable = true
item_hook.func = hook_func
patch()
end
--
-- Set hook on every instance of the given file
--
local function set_on_file(mod_name, filepath, func_name, hook_func)
-- Add hook create function to list for the file
MODS_HOOKS_BY_FILE[filepath] = MODS_HOOKS_BY_FILE[filepath] or {}
local hook_create_func = function(this_filepath, this_index)
local dynamic_func_name = string.format(
"Mods.require_store[\"%s\"][%i].%s",
this_filepath, this_index, func_name
)
set(mod_name, dynamic_func_name, hook_func, false)
end
table.insert(MODS_HOOKS_BY_FILE[filepath], hook_create_func)
-- Add the new hook to every instance of the file
local all_file_instances = Mods.require_store[filepath]
if all_file_instances then
for i, item in ipairs(all_file_instances) do
if item then
hook_create_func(filepath, i)
end
end
end
end
--
-- Enable/Disable hook
--
local function enable(value, mod_name, func_name)
for _, item in ipairs(MODS_HOOKS) do
if item.name == func_name or func_name == nil then
for _, hook in ipairs(item.hooks) do
if hook.name == mod_name then
hook.enable = value
patch()
end
end
end
end
return
end
--
-- Enable all hooks on a stored file
--
local function enable_by_file(filepath, store_index)
local all_file_instances = Mods.require_store[filepath]
local file_instance = all_file_instances and all_file_instances[store_index]
local all_file_hooks = MODS_HOOKS_BY_FILE[filepath]
if all_file_hooks and file_instance then
for _, hook_create_func in ipairs(all_file_hooks) do
hook_create_func(filepath, store_index)
end
end
end
--
-- Remove hook from chain
--
local function remove(func_name, mod_name)
for i, item in ipairs(MODS_HOOKS) do
if item.name == func_name then
if mod_name ~= nil then
for j, hook in ipairs(item.hooks) do
if hook.name == mod_name then
table.remove(item.hooks, j)
patch()
end
end
else
local item_name = "MODS_HOOKS[" .. tostring(i) .. "]"
-- Restore orginal function
assert(loadstring(item.name .. " = " .. item_name .. ".func"))()
-- Remove hook function
table.remove(MODS_HOOKS, i)
return
end
end
end
return
end
--
-- Move hook to front of the hook chain
--
local function front(mod_name, func_name)
for _, item in ipairs(MODS_HOOKS) do
if item.name == func_name or func_name == nil then
for i, hook in ipairs(item.hooks) do
if hook.name == mod_name then
local saved_hook = table.clone(hook)
table.remove(item.hooks, i)
table.insert(item.hooks, saved_hook)
patch()
end
end
end
end
return
end
Mods.hook = {
set = set,
set_on_file = set_on_file,
enable = enable,
enable_by_file = enable_by_file,
remove = remove,
front = front,
_get_item = get_item,
_get_item_hook = get_item_hook,
_patch = patch,
} }

View file

@ -3,7 +3,6 @@
local loader = {} local loader = {}
Mods = { Mods = {
hook = {},
lua = setmetatable({}, { lua = setmetatable({}, {
__index = { debug = debug, io = io, ffi = ffi, os = os }, __index = { debug = debug, io = io, ffi = ffi, os = os },
}), }),
@ -11,7 +10,7 @@ Mods = {
dofile("scripts/mods/dml/require") dofile("scripts/mods/dml/require")
dofile("scripts/mods/dml/class") dofile("scripts/mods/dml/class")
dofile("scripts/mods/dml/hook") Mods.hook = dofile("scripts/mods/dml/hook")
function loader:init(boot_gui, mod_data) function loader:init(boot_gui, mod_data)
local ModLoader = dofile("scripts/mods/dml/mod_loader") local ModLoader = dofile("scripts/mods/dml/mod_loader")

View file

@ -1,30 +1,32 @@
Mods.require_store = Mods.require_store or {} local require_store = Mods.require_store or {}
Mods.original_require = Mods.original_require or require Mods.require_store = require_store
local original_require = Mods.original_require or require
Mods.original_require = original_require
local can_insert = function(filepath, new_result) local can_insert = function(filepath, new_result)
local store = Mods.require_store[filepath] local store = require_store[filepath]
if not store or #store == 0 then local num_store = #store
if not store or num_store == 0 then
return true return true
end end
if store[#store] ~= new_result then if store[num_store] ~= new_result then
return true return true
end end
end end
require = function(filepath, ...) require = function(filepath, ...)
local Mods = Mods local result = original_require(filepath, ...)
local result = Mods.original_require(filepath, ...)
if result and type(result) == "table" then if result and type(result) == "table" then
if can_insert(filepath, result) then if can_insert(filepath, result) then
Mods.require_store[filepath] = Mods.require_store[filepath] or {} require_store[filepath] = require_store[filepath] or {}
local store = Mods.require_store[filepath] local store = require_store[filepath]
table.insert(store, result) table.insert(store, result)
--print("[Require] #" .. tostring(#store) .. " of " .. filepath) --print("[Require] #" .. tostring(#store) .. " of " .. filepath)
local Mods = Mods
if Mods.hook then if Mods.hook then
Mods.hook.enable_by_file(filepath, #store) Mods.hook.enable_by_file(filepath, #store)
end end