diff --git a/polymer/eduke32/source/gameexec.c b/polymer/eduke32/source/gameexec.c index ffc37b824..9678a328a 100644 --- a/polymer/eduke32/source/gameexec.c +++ b/polymer/eduke32/source/gameexec.c @@ -5465,7 +5465,8 @@ void A_Execute(int32_t iActor,int32_t iPlayer,int32_t lDist) void G_SaveMapState(void) { - map_t *mapinfo = &MapInfo[ud.volume_number*MAXLEVELS+ud.level_number]; + int32_t levelnum = ud.volume_number*MAXLEVELS+ud.level_number; + map_t *mapinfo = &MapInfo[levelnum]; mapstate_t *save; if (mapinfo->savedstate == NULL) @@ -5558,7 +5559,23 @@ void G_SaveMapState(void) else save->vars[i] = (intptr_t *)aGameVars[i].val.lValue; } #else - // TODO! (Not easy.) + { + int32_t slen; + const char *svcode = El_SerializeGamevars(&slen, levelnum); + + if (slen < 0) + { + El_OnError("ERROR: savemapstate: serialization failed!"); + } + else + { + char *savecode = Bstrdup(svcode); + if (savecode == NULL) + G_GameExit("OUT OF MEMORY in G_SaveMapState!"); + Bfree(save->savecode); + save->savecode = savecode; + } + } #endif ototalclock = totalclock; } @@ -5566,7 +5583,8 @@ void G_SaveMapState(void) void G_RestoreMapState(void) { - mapstate_t *save = MapInfo[ud.volume_number*MAXLEVELS+ud.level_number].savedstate; + int32_t levelnum = ud.volume_number*MAXLEVELS+ud.level_number; + mapstate_t *save = MapInfo[levelnum].savedstate; if (save != NULL) { @@ -5664,7 +5682,10 @@ void G_RestoreMapState(void) Gv_RefreshPointers(); #else - // TODO! (Not easy.) + if (save->savecode) + { + El_RestoreGamevars(save->savecode); + } #endif // Update g_player[].ps->i (sprite indices of players) to be consistent // with just loaded sprites. diff --git a/polymer/eduke32/source/lunatic/control.lua b/polymer/eduke32/source/lunatic/control.lua index 31473ff70..13f23301e 100644 --- a/polymer/eduke32/source/lunatic/control.lua +++ b/polymer/eduke32/source/lunatic/control.lua @@ -1834,7 +1834,7 @@ end function _savemapstate() ffiC.G_SaveMapState() local errmsg = debug.traceback( - "warning: savemapstate: gamevar saving not yet implemented", 2) + "warning: savemapstate: gamevar saving not fully implemented", 2) ffiC.El_OnError(errmsg) print(errmsg) end @@ -1842,7 +1842,7 @@ end function _loadmapstate() ffiC.G_RestoreMapState() local errmsg = debug.traceback( - "warning: loadmapstate: gamevar saving not yet implemented", 2) + "warning: loadmapstate: gamevar saving not fully implemented", 2) ffiC.El_OnError(errmsg) print(errmsg) end diff --git a/polymer/eduke32/source/lunatic/defs.ilua b/polymer/eduke32/source/lunatic/defs.ilua index 13f0df292..7ce712ef2 100644 --- a/polymer/eduke32/source/lunatic/defs.ilua +++ b/polymer/eduke32/source/lunatic/defs.ilua @@ -597,7 +597,8 @@ void El_OnError(const char *str); char *g_elSavecode; void El_FreeSaveCode(void); -const char *(*El_SerializeGamevars)(int32_t *slenptr); +const char *(*El_SerializeGamevars)(int32_t *slenptr, int32_t levelnum); +int32_t (*El_RestoreGamevars)(const char *savecode); const char *s_buildRev; const char *g_sizes_of_what[]; @@ -2244,8 +2245,8 @@ local CON_MODULE_NAME = "_CON\0" do local savegame = require("savegame") - -- Callback for: const char *(int32_t *slenptr); - ffiC.El_SerializeGamevars = function(slenptr) + -- Callback for: const char *(int32_t *slenptr, int32_t levelnum); + ffiC.El_SerializeGamevars = function(slenptr, levelnum) local sb = savegame.savebuffer() -- Module name, module table, restore_local. See SAVEFUNC_ARGS. @@ -2305,6 +2306,10 @@ do local fn = os.getenv("LUNATIC_SAVECODE_FN") if (fn ~= nil) then + if (levelnum >= 0) then + fn = fn .. levelnum + end + local io = require("io") local f = io.open(fn, "w") @@ -2471,6 +2476,17 @@ do end end +-- Restore CON gamevars from loadmapstate. +-- TODO: non-user-defined gamevars. +-- TODO: savegames. +-- int32_t El_RestoreGamevars(const char *) +ffiC.El_RestoreGamevars = function(savecode) + savecode = ffi.string(savecode) + local restorefunc = assert(loadstring(savecode)) + restorefunc(CON_MODULE_NAME, package_loaded[CON_MODULE_NAME], nil) + return 0 +end + -- Run the CON code translated into Lua. if (concode) then local confunc, conerrmsg = loadstring(concode, "CON") diff --git a/polymer/eduke32/source/lunatic/lunacon.lua b/polymer/eduke32/source/lunatic/lunacon.lua index a43e2b9fd..b8243f877 100644 --- a/polymer/eduke32/source/lunatic/lunacon.lua +++ b/polymer/eduke32/source/lunatic/lunacon.lua @@ -315,7 +315,8 @@ local function new_initial_codetab() "_V,_A={},{}", "-- NOTE to the reader: This require's result is Lunatic-private API! DO NOT USE!", "local _dummy,_S=require'end_gamevars'", - "local _V,_A=_V,_A", +-- XXX: Currently commented out because of gamevar restoration from loadmapstate. +-- "local _V,_A=_V,_A", "local _C,_M,_I={},{},{}", -- actions, moves, ais -- Static ivec3s so that no allocations need to be made. diff --git a/polymer/eduke32/source/lunatic/lunatic_game.c b/polymer/eduke32/source/lunatic/lunatic_game.c index 60b216647..231deb0ce 100644 --- a/polymer/eduke32/source/lunatic/lunatic_game.c +++ b/polymer/eduke32/source/lunatic/lunatic_game.c @@ -437,6 +437,8 @@ static void El_PushCFunctions(lua_State *L) ////// +LUNATIC_CB int32_t (*El_RestoreGamevars)(const char *savecode); + static void El_StateSetup(lua_State *L) { luaopen_lpeg(L); diff --git a/polymer/eduke32/source/lunatic/lunatic_game.h b/polymer/eduke32/source/lunatic/lunatic_game.h index af25c108d..354d94520 100644 --- a/polymer/eduke32/source/lunatic/lunatic_game.h +++ b/polymer/eduke32/source/lunatic/lunatic_game.h @@ -39,6 +39,10 @@ void El_DestroyState(L_State *estate); int32_t El_CallEvent(L_State *estate, int32_t eventidx, int32_t iActor, int32_t iPlayer, int32_t lDist, int32_t *iReturn); int32_t El_CallActor(L_State *estate, int32_t actortile, int32_t iActor, int32_t iPlayer, int32_t lDist); +void El_OnError(const char *str); + +int32_t (*El_RestoreGamevars)(const char *savecode); + static inline int32_t El_HaveEvent(int32_t eventidx) { return g_elEvents[eventidx]!=0; } static inline int32_t El_HaveActor(int32_t actortile) { return g_elActors[actortile].haveit!=0; } diff --git a/polymer/eduke32/source/premap.c b/polymer/eduke32/source/premap.c index 913be4182..47a1dbf4a 100644 --- a/polymer/eduke32/source/premap.c +++ b/polymer/eduke32/source/premap.c @@ -1083,8 +1083,8 @@ static inline void prelevel(char g) // NOTE: must be safe loop because callbacks could delete sprites. for (SPRITES_OF_STAT_SAFE(STAT_DEFAULT, i, nexti)) { -#if !defined LUNATIC A_ResetVars(i); +#if !defined LUNATIC A_LoadActor(i); #endif VM_OnEvent(EVENT_LOADACTOR, i, -1, -1, 0); diff --git a/polymer/eduke32/source/savegame.c b/polymer/eduke32/source/savegame.c index ab8c7182b..765f6eaf9 100644 --- a/polymer/eduke32/source/savegame.c +++ b/polymer/eduke32/source/savegame.c @@ -1692,7 +1692,9 @@ static void sv_restload() #endif #ifdef LUNATIC -LUNATIC_CB const char *(*El_SerializeGamevars)(int32_t *slenptr); +// : if we're not serializing for a mapstate, -1 +// otherwise, the linearized level number +LUNATIC_CB const char *(*El_SerializeGamevars)(int32_t *slenptr, int32_t levelnum); #endif static uint8_t *dosaveplayer2(FILE *fil, uint8_t *mem) @@ -1711,7 +1713,7 @@ static uint8_t *dosaveplayer2(FILE *fil, uint8_t *mem) // be present before Lua state creation in svgm_script, so save it // right before, too. int32_t slen, slen_ext; - const char *svcode = El_SerializeGamevars(&slen); + const char *svcode = El_SerializeGamevars(&slen, -1); if (slen < 0) { diff --git a/polymer/eduke32/source/savegame.h b/polymer/eduke32/source/savegame.h index 5a37a11b5..eaf27f318 100644 --- a/polymer/eduke32/source/savegame.h +++ b/polymer/eduke32/source/savegame.h @@ -92,4 +92,8 @@ enum void G_Util_PtrToIdx(void *ptr, int32_t count, const void *base, int32_t mode); void G_Util_PtrToIdx2(void *ptr, int32_t count, size_t stride, const void *base, int32_t mode); +#ifdef LUNATIC +const char *(*El_SerializeGamevars)(int32_t *slenptr, int32_t levelnum); +#endif + #endif