From 01d28e3eb2ddba3f95f6d98d37b260b6f238d5d0 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 23 Sep 2016 17:49:33 +0200 Subject: [PATCH] - added the last missing bits of the savegame code - thinker list deserialization and handling of players during hub travel. Now testing is what remains... --- src/CMakeLists.txt | 1 - src/dthinker.cpp | 79 ++++++++++++++++++++++++++++++++++++++++++++++ src/json.cpp | 39 ----------------------- src/p_saveg.cpp | 6 +--- src/serializer.cpp | 58 ++++++++++++++++++++++++++-------- src/serializer.h | 10 +++--- 6 files changed, 130 insertions(+), 63 deletions(-) delete mode 100644 src/json.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d6878a19e..ab5f137ef 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1001,7 +1001,6 @@ set( FASTMATH_SOURCES ) set (PCH_SOURCES - json.cpp actorptrselect.cpp am_map.cpp b_bot.cpp diff --git a/src/dthinker.cpp b/src/dthinker.cpp index 0cd2c6a68..5dbded654 100644 --- a/src/dthinker.cpp +++ b/src/dthinker.cpp @@ -116,6 +116,85 @@ void DThinker::SaveList(FSerializer &arc, DThinker *node) } } +//========================================================================== +// +// +// +//========================================================================== + +void DThinker::SerializeThinkers(FSerializer &arc, bool hubLoad) +{ + //DThinker *thinker; + //BYTE stat; + //int statcount; + int i; + + if (arc.isWriting()) + { + arc.BeginArray("thinkers"); + for (i = 0; i <= MAX_STATNUM; i++) + { + arc.BeginArray(nullptr); + SaveList(arc, Thinkers[i].GetHead()); + SaveList(arc, FreshThinkers[i].GetHead()); + arc.EndArray(); + } + arc.EndArray(); + } + else + { + if (arc.BeginArray("thinkers")) + { + for (i = 0; i <= MAX_STATNUM; i++) + { + if (arc.BeginArray(nullptr)) + { + int size = arc.ArraySize(); + for (int j = 0; j < size; j++) + { + DThinker *thinker; + arc(nullptr, thinker); + if (thinker != nullptr) + { + // This may be a player stored in their ancillary list. Remove + // them first before inserting them into the new list. + if (thinker->NextThinker != nullptr) + { + thinker->Remove(); + } + // Thinkers with the OF_JustSpawned flag set go in the FreshThinkers + // list. Anything else goes in the regular Thinkers list. + if (thinker->ObjectFlags & OF_EuthanizeMe) + { + // This thinker was destroyed during the loading process. Do + // not link it into any list. + } + else if (thinker->ObjectFlags & OF_JustSpawned) + { + FreshThinkers[i].AddTail(thinker); + thinker->PostSerialize(); + } + else + { + Thinkers[i].AddTail(thinker); + thinker->PostSerialize(); + } + } + } + arc.EndArray(); + } + } + arc.EndArray(); + } + } +} + +//========================================================================== +// +// +// +//========================================================================== + DThinker::DThinker (int statnum) throw() { NextThinker = NULL; diff --git a/src/json.cpp b/src/json.cpp deleted file mode 100644 index 1bdc5d90e..000000000 --- a/src/json.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include "serializer.h" -#include "r_local.h" -#include "p_setup.h" -#include "c_dispatch.h" -#include "i_system.h" -#include "a_sharedglobal.h" - - - -//========================================================================== -// -// -// -//========================================================================== - - -void DThinker::SerializeThinkers(FSerializer &arc, bool hubLoad) -{ - //DThinker *thinker; - //BYTE stat; - //int statcount; - int i; - - if (arc.isWriting()) - { - arc.BeginArray("thinkers"); - for (i = 0; i <= MAX_STATNUM; i++) - { - arc.BeginArray(nullptr); - SaveList(arc, Thinkers[i].GetHead()); - SaveList(arc, FreshThinkers[i].GetHead()); - arc.EndArray(); - } - arc.EndArray(); - } - else - { - } -} diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index 6459fc60f..fb1504083 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -63,10 +63,6 @@ #include "r_renderer.h" #include "serializer.h" -// just the stuff that already got converted to FSerializer so that it can be seen as 'done' when searching. -#include "zzz_old.cpp" - - // // Thinkers // @@ -905,7 +901,7 @@ void G_SerializeLevel(FSerializer &arc, bool hubload) { P_DestroyThinkers(hubload); interpolator.ClearInterpolations(); - arc.ReadObjects(); + arc.ReadObjects(hubload); } arc("level.flags", level.flags) diff --git a/src/serializer.cpp b/src/serializer.cpp index 4d9da256b..3045515f7 100644 --- a/src/serializer.cpp +++ b/src/serializer.cpp @@ -31,6 +31,7 @@ #include "v_text.h" char nulspace[1024 * 1024 * 4]; +bool save_full = false; // for testing. Should be removed afterward. //========================================================================== // @@ -206,7 +207,7 @@ struct FReader rapidjson::Document doc; mDoc.Parse(buffer, length); mObjects.Push(FJSONObject(&mDoc)); - memset(mPlayers, 0, sizeof(mPlayers)); + memset(mPlayers, -1, sizeof(mPlayers)); } rapidjson::Value *FindKey(const char *key) @@ -806,7 +807,7 @@ void FSerializer::WriteObjects() // //========================================================================== -void FSerializer::ReadObjects() +void FSerializer::ReadObjects(bool hubtravel) { bool founderrors = false; @@ -823,6 +824,7 @@ void FSerializer::ReadObjects() if (BeginObject(nullptr)) { FString clsname; // do not deserialize the class type directly so that we can print appropriate errors. + int pindex = -1; Serialize(*this, "classtype", clsname, nullptr); PClass *cls = PClass::FindClass(clsname); @@ -830,6 +832,7 @@ void FSerializer::ReadObjects() { Printf("Unknown object class '%d' in savegame", clsname.GetChars()); founderrors = true; + r->mDObjects[i] = RUNTIME_CLASS(AActor)->CreateNew(); // make sure we got at least a valid pointer for the duration of the loading process. } else { @@ -849,33 +852,60 @@ void FSerializer::ReadObjects() for (unsigned i = 0; i < r->mDObjects.Size(); i++) { auto obj = r->mDObjects[i]; - try + if (BeginObject(nullptr)) { - if (BeginObject(nullptr)) + if (obj != nullptr) { int pindex = -1; - Serialize(*this, "playerindex", pindex, nullptr); - if (obj != nullptr) + if (hubtravel) { - if (pindex >= 0 && pindex < MAXPLAYERS) + // mark this as a hub travelling player. This needs to be taken care of later and be replaced with the real travelling player, + // but that's better done at the end of this loop so that inventory ownership is not getting messed up. + Serialize(*this, "playerindex", pindex, nullptr); + if (hubtravel && pindex >= 0 && pindex < MAXPLAYERS) { - obj->ObjectFlags |= OF_LoadedPlayer; r->mPlayers[pindex] = int(i); } + } + try + { obj->SerializeUserVars(*this); obj->Serialize(*this); } - EndObject(); + catch (CRecoverableError &err) + { + // In case something in here throws an error, let's continue and deal with it later. + Printf(TEXTCOLOR_RED "'%s'\n while restoring %s", err.GetMessage(), obj ? obj->GetClass()->TypeName.GetChars() : "invalid object"); + mErrors++; + } } - } - catch (CRecoverableError &err) - { - Printf(TEXTCOLOR_RED "'%s'\n while restoring %s", err.GetMessage(),obj? obj->GetClass()->TypeName.GetChars() : "invalid object"); - mErrors++; + EndObject(); } } } EndArray(); + + if (hubtravel) + { + for (int i = 0; i < MAXPLAYERS; i++) + { + int pindex = r->mPlayers[i]; + if (pindex != -1) + { + if (players[i].mo != nullptr) + { + r->mDObjects[pindex]->Destroy(); + DObject::StaticPointerSubstitution(r->mDObjects[pindex], players[i].mo); + r->mDObjects[pindex] = players[i].mo; + } + else + { + players[i].mo = static_cast(r->mDObjects[pindex]); + } + } + } + } + DThinker::bSerialOverride = false; assert(!founderrors); if (founderrors) diff --git a/src/serializer.h b/src/serializer.h index 4730136a2..f1d35e1f8 100644 --- a/src/serializer.h +++ b/src/serializer.h @@ -7,6 +7,8 @@ #include "r_defs.h" #include "resourcefiles/file_zip.h" +extern bool save_full; + struct ticcmd_t; struct usercmd_t; @@ -72,7 +74,7 @@ public: bool OpenReader(const char *buffer, size_t length); bool OpenReader(FCompressedBuffer *input); void Close(); - void ReadObjects(); + void ReadObjects(bool hubtravel); bool BeginObject(const char *name); void EndObject(); bool BeginArray(const char *name); @@ -108,13 +110,13 @@ public: template FSerializer &operator()(const char *key, T &obj, T &def) { - return Serialize(*this, key, obj, &def); + return Serialize(*this, key, obj, save_full? nullptr : &def); } template FSerializer &Array(const char *key, T *obj, int count, bool fullcompare = false) { - if (fullcompare && isWriting() && nullcmp(obj, count * sizeof(T))) + if (!save_full && fullcompare && isWriting() && nullcmp(obj, count * sizeof(T))) { return *this; } @@ -138,7 +140,7 @@ public: template FSerializer &Array(const char *key, T *obj, T *def, int count, bool fullcompare = false) { - if (fullcompare && isWriting() && def != nullptr && !memcmp(obj, def, count * sizeof(T))) + if (!save_full && fullcompare && isWriting() && def != nullptr && !memcmp(obj, def, count * sizeof(T))) { return *this; }