From 74da3e5fa7bcfb8d2e377245e263988d0c83176b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 8 Dec 2021 00:14:10 +0100 Subject: [PATCH] - added savegame support for the new actor management. --- source/common/objects/dobjgc.cpp | 1 - source/core/actorlist.cpp | 22 ++++++++++++++++------ source/core/savegamehelp.cpp | 28 ++++++++++++++++++++++++---- source/core/version.h | 16 ++++++++-------- source/games/duke/src/gamevar.cpp | 3 --- source/games/duke/src/savegame.cpp | 1 + 6 files changed, 49 insertions(+), 22 deletions(-) diff --git a/source/common/objects/dobjgc.cpp b/source/common/objects/dobjgc.cpp index 59c5002d7..91cfafaef 100644 --- a/source/common/objects/dobjgc.cpp +++ b/source/common/objects/dobjgc.cpp @@ -195,7 +195,6 @@ static DObject **SweepList(DObject **p, size_t count, size_t *finalize_count) // However, this can happen during deletion of the thinker list while cleaning up // from a savegame error so we can't assume that any thinker that gets here is an error. - assert(!curr->IsKindOf("CoreActor")); curr->Destroy(); } diff --git a/source/core/actorlist.cpp b/source/core/actorlist.cpp index aef9a4e98..8083857c6 100644 --- a/source/core/actorlist.cpp +++ b/source/core/actorlist.cpp @@ -142,6 +142,7 @@ static void RemoveActorStat(DCoreActor* actor) auto prevp = prev ? &prev->nextStat : &firstEntry; auto nextp = next ? &next->prevStat : &lastEntry; + assert(*prevp == actor); assert(*nextp == actor); @@ -364,7 +365,7 @@ DCoreActor* InsertActor(PClass* type, sectortype* sector, int stat, bool tail) void DCoreActor::OnDestroy() { - assert(spr.statnum >= 0 && spr.statnum < MAXSTATUS); + if(link_stat == INT_MAX) return; int stat = link_stat; RemoveActorStat(this); @@ -395,11 +396,10 @@ void InitSpriteLists() TSpriteIterator it; while (auto actor = it.Next()) allActors.Push(actor); - for (auto& act : allActors) - { - if (!(act->ObjectFlags & OF_EuthanizeMe)) - act->Destroy(); - } + + // clear all lists manually before doing any mass destruction. + // This may also be called in error situations where the list has become corrupted, + // so we should not depend on its consistency anymore. for (auto& stat : statList) { stat.firstEntry = stat.lastEntry = nullptr; @@ -408,6 +408,16 @@ void InitSpriteLists() { sect.firstEntry = sect.lastEntry = nullptr; } + + for (auto& act : allActors) + { + if (!(act->ObjectFlags & OF_EuthanizeMe)) + { + act->link_stat = INT_MAX; + act->prevStat = act->nextStat = act->prevSect = act->nextSect = nullptr; + act->Destroy(); + } + } Numsprites = 0; } diff --git a/source/core/savegamehelp.cpp b/source/core/savegamehelp.cpp index 4de7b92d5..d13cb308f 100644 --- a/source/core/savegamehelp.cpp +++ b/source/core/savegamehelp.cpp @@ -107,6 +107,7 @@ static void SerializeGlobals(FSerializer& arc) static void SerializeSession(FSerializer& arc) { + arc.ReadObjects(false); SerializeMap(arc); SerializeStatistics(arc); SECRET_Serialize(arc); @@ -510,7 +511,9 @@ FSerializer &Serialize(FSerializer &arc, const char *key, sectortype &c, sectort { if (arc.BeginObject(key)) { - arc("wallptr", c.wallptr, def->wallptr) + arc("firstentry", c.firstEntry) + ("lastentry", c.lastEntry) + ("wallptr", c.wallptr, def->wallptr) ("wallnum", c.wallnum, def->wallnum) ("ceilingz", c.ceilingz, def->ceilingz) ("floorz", c.floorz, def->floorz) @@ -651,11 +654,27 @@ FSerializer &Serialize(FSerializer &arc, const char *key, walltype &c, walltype return arc; } +FSerializer& Serialize(FSerializer& arc, const char* key, ActorStatList& c, ActorStatList* def) +{ + if (arc.BeginObject(key)) + { + arc("firstentry", c.firstEntry) + ("lastentry", c.lastEntry) + .EndObject(); + } + return arc; +} void DCoreActor::Serialize(FSerializer& arc) { - // nothing here yet. - arc("sprite", spr) + Super::Serialize(arc); + arc("link_stat", link_stat) + ("link_sector", link_sector) + ("prevstat", prevStat) + ("nextstat", nextStat) + ("prevsect", prevSect) + ("nextsect", nextSect) + ("sprite", spr) ("spriteext", sprext); if (arc.isReading()) spsmooth = {}; @@ -666,7 +685,8 @@ void SerializeMap(FSerializer& arc) { if (arc.BeginObject("engine")) { - arc("numsectors", numsectors) + arc.Array("statlist", statList, MAXSTATUS) + ("numsectors", numsectors) ("sectors", sector, sectorbackup) ("numwalls", numwalls) ("walls", wall, wallbackup) diff --git a/source/core/version.h b/source/core/version.h index bbb3bde6f..66b5484b9 100644 --- a/source/core/version.h +++ b/source/core/version.h @@ -69,15 +69,15 @@ const char *GetVersionString(); #define SAVESIG_SW GAMENAME ".ShadowWarrior" #define SAVESIG_PS GAMENAME ".Exhumed" -#define MINSAVEVER_DN3D 10 -#define MINSAVEVER_BLD 12 -#define MINSAVEVER_SW 13 -#define MINSAVEVER_PS 15 +#define MINSAVEVER_DN3D 16 +#define MINSAVEVER_BLD 16 +#define MINSAVEVER_SW 16 +#define MINSAVEVER_PS 16 -#define SAVEVER_DN3D 12 -#define SAVEVER_BLD 12 -#define SAVEVER_SW 13 -#define SAVEVER_PS 15 +#define SAVEVER_DN3D 16 +#define SAVEVER_BLD 16 +#define SAVEVER_SW 16 +#define SAVEVER_PS 16 #define NETGAMEVERSION 1 diff --git a/source/games/duke/src/gamevar.cpp b/source/games/duke/src/gamevar.cpp index 468b42728..b09e1bd66 100644 --- a/source/games/duke/src/gamevar.cpp +++ b/source/games/duke/src/gamevar.cpp @@ -73,13 +73,10 @@ FSerializer& Serialize(FSerializer& arc, const char* keyname, GameVarValue& w, G case 0: { // pointless to handle now, fix when saving works again. -#pragma message(" fix me!"); -#if 0 DDukeActor* a = arc.isWriting() ? w.actor() : nullptr; arc("actor", a); if (arc.isReading()) w = GameVarValue(a); break; -#endif } case 1: { diff --git a/source/games/duke/src/savegame.cpp b/source/games/duke/src/savegame.cpp index 5acc4840e..7f27dcc0d 100644 --- a/source/games/duke/src/savegame.cpp +++ b/source/games/duke/src/savegame.cpp @@ -298,6 +298,7 @@ void DDukeActor::Serialize(FSerializer& arc) Super::Serialize(arc); + if (arc.isReading()) s = &spr; arc("cgg", cgg) ("spriteextra", spriteextra) ("picnum", picnum)