Files
gen1recomp/tests/modkit/cases/platform_lifecycle_hooks.lua
T
2026-08-12 09:22:30 -04:00

91 lines
3.0 KiB
Lua

-- core.update / core.quit_to_launcher through the public mod API: a
-- platform-launcher integration can pause the simulation and veto the
-- return-to-launcher decision from a mod, with no main.lua patch.
package.path = "./?.lua;./?/init.lua;" .. package.path
local T = require("tests.modkit")
local PlatformHooks = require("src.core.PlatformHooks")
local FIXTURE = {
["mods/fix_platform_bridge/manifest.json"] = [[{
"id": "fix_platform_bridge",
"name": "Fixture Platform Bridge",
"version": "1.0.0",
"entry": "main.lua",
"api": 2
}]],
["mods/fix_platform_bridge/main.lua"] = [[
local mod = ...
local paused = false
local extraPolls = 0
mod.hooks:wrap("core.update", function(nextFn, game, dt)
extraPolls = extraPolls + 1
if not paused then nextFn(game, dt) end
end)
local vetoQuit = false
mod.hooks:wrap("core.quit_to_launcher", function(nextFn)
if vetoQuit then return false end
return nextFn()
end)
-- test-only knobs on mod.exports: a sandboxed mod has no shared _G to
-- smuggle them through (src/mods/Sandbox.lua)
mod.exports.setPaused = function(v) paused = v end
mod.exports.extraPolls = function() return extraPolls end
mod.exports.setVetoQuit = function(v) vetoQuit = v end
]],
}
-- core.update: a subscriber can pause (skip vanilla) and still run every frame
do
local run = T.sdk.loadMods({ "mods/fix_platform_bridge" },
{ fs = T.sdk.memfs(FIXTURE) })
T.eq(#run.errors, 0,
"the fixture mod loads clean (" .. tostring(run.errors[1]) .. ")")
local bridge = run.loader.exports.fix_platform_bridge
local calls = 0
local fakeGame = { update = function(self, dt) calls = calls + 1 end }
bridge.setPaused(false)
PlatformHooks.update(fakeGame, 1 / 60)
T.eq(calls, 1, "unpaused: vanilla Game:update runs")
T.eq(bridge.extraPolls(), 1,
"the subscriber's wrapper runs every frame")
bridge.setPaused(true)
PlatformHooks.update(fakeGame, 1 / 60)
T.eq(calls, 1, "paused: vanilla Game:update is skipped")
T.eq(bridge.extraPolls(), 2,
"the subscriber keeps polling every frame while paused")
run.release()
end
-- core.quit_to_launcher: a subscriber can veto without the vanilla
-- condition ever running, or pass it through unchanged
do
local run = T.sdk.loadMods({ "mods/fix_platform_bridge" },
{ fs = T.sdk.memfs(FIXTURE) })
T.eq(#run.errors, 0,
"the fixture mod loads clean (" .. tostring(run.errors[1]) .. ")")
local bridge = run.loader.exports.fix_platform_bridge
bridge.setVetoQuit(true)
local vanillaCalls = 0
local vetoed = PlatformHooks.quitToLauncher(function()
vanillaCalls = vanillaCalls + 1
return true
end)
T.eq(vetoed, false, "a subscriber can veto the return-to-launcher decision")
T.eq(vanillaCalls, 0, "a veto never evaluates the vanilla condition")
bridge.setVetoQuit(false)
local passed = PlatformHooks.quitToLauncher(function() return true end)
T.eq(passed, true, "with no veto, the vanilla decision passes through unchanged")
run.release()
end
T.finish("platform_lifecycle_hooks")