- added the last missing bits of the savegame code - thinker list deserialization and handling of players during hub travel. Now testing is what remains...

This commit is contained in:
Christoph Oelckers 2016-09-23 17:49:33 +02:00
parent edb7f7959e
commit 01d28e3eb2
6 changed files with 130 additions and 63 deletions

View file

@ -1001,7 +1001,6 @@ set( FASTMATH_SOURCES
)
set (PCH_SOURCES
json.cpp
actorptrselect.cpp
am_map.cpp
b_bot.cpp

View file

@ -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;

View file

@ -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
{
}
}

View file

@ -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)

View file

@ -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<APlayerPawn*>(r->mDObjects[pindex]);
}
}
}
}
DThinker::bSerialOverride = false;
assert(!founderrors);
if (founderrors)

View file

@ -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<class T>
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<class T>
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<class T>
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;
}