Compare commits
2 commits
5ac66779c2
...
9882720675
Author | SHA1 | Date | |
---|---|---|---|
9882720675 | |||
1df5f47c2c |
2 changed files with 95 additions and 95 deletions
|
@ -11,100 +11,6 @@ local log = function(category, format, ...)
|
||||||
end
|
end
|
||||||
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()
|
|
||||||
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)
|
|
||||||
local done, error = self:_state_update(dt)
|
|
||||||
local params = self._params
|
|
||||||
|
|
||||||
if error then
|
|
||||||
return StateError, { error }
|
|
||||||
elseif done then
|
|
||||||
local next_index = params.sub_state_index + 1
|
|
||||||
params.sub_state_index = next_index
|
|
||||||
local next_state_data = params.states[next_index]
|
|
||||||
|
|
||||||
if next_state_data then
|
|
||||||
return next_state_data[1], self._params
|
|
||||||
else
|
|
||||||
self._parent:sub_states_done()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local StateBootLoadMods = class("StateBootLoadMods", "StateBootSubStateBase")
|
|
||||||
|
|
||||||
StateBootLoadMods.on_enter = function(self, parent, params)
|
|
||||||
log("StateBootLoadMods", "Entered")
|
|
||||||
StateBootLoadMods.super.on_enter(self, parent, params)
|
|
||||||
|
|
||||||
local state_params = self:_state_params()
|
|
||||||
local package_manager = state_params.package_manager
|
|
||||||
|
|
||||||
self._state = "load_package"
|
|
||||||
self._package_manager = package_manager
|
|
||||||
self._package_handles = {
|
|
||||||
["packages/mods"] = package_manager:load("packages/mods", "StateBootLoadMods", nil),
|
|
||||||
["packages/dml"] = package_manager:load("packages/dml", "StateBootLoadMods", nil),
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
StateBootLoadMods._state_update = function(self, dt)
|
|
||||||
local state = self._state
|
|
||||||
local package_manager = self._package_manager
|
|
||||||
|
|
||||||
if state == "load_package" and package_manager:update() then
|
|
||||||
log("StateBootLoadMods", "Packages loaded, loading mods")
|
|
||||||
self._state = "load_mods"
|
|
||||||
local DML = require("scripts/mods/dml/init")
|
|
||||||
|
|
||||||
local mod_data = require("scripts/mods/mod_data")
|
|
||||||
local mod_loader = DML.create_loader(mod_data, self._parent:gui())
|
|
||||||
|
|
||||||
self._dml = DML
|
|
||||||
Managers.mod = mod_loader
|
|
||||||
elseif state == "load_mods" and self._dml.update(Managers.mod, dt) then
|
|
||||||
log("StateBootLoadMods", "Mods loaded, exiting")
|
|
||||||
return true, false
|
|
||||||
end
|
|
||||||
|
|
||||||
return false, false
|
|
||||||
end
|
|
||||||
|
|
||||||
local GameStateMachine = require("scripts/foundation/utilities/game_state_machine")
|
|
||||||
|
|
||||||
local patched = false
|
|
||||||
|
|
||||||
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`.
|
|
||||||
-- We do want to wait until then, so that most of the game's core
|
|
||||||
-- systems are at least loaded and can be hooked, even if they aren't
|
|
||||||
-- running, yet.
|
|
||||||
local pos = 4
|
|
||||||
table.insert(params.states, pos, {
|
|
||||||
StateBootLoadMods,
|
|
||||||
{
|
|
||||||
package_manager = params.package_manager,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
GameStateMachine_init(self, parent, start_state, params, ...)
|
|
||||||
end
|
|
||||||
|
|
||||||
log("mod_main", "Mod patching complete")
|
|
||||||
end
|
|
||||||
|
|
||||||
log("mod_main", "Initializing mods...")
|
log("mod_main", "Initializing mods...")
|
||||||
|
|
||||||
local require_store = {}
|
local require_store = {}
|
||||||
|
@ -199,6 +105,98 @@ end
|
||||||
require("scripts/main")
|
require("scripts/main")
|
||||||
log("mod_main", "'scripts/main' loaded")
|
log("mod_main", "'scripts/main' loaded")
|
||||||
|
|
||||||
|
-- Inject our state into the game. The state needs to run after `StateGame._init_managers`,
|
||||||
|
-- since some parts of DMF, and presumably other mods, depend on some of those managers to exist.
|
||||||
|
local function patch_mod_loading_state()
|
||||||
|
local StateBootSubStateBase = require("scripts/game_states/boot/state_boot_sub_state_base")
|
||||||
|
local StateBootLoadDML = class("StateBootLoadDML", "StateBootSubStateBase")
|
||||||
|
local StateGameLoadMods = class("StateGameLoadMods")
|
||||||
|
|
||||||
|
StateBootLoadDML.on_enter = function(self, parent, params)
|
||||||
|
log("StateBootLoadDML", "Entered")
|
||||||
|
StateBootLoadDML.super.on_enter(self, parent, params)
|
||||||
|
|
||||||
|
local state_params = self:_state_params()
|
||||||
|
local package_manager = state_params.package_manager
|
||||||
|
|
||||||
|
self._package_manager = package_manager
|
||||||
|
self._package_handles = {
|
||||||
|
["packages/mods"] = package_manager:load("packages/mods", "StateBootDML", nil),
|
||||||
|
["packages/dml"] = package_manager:load("packages/dml", "StateBootDML", nil),
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
StateBootLoadDML._state_update = function(self, dt)
|
||||||
|
local package_manager = self._package_manager
|
||||||
|
|
||||||
|
if package_manager:update() then
|
||||||
|
local DML = require("scripts/mods/dml/init")
|
||||||
|
local mod_data = require("scripts/mods/mod_data")
|
||||||
|
local mod_loader = DML.create_loader(mod_data)
|
||||||
|
Managers.mod = mod_loader
|
||||||
|
log("StateBootLoadDML", "DML loaded, exiting")
|
||||||
|
return true, false
|
||||||
|
end
|
||||||
|
|
||||||
|
return false, false
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function StateGameLoadMods:on_enter(_, params)
|
||||||
|
log("StateGameLoadMods", "Entered")
|
||||||
|
self._next_state = require("scripts/game_states/game/state_splash")
|
||||||
|
self._next_state_params = params
|
||||||
|
end
|
||||||
|
|
||||||
|
function StateGameLoadMods:update(main_dt)
|
||||||
|
local state = self._loading_state
|
||||||
|
|
||||||
|
-- We're relying on the fact that DML internally makes sure
|
||||||
|
-- that `Managers.mod:update()` is being called appropriately.
|
||||||
|
-- The implementation as of this writing is to hook `StateGame.update`.
|
||||||
|
if Managers.mod:all_mods_loaded() then
|
||||||
|
Log.info("StateGameLoadMods", "Mods loaded, exiting")
|
||||||
|
return self._next_state, self._next_state_params
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local GameStateMachine = require("scripts/foundation/utilities/game_state_machine")
|
||||||
|
local GameStateMachine_init = GameStateMachine.init
|
||||||
|
GameStateMachine.init = function(self, parent, start_state, params, creation_context, state_change_callbacks, name)
|
||||||
|
if name == "Main" then
|
||||||
|
log("mod_main", "Injecting StateBootLoadDML")
|
||||||
|
|
||||||
|
-- Hardcoded position after `StateRequireScripts`.
|
||||||
|
-- We need to wait until then to even begin most of our stuff,
|
||||||
|
-- so that most of the game's core systems are at least loaded and can be hooked,
|
||||||
|
-- even if they aren't running, yet.
|
||||||
|
local pos = 4
|
||||||
|
table.insert(params.states, pos, {
|
||||||
|
StateBootLoadDML,
|
||||||
|
{
|
||||||
|
package_manager = params.package_manager,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
GameStateMachine_init(self, parent, start_state, params, creation_context, state_change_callbacks, name)
|
||||||
|
elseif name == "Game" then
|
||||||
|
log("mod_main", "Injection StateGameLoadMods")
|
||||||
|
-- The second time around, we want to be the first, so we pass our own
|
||||||
|
-- 'start_state'.
|
||||||
|
-- We can't just have the state machine be initialized and then change its `_next_state`, as by the end of
|
||||||
|
-- `init`, a bunch of stuff will already be initialized.
|
||||||
|
GameStateMachine_init(self, parent, StateGameLoadMods, params, creation_context, state_change_callbacks, name)
|
||||||
|
-- And since we're done now, we can revert the function to its original
|
||||||
|
GameStateMachine.init = GameStateMachine_init
|
||||||
|
|
||||||
|
return
|
||||||
|
else
|
||||||
|
-- In all other cases, simply call the original
|
||||||
|
GameStateMachine_init(self, parent, start_state, params, creation_context, state_change_callbacks, name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- Override `init` to run our injection
|
-- Override `init` to run our injection
|
||||||
function init()
|
function init()
|
||||||
patch_mod_loading_state()
|
patch_mod_loading_state()
|
||||||
|
|
|
@ -38,7 +38,9 @@ async fn handle_action(
|
||||||
action_queue: Arc<RwLock<UnboundedReceiver<AsyncAction>>>,
|
action_queue: Arc<RwLock<UnboundedReceiver<AsyncAction>>>,
|
||||||
) {
|
) {
|
||||||
while let Some(action) = action_queue.write().await.recv().await {
|
while let Some(action) = action_queue.write().await.recv().await {
|
||||||
tracing::debug!(?action);
|
if cfg!(debug_assertions) && !matches!(action, AsyncAction::Log(_)) {
|
||||||
|
tracing::debug!(?action);
|
||||||
|
}
|
||||||
|
|
||||||
let event_sink = event_sink.clone();
|
let event_sink = event_sink.clone();
|
||||||
match action {
|
match action {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue