-- One-off migration: rewrite rooms/*.sav from the old baked-in adhesion classes -- (spiky_/skewer_/sticky_) to the new model of a plain base class carrying -- an `adhesion` property. spiky and old-sticky both become the new soft "sticky"; -- skewer becomes the rigid "gluey". Run once from the project root: lua tools/backfill_adhesion.lua loadstring = loadstring or load -- TSerial.unpack still calls loadstring (removed in Lua 5.4+) package.path = "./?.lua;" .. package.path require "libs/TSerial" local dir = "rooms" local adhesionForPrefix = { spiky = "sticky", skewer = "gluey", sticky = "sticky" } local function savFiles() local files = {} local pipe = io.popen('ls "' .. dir .. '"') for name in pipe:lines() do if name:match("%.sav$") then table.insert(files, name) end end pipe:close() return files end local function readFile(path) local handle = assert(io.open(path, "r")) local contents = handle:read("*a") handle:close() return contents end local function writeFile(path, contents) local handle = assert(io.open(path, "w")) handle:write(contents) handle:close() end local totalFiles, totalObjects = 0, 0 for _, file in ipairs(savFiles()) do local path = dir .. "/" .. file local saveTable = TSerial.unpack(readFile(path)) local migrated = 0 for _, object in ipairs((saveTable and saveTable.objects) or {}) do if type(object.class) == "string" then for prefix, adhesion in pairs(adhesionForPrefix) do local base = object.class:match("^" .. prefix .. "_(.+)") if base then object.class = base if not object.adhesion then object.adhesion = adhesion end migrated = migrated + 1 break end end end end if migrated > 0 then writeFile(path, TSerial.pack(saveTable, nil, true)) totalFiles = totalFiles + 1 totalObjects = totalObjects + migrated print(string.format("%-28s migrated %d object(s)", file, migrated)) end end print(string.format("done: %d object(s) across %d file(s)", totalObjects, totalFiles))