mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-15 15:51:17 +02:00
fix(save/gen2): auto-recover orphaned save slots and fix PartyMenu field moves
- Auto-recover save slots: Scan saves/<version>/ on boot to re-index orphaned slot files if options.lua is reset or loses its slot registry. - Fix Gen 2 field moves: Make PartyMenu field actions (Strength, Surf, Cut, Flash) generation-aware so they execute safely in Gold. - Fortify platform stability: Guard native controller/hidapi init against Android 14 receiver exceptions and ensure safe Windows file replacement. - Add unit test coverage for slot auto-recovery in save_editor_gen2_tests.lua.
This commit is contained in:
+49
-2
@@ -832,9 +832,41 @@ local function tryMigrateLegacy(version, fs)
|
||||
return id
|
||||
end
|
||||
|
||||
-- Scan the filesystem for orphaned slot files under saves/<version>/ when options.lua
|
||||
-- has no registered slots for this version (e.g. options.lua was reset or lost).
|
||||
local function scanDiskSlots(version, fs)
|
||||
if not fs then return nil end
|
||||
local dir = "saves/" .. version
|
||||
local slots = {}
|
||||
if fs.getDirectoryItems and fs.getInfo and fs.getInfo(dir) then
|
||||
local items = pcall(fs.getDirectoryItems, dir) and fs.getDirectoryItems(dir) or {}
|
||||
local numbers = {}
|
||||
for _, item in ipairs(items) do
|
||||
local slotId = item:match("^(slot%d+)%.lua$")
|
||||
if slotId then
|
||||
local n = tonumber(slotId:match("%d+"))
|
||||
table.insert(numbers, { id = slotId, num = n or 0 })
|
||||
end
|
||||
end
|
||||
table.sort(numbers, function(a, b) return a.num < b.num end)
|
||||
for _, item in ipairs(numbers) do
|
||||
table.insert(slots, item.id)
|
||||
end
|
||||
else
|
||||
for i = 1, 30 do
|
||||
local slotId = "slot" .. i
|
||||
local path = dir .. "/" .. slotId .. ".lua"
|
||||
if fs.getInfo and fs.getInfo(path) then
|
||||
table.insert(slots, slotId)
|
||||
end
|
||||
end
|
||||
end
|
||||
return #slots > 0 and slots or nil
|
||||
end
|
||||
|
||||
-- Resolve (once per version per process) which slot in-game saves use: an
|
||||
-- existing registry wins; otherwise a lazy legacy migration may create
|
||||
-- slot1; otherwise false, meaning the flat legacy path.
|
||||
-- slot1; otherwise auto-recover disk slots; otherwise false (flat legacy path).
|
||||
local function ensureVersionSlots(version, fs)
|
||||
if slotsChecked[version] then return end
|
||||
slotsChecked[version] = true
|
||||
@@ -848,7 +880,22 @@ local function ensureVersionSlots(version, fs)
|
||||
activeSlotCache[version] = reg.active or reg.list[1]
|
||||
return
|
||||
end
|
||||
activeSlotCache[version] = tryMigrateLegacy(version, fs) or false
|
||||
local migrated = tryMigrateLegacy(version, fs)
|
||||
if migrated then
|
||||
activeSlotCache[version] = migrated
|
||||
return
|
||||
end
|
||||
-- Auto-recovery: if options.lua lost its slot registry, scan disk for orphaned slot files
|
||||
local recovered = scanDiskSlots(version, fs)
|
||||
if recovered and #recovered > 0 then
|
||||
opts.saveSlots = opts.saveSlots or {}
|
||||
opts.saveSlots[version] = { list = recovered, active = recovered[1] }
|
||||
SaveData.saveOptions(opts, fs)
|
||||
activeSlotCache[version] = recovered[1]
|
||||
Logger.info("auto-recovered %d save slot(s) for %s from disk", #recovered, version)
|
||||
return
|
||||
end
|
||||
activeSlotCache[version] = false
|
||||
end
|
||||
|
||||
-- (body for the forward-declared saveNames.) Resolves the ACTIVE slot for
|
||||
|
||||
Reference in New Issue
Block a user