feat(dtmm): Move class and require hooks into early loading
These need to be executed as early as possible if they're supposed to capture all of their respective calls.
This commit is contained in:
parent
f0450285ad
commit
be1cff9f3c
1 changed files with 147 additions and 79 deletions
|
@ -1,3 +1,7 @@
|
|||
local _G = _G
|
||||
local rawget = rawget
|
||||
local rawset = rawset
|
||||
|
||||
local log = function(category, format, ...)
|
||||
local Log = rawget(_G, "Log")
|
||||
if Log then
|
||||
|
@ -7,28 +11,14 @@ local log = function(category, format, ...)
|
|||
end
|
||||
end
|
||||
|
||||
log("mod_main", " Initializing mods...")
|
||||
-- Keep a backup of certain system libraries before
|
||||
-- Fatshark's code scrubs them.
|
||||
-- The loader can then decide to pass them on to mods, or ignore them
|
||||
local libs = {
|
||||
io = io,
|
||||
debug = debug,
|
||||
ffi = ffi,
|
||||
os = os,
|
||||
load = load,
|
||||
loadfile = loadfile,
|
||||
loadstring = loadstring,
|
||||
}
|
||||
-- Patch `GameStateMachine.init` to add our own state for loading mods.
|
||||
-- In the future, Fatshark might provide us with a dedicated way to do this.
|
||||
local function patch_mod_loading_state()
|
||||
local StateBootSubStateBase = require("scripts/game_states/boot/state_boot_sub_state_base")
|
||||
|
||||
require("scripts/main")
|
||||
log("mod_main", "'scripts/main' loaded")
|
||||
|
||||
local StateBootSubStateBase = require("scripts/game_states/boot/state_boot_sub_state_base")
|
||||
|
||||
-- A necessary override.
|
||||
-- The original does not proxy `dt` to `_state_update`, but we need that.
|
||||
StateBootSubStateBase.update = function (self, dt)
|
||||
-- A necessary override.
|
||||
-- The original does not proxy `dt` to `_state_update`, but we need that.
|
||||
StateBootSubStateBase.update = function (self, dt)
|
||||
local done, error = self:_state_update(dt)
|
||||
local params = self._params
|
||||
|
||||
|
@ -45,11 +35,11 @@ StateBootSubStateBase.update = function (self, dt)
|
|||
self._parent:sub_states_done()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local StateBootLoadMods = class("StateBootLoadMods", "StateBootSubStateBase")
|
||||
local StateBootLoadMods = class("StateBootLoadMods", "StateBootSubStateBase")
|
||||
|
||||
StateBootLoadMods.on_enter = function (self, parent, params)
|
||||
StateBootLoadMods.on_enter = function (self, parent, params)
|
||||
log("StateBootLoadMods", "Entered")
|
||||
StateBootLoadMods.super.on_enter(self, parent, params)
|
||||
|
||||
|
@ -62,9 +52,9 @@ StateBootLoadMods.on_enter = function (self, parent, params)
|
|||
["packages/mods"] = package_manager:load("packages/mods", "StateBootLoadMods", nil),
|
||||
["packages/dml"] = package_manager:load("packages/dml", "StateBootLoadMods", nil),
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
StateBootLoadMods._state_update = function (self, dt)
|
||||
StateBootLoadMods._state_update = function (self, dt)
|
||||
local state = self._state
|
||||
local package_manager = self._package_manager
|
||||
|
||||
|
@ -75,19 +65,15 @@ StateBootLoadMods._state_update = function (self, dt)
|
|||
self._mod_loader = mod_loader
|
||||
|
||||
local mod_data = require("scripts/mods/mod_data")
|
||||
mod_loader:init(mod_data, libs, self._parent:gui())
|
||||
mod_loader:init(mod_data, self._parent:gui())
|
||||
elseif state == "load_mods" and self._mod_loader:update(dt) then
|
||||
log("StateBootLoadMods", "Mods loaded, exiting")
|
||||
return true, false
|
||||
end
|
||||
|
||||
return false, false
|
||||
end
|
||||
end
|
||||
|
||||
-- Patch `GameStateMachine.init` to add our own state for loading mods.
|
||||
-- In the future, Fatshark might provide us with a dedicated way to do this.
|
||||
local function patch_mod_loading_state()
|
||||
log("mod_main", "Adding mod loading state")
|
||||
local GameStateMachine = require("scripts/foundation/utilities/game_state_machine")
|
||||
|
||||
local patched = false
|
||||
|
@ -95,6 +81,7 @@ local function patch_mod_loading_state()
|
|||
local GameStateMachine_init = GameStateMachine.init
|
||||
GameStateMachine.init = function(self, parent, start_state, params, ...)
|
||||
if not patched then
|
||||
log("mod_main", "Injecting mod loading state")
|
||||
patched = true
|
||||
|
||||
-- Hardcoded position after `StateRequireScripts`.
|
||||
|
@ -112,13 +99,94 @@ local function patch_mod_loading_state()
|
|||
|
||||
GameStateMachine_init(self, parent, start_state, params, ...)
|
||||
end
|
||||
|
||||
log("mod_main", "Mod patching complete")
|
||||
end
|
||||
|
||||
log("mod_main", "Initializing mods...")
|
||||
|
||||
local require_store = {}
|
||||
|
||||
Mods = {
|
||||
-- Keep a backup of certain system libraries before
|
||||
-- Fatshark's code scrubs them.
|
||||
-- The loader can then decide to pass them on to mods, or ignore them
|
||||
lua = setmetatable({}, {
|
||||
io = io,
|
||||
debug = debug,
|
||||
ffi = ffi,
|
||||
os = os,
|
||||
load = load,
|
||||
loadfile = loadfile,
|
||||
loadstring = loadstring,
|
||||
}),
|
||||
require_store = require_store
|
||||
}
|
||||
|
||||
local can_insert = function(filepath, new_result)
|
||||
local store = require_store[filepath]
|
||||
if not store or #store then
|
||||
return true
|
||||
end
|
||||
|
||||
if store[#store] ~= new_result then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local original_require = require
|
||||
require = function(filepath, ...)
|
||||
local result = original_require(filepath, ...)
|
||||
if result and type(result) == "table" then
|
||||
if can_insert(filepath, result) then
|
||||
require_store[filepath] = require_store[filepath] or {}
|
||||
local store = require_store[filepath]
|
||||
|
||||
table.insert(store, result)
|
||||
|
||||
if Mods.hook then
|
||||
Mods.hook.enable_by_file(filepath, #store)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
require("scripts/boot_init")
|
||||
require("scripts/foundation/utilities/class")
|
||||
|
||||
-- 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 = setmetatable({}, {
|
||||
__index = function(_, key)
|
||||
return key
|
||||
end
|
||||
})
|
||||
|
||||
local original_class = class
|
||||
class = function(class_name, super_name, ...)
|
||||
local result = original_class(class_name, super_name, ...)
|
||||
if not rawget(_G, class_name) then
|
||||
rawset(_G, class_name, result)
|
||||
end
|
||||
if not rawget(_G.CLASS, class_name) then
|
||||
rawset(_G.CLASS, class_name, result)
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
require("scripts/main")
|
||||
log("mod_main", "'scripts/main' loaded")
|
||||
|
||||
-- Override `init` to run our injection
|
||||
function init()
|
||||
patch_mod_loading_state()
|
||||
|
||||
-- As requested by Fatshark
|
||||
local StateRequireScripts = require("scripts/game_states/boot/state_require_scripts")
|
||||
StateRequireScripts._get_is_modded = function() return true end
|
||||
|
||||
patch_mod_loading_state()
|
||||
Main:init()
|
||||
end
|
||||
|
|
Loading…
Add table
Reference in a new issue