diff --git a/lib/StadiumInstall.lua b/lib/StadiumInstall.lua index d1ec135..d706437 100644 --- a/lib/StadiumInstall.lua +++ b/lib/StadiumInstall.lua @@ -189,22 +189,46 @@ local function shipped() return true end --- Whether the STADIUM rungs can be offered at all: either the packs have been --- built from the player's ROM, or the mod folder already carries a set. +-- Whether the packs on disk can be READ, even if they are not current. +-- +-- Format and count, but deliberately NOT rev. The distinction matters on an +-- upgrade: a rev bump means the packs are out of date, not that they are +-- unreadable, and treating the two the same is what would make the STADIUM +-- rungs disappear off the options row for anyone whose cache predates it. +-- Losing the recolour until a rebuild is a blemish; losing the mode is not. +function StadiumInstall.usable() + local m = readMarker() + return (m ~= nil and m.format == StadiumInstall.FORMAT + and m.count == StadiumInstall.COUNT) and true or false +end + +-- Whether the STADIUM rungs can be offered at all: the packs have been built +-- from the player's ROM (current or merely readable), or the mod folder +-- already carries a set. function StadiumInstall.available() if StadiumInstall.ready() then return true end + if StadiumInstall.usable() then return true end return shipped() end --- Whether there is work to do: something to build from, and nothing usable --- yet. +-- Whether there is work to do: a ROM to build from, and no CURRENT set. -- --- A checkout that already carries a set is NOT pending. Building anyway would --- be correct and would also mean a ten-second loading screen on the first run --- of every checkout, to arrive at the files that were already sitting there. +-- Keyed on ready() rather than available(), and that is the whole upgrade +-- story. It used to short-circuit on available(), which meant a checkout +-- carrying assets/stadium was never pending -- so when REV went to 3 for the +-- shiny variants, such a machine did not rebuild, was not asked to, and +-- quietly kept serving the old set: every shiny Pokemon drawn in its +-- ordinary colours, with nothing on screen to say why. That is exactly what +-- happened here, and it took a driver run sitting at "idle 0/151" to notice. +-- +-- The cost this trades away is real and was the original reason: a checkout +-- with a ROM now spends one loading screen rebuilding a set it already had +-- files for. Once. After that ready() is true and it is not pending again -- +-- and what it buys is that a rev bump actually reaches the people it was +-- bumped for. function StadiumInstall.pending() - if StadiumInstall.available() then return false end - return StadiumInstall.romPresent() + if not StadiumInstall.romPresent() then return false end + return not StadiumInstall.ready() end function StadiumInstall.forget() diff --git a/lib/StadiumPack.lua b/lib/StadiumPack.lua index d37041a..e958938 100644 --- a/lib/StadiumPack.lua +++ b/lib/StadiumPack.lua @@ -78,15 +78,27 @@ local function readPack(species, shiny) -- half-written folder must not be read at all. Required lazily: Install -- requires this module at load, so the reverse edge cannot be taken then. local rel = packName(StadiumPack.CACHE_DIR, species, shiny) + local install = V.require("StadiumInstall") + local mod = V.mod + local haveShipped = false + if mod and mod.read then + local okS, b = pcall(mod.read, mod, packName(StadiumPack.DIR, species, shiny)) + haveShipped = okS and type(b) == "string" and #b > 4 + end + -- A CURRENT cache always wins. A stale one (readable, but built by an older + -- extractor) wins only when there is no shipped set to prefer instead -- + -- that ordering is what stops a cache from an extractor rev we have since + -- fixed shadowing good files, while still leaving something on screen for a + -- player whose only copy IS that cache. A half-written folder is caught by + -- the marker and satisfies neither. if love and love.filesystem and love.filesystem.getInfo - and V.require("StadiumInstall").ready() then + and (install.ready() or (install.usable() and not haveShipped)) then local okInfo, info = pcall(love.filesystem.getInfo, rel, "file") if okInfo and info then local ok, bytes = pcall(love.filesystem.read, rel) if ok and type(bytes) == "string" and #bytes > 4 then return bytes end end end - local mod = V.mod if not (mod and mod.read) then return nil end local ok, bytes = pcall(mod.read, mod, packName(StadiumPack.DIR, species, shiny)) diff --git a/tests/shiny_shots.lua b/tests/shiny_shots.lua index 7839842..50c6bd6 100644 --- a/tests/shiny_shots.lua +++ b/tests/shiny_shots.lua @@ -58,6 +58,15 @@ return function(game) -- unrecoloured Pokemon. Calling begin/step directly is both faster and -- honest about what is being tested, which is the extraction, not the -- screen that usually triggers it. + -- the upgrade question, asked before anything is built: with a stale + -- marker on disk, does this machine know it has work to do? + U.log(("upgrade check: ready=%s usable=%s available=%s pending=%s rom=%s") + :format(tostring(StadiumInstall.ready()), + tostring(StadiumInstall.usable()), + tostring(StadiumInstall.available()), + tostring(StadiumInstall.pending()), + tostring(StadiumInstall.romPresent()))) + if not StadiumInstall.ready() then local ok, err = StadiumInstall.begin() U.log(("stadium build: begin=%s %s"):format(tostring(ok), tostring(err or "")))