From 05b43ca258f808f7206c228e04c02bcb339a3768 Mon Sep 17 00:00:00 2001 From: MaxTomahawk Date: Fri, 7 Aug 2026 15:21:16 +0200 Subject: [PATCH] feat: include engine version in checkpoints --- docs/rfcs/0004-runtime-checkpoints.md | 7 +++++-- src/core/Checkpoint.lua | 5 ++++- tests/modkit/cases/checkpoints.lua | 7 ++++++- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/docs/rfcs/0004-runtime-checkpoints.md b/docs/rfcs/0004-runtime-checkpoints.md index e9ba649c..0df1c421 100644 --- a/docs/rfcs/0004-runtime-checkpoints.md +++ b/docs/rfcs/0004-runtime-checkpoints.md @@ -56,7 +56,9 @@ Returns a detached data-only format-1 checkpoint, or { format = 1, kind = "overworld", - identity = { gameVersion = "red", playthroughId = "..." }, + identity = { + engineVersion = "...", gameVersion = "red", playthroughId = "...", + }, save = { -- canonical dynamic progress, excluding global options }, runtime = { overworld = { map = "PALLET_TOWN", x = 5, y = 6, @@ -65,7 +67,8 @@ Returns a detached data-only format-1 checkpoint, or } ``` -Capture deep-copies through the restricted serializer before and after +`engineVersion` is metadata for caller compatibility warnings; the engine does +not reject patch/minor mismatches on restore. Capture deep-copies through the restricted serializer before and after `OverworldController:captureSave` synchronizes live map, tile, facing, and surf state. It excludes `save.options`, functions, userdata, threads, metatables as behavior, controller instances, and static content registries. Failure code diff --git a/src/core/Checkpoint.lua b/src/core/Checkpoint.lua index d1082855..f09962f6 100644 --- a/src/core/Checkpoint.lua +++ b/src/core/Checkpoint.lua @@ -3,6 +3,7 @@ local SaveSerializer = require("src.core.SaveSerializer") local SaveData = require("src.core.SaveData") +local Version = require("src.core.Version") local Checkpoint = {} @@ -119,6 +120,7 @@ function Checkpoint.capture(game) format = Checkpoint.FORMAT, kind = "overworld", identity = { + engineVersion = Version.engine, gameVersion = game.save.version, playthroughId = game.save.meta.playthroughId, }, @@ -154,7 +156,8 @@ local function validate(game, checkpoint) local identity = copy.identity local current = game and game.save local currentId = current and current.meta and current.meta.playthroughId - if type(identity) ~= "table" or type(identity.gameVersion) ~= "string" + if type(identity) ~= "table" or type(identity.engineVersion) ~= "string" + or type(identity.gameVersion) ~= "string" or type(identity.playthroughId) ~= "string" then return nil, "invalid_checkpoint", "Checkpoint identity is missing or corrupt." end diff --git a/tests/modkit/cases/checkpoints.lua b/tests/modkit/cases/checkpoints.lua index 3dd4aa09..a1277b1e 100644 --- a/tests/modkit/cases/checkpoints.lua +++ b/tests/modkit/cases/checkpoints.lua @@ -9,6 +9,7 @@ local Loader = require("src.mods.Loader") local Runtime = require("src.mods.Runtime") local GameMethods = require("src.core.Game") local StateStack = require("src.core.StateStack") +local Version = require("src.core.Version") local savedEvents, savedHooks = Runtime.events, Runtime.hooks @@ -204,7 +205,11 @@ local snapshot, code, message = checkpoints:capture(game) T.check(snapshot ~= nil, "stable overworld captures: " .. tostring(code or message)) T.eq(snapshot.format, 1, "checkpoint format is explicit") T.eq(snapshot.kind, "overworld", "checkpoint runtime kind is explicit") -T.same(snapshot.identity, { gameVersion = "red", playthroughId = "play-a" }, +T.same(snapshot.identity, { + engineVersion = Version.engine, + gameVersion = "red", + playthroughId = "play-a", + }, "checkpoint carries compatibility identity") T.same(snapshot.runtime.overworld, { map = "ROUTE_1", x = 7, y = 8, facing = "left", surfing = true },