Aleksei-bird 7c9c708c92 Первый фикс
Пачки некоторых позиций увеличены
2024-03-01 20:54:33 +03:00

153 lines
7.3 KiB
Lua

-- This code handles the general migration process of the mod's global table
-- It decides whether and which migrations should be applied, in appropriate order
local migrator = {}
---@alias MigrationMasterList { [integer]: { version: VersionString, migration: Migration } }
---@alias Migration { global: function, player_table: function, subfactory: function, packed_subfactory: function }
---@alias MigrationObject PlayerTable | FPSubfactory | FPPackedSubfactory
-- Returns a table containing all existing migrations in order
local migration_masterlist = { ---@type MigrationMasterList
[1] = {version="0.18.20", migration=require("backend.migrations.migration_0_18_20")},
[2] = {version="0.18.27", migration=require("backend.migrations.migration_0_18_27")},
[3] = {version="0.18.29", migration=require("backend.migrations.migration_0_18_29")},
[4] = {version="0.18.38", migration=require("backend.migrations.migration_0_18_38")},
[5] = {version="0.18.42", migration=require("backend.migrations.migration_0_18_42")},
[6] = {version="0.18.45", migration=require("backend.migrations.migration_0_18_45")},
[7] = {version="0.18.48", migration=require("backend.migrations.migration_0_18_48")},
[8] = {version="0.18.49", migration=require("backend.migrations.migration_0_18_49")},
[9] = {version="0.18.51", migration=require("backend.migrations.migration_0_18_51")},
[10] = {version="1.0.6", migration=require("backend.migrations.migration_1_0_6")},
[11] = {version="1.1.5", migration=require("backend.migrations.migration_1_1_5")},
[12] = {version="1.1.6", migration=require("backend.migrations.migration_1_1_6")},
[13] = {version="1.1.8", migration=require("backend.migrations.migration_1_1_8")},
[14] = {version="1.1.14", migration=require("backend.migrations.migration_1_1_14")},
[15] = {version="1.1.19", migration=require("backend.migrations.migration_1_1_19")},
[16] = {version="1.1.21", migration=require("backend.migrations.migration_1_1_21")},
[17] = {version="1.1.25", migration=require("backend.migrations.migration_1_1_25")},
[18] = {version="1.1.26", migration=require("backend.migrations.migration_1_1_26")},
[19] = {version="1.1.27", migration=require("backend.migrations.migration_1_1_27")},
[20] = {version="1.1.42", migration=require("backend.migrations.migration_1_1_42")},
[21] = {version="1.1.43", migration=require("backend.migrations.migration_1_1_43")},
[22] = {version="1.1.59", migration=require("backend.migrations.migration_1_1_59")},
[23] = {version="1.1.61", migration=require("backend.migrations.migration_1_1_61")},
[24] = {version="1.1.65", migration=require("backend.migrations.migration_1_1_65")},
[25] = {version="1.1.66", migration=require("backend.migrations.migration_1_1_66")},
[26] = {version="1.1.67", migration=require("backend.migrations.migration_1_1_67")},
}
-- ** LOCAL UTIL **
-- Compares two mod versions, returns true if v1 is an earlier version than v2 (v1 < v2)
-- Version numbers have to be of the same structure: same amount of numbers, separated by a '.'
---@param v1 VersionString
---@param v2 VersionString
---@return boolean
local function compare_versions(v1, v2)
local split_v1 = util.split_string(v1, ".")
local split_v2 = util.split_string(v2, ".")
for i = 1, #split_v1 do
if split_v1[i] == split_v2[i] then
-- continue
elseif split_v1[i] < split_v2[i] then
return true
else
return false
end
end
return false -- return false if both versions are the same
end
-- Applies given migrations to the object
---@param migrations Migration[]
---@param function_name string
---@param object MigrationObject?
---@param player LuaPlayer?
local function apply_migrations(migrations, function_name, object, player)
for _, migration in ipairs(migrations) do
local migration_function = migration[function_name]
if migration_function ~= nil then
local migration_message = migration_function(object, player) ---@type string
-- If no message is returned, everything went fine
if migration_message == "removed" then break end
end
end
end
-- Determines whether a migration needs to take place, and if so, returns the appropriate range of the
-- migration_masterlist. If the version changed, but no migrations apply, it returns an empty array.
---@param previous_version VersionString
---@return Migration[]
local function determine_migrations(previous_version)
local migrations = {}
local found = false
for _, migration in ipairs(migration_masterlist) do
if compare_versions(previous_version, migration.version) then found = true end
if found then table.insert(migrations, migration.migration) end
end
return migrations
end
-- ** TOP LEVEL **
-- Applies any appropriate migrations to the global table
function migrator.migrate_global()
local migrations = determine_migrations(global.mod_version)
apply_migrations(migrations, "global", nil, nil)
global.mod_version = script.active_mods["factoryplanner"]
end
-- Applies any appropriate migrations to the given factory
---@param player LuaPlayer
function migrator.migrate_player_table(player)
local player_table = util.globals.player_table(player)
if player_table ~= nil then -- don't apply migrations to new players
local migrations = determine_migrations(player_table.mod_version)
-- General migrations
local old_version = player_table.mod_version -- keep for comparison below
apply_migrations(migrations, "player_table", player_table, player)
player_table.mod_version = global.mod_version
-- Subfactory migrations
for _, factory_name in pairs({"factory", "archive"}) do
--local outdated_subfactories = {}
for _, subfactory in pairs(Factory.get_all(player_table[factory_name], "Subfactory")) do
if subfactory.mod_version ~= old_version then -- out-of-sync subfactory
--error("Out of date subfactory, please report this to the mod author including the save file")
--table.insert(outdated_subfactories, subfactory)
else
apply_migrations(migrations, "subfactory", subfactory, player)
subfactory.mod_version = global.mod_version
end
end
--[[ -- Remove subfactories who weren't migrated along properly for some reason
-- TODO This is likely due to an old, now-fixed bug that left them behind
for _, subfactory in pairs(outdated_subfactories) do
Factory.remove(player_table[factory_name], subfactory)
end ]]
end
end
end
-- Applies any appropriate migrations to the given export_table's subfactories
---@param export_table ExportTable
function migrator.migrate_export_table(export_table)
local migrations = determine_migrations(export_table.mod_version)
for _, packed_subfactory in pairs(export_table.subfactories) do
-- This migration type won't need the player argument, and removing it allows
-- us to run imports without having a player attached
apply_migrations(migrations, "packed_subfactory", packed_subfactory, nil)
end
export_table.mod_version = global.mod_version
end
return migrator