- converted the basic savegame loader so that all remnant of FArchive have been removed now.

This commit is contained in:
Christoph Oelckers 2016-09-22 00:18:31 +02:00
parent 88c27e2cc0
commit 1c9dbc3c36
11 changed files with 187 additions and 239 deletions

View file

@ -14,7 +14,6 @@
#include "a_specialspot.h" #include "a_specialspot.h"
#include "templates.h" #include "templates.h"
#include "m_bbox.h" #include "m_bbox.h"
#include "farchive.h"
#include "portal.h" #include "portal.h"
#include "d_player.h" #include "d_player.h"
#include "p_maputl.h" #include "p_maputl.h"

View file

@ -1830,10 +1830,6 @@ bool G_CheckSaveGameWads (FSerializer &arc, bool printwarn)
void G_DoLoadGame () void G_DoLoadGame ()
{ {
#if 0 // SAVEGAME
char sigcheck[20];
char *text = NULL;
char *map;
bool hidecon; bool hidecon;
if (gameaction != ga_autoloadgame) if (gameaction != ga_autoloadgame)
@ -1843,76 +1839,82 @@ void G_DoLoadGame ()
hidecon = gameaction == ga_loadgamehidecon; hidecon = gameaction == ga_loadgamehidecon;
gameaction = ga_nothing; gameaction = ga_nothing;
FILE *stdfile = fopen (savename.GetChars(), "rb"); FResourceFile *resfile = FResourceFile::OpenResourceFile(savename.GetChars(), nullptr, true, true);
if (stdfile == NULL) if (resfile == nullptr)
{ {
Printf ("Could not read savegame '%s'\n", savename.GetChars()); Printf ("Could not read savegame '%s'\n", savename.GetChars());
return; return;
} }
PNGHandle *png = M_VerifyPNG (stdfile); FResourceLump *info = resfile->FindLump("info.json");
if (png == NULL) if (info == nullptr)
{ {
fclose (stdfile); delete resfile;
Printf ("'%s' is not a valid (PNG) savegame\n", savename.GetChars()); Printf ("'%s' is not a valid savegame: Missing 'info.json'.\n", savename.GetChars());
return; return;
} }
SaveVersion = 0; SaveVersion = 0;
void *data = info->CacheLump();
FSerializer arc;
if (!arc.OpenReader((const char *)data, info->LumpSize, true))
{
Printf("Failed to access savegame info\n");
delete resfile;
return;
}
// Check whether this savegame actually has been created by a compatible engine. // Check whether this savegame actually has been created by a compatible engine.
// Since there are ZDoom derivates using the exact same savegame format but // Since there are ZDoom derivates using the exact same savegame format but
// with mutual incompatibilities this check simplifies things significantly. // with mutual incompatibilities this check simplifies things significantly.
char *engine = M_GetPNGText (png, "Engine"); FString savever, engine, map;
if (engine == NULL || 0 != strcmp (engine, GAMESIG)) arc("Save Version", SaveVersion);
arc("Engine", engine);
arc("Current Map", map);
if (engine.CompareNoCase(GAMESIG) != 0)
{ {
// Make a special case for the message printed for old savegames that don't // Make a special case for the message printed for old savegames that don't
// have this information. // have this information.
if (engine == NULL) if (engine.IsEmpty())
{ {
Printf ("Savegame is from an incompatible version\n"); Printf ("Savegame is from an incompatible version\n");
} }
else else
{ {
Printf ("Savegame is from another ZDoom-based engine: %s\n", engine); Printf ("Savegame is from another ZDoom-based engine: %s\n", engine);
delete[] engine;
} }
delete png; delete resfile;
fclose (stdfile);
return; return;
} }
if (engine != NULL)
{
delete[] engine;
}
SaveVersion = 0; if (SaveVersion < MINSAVEVER || SaveVersion > SAVEVER)
if (!M_GetPNGText (png, "ZDoom Save Version", sigcheck, 20) ||
0 != strncmp (sigcheck, "SAVEVER", 9) || // ZDOOMSAVE is the first 9 chars
(SaveVersion = atoi (sigcheck+9)) < MINSAVEVER)
{ {
delete png; delete resfile;
fclose (stdfile);
Printf ("Savegame is from an incompatible version"); Printf ("Savegame is from an incompatible version");
if (SaveVersion != 0) if (SaveVersion < MINSAVEVER)
{ {
Printf(": %d (%d is the oldest supported)", SaveVersion, MINSAVEVER); Printf(": %d (%d is the oldest supported)", SaveVersion, MINSAVEVER);
} }
else
{
Printf(": %d (%d is the highest supported)", SaveVersion, SAVEVER);
}
Printf("\n"); Printf("\n");
return; return;
} }
if (!G_CheckSaveGameWads (png, true)) if (!G_CheckSaveGameWads (arc, true))
{ {
fclose (stdfile); delete resfile;
return; return;
} }
map = M_GetPNGText (png, "Current Map"); if (map.IsEmpty())
if (map == NULL)
{ {
Printf ("Savegame is missing the current map\n"); Printf ("Savegame is missing the current map\n");
fclose (stdfile); delete resfile;
return; return;
} }
@ -1922,35 +1924,46 @@ void G_DoLoadGame ()
{ {
gamestate = GS_HIDECONSOLE; gamestate = GS_HIDECONSOLE;
} }
// we are done with info.json.
arc.Close();
info = resfile->FindLump("global.json");
if (info == nullptr)
{
delete resfile;
Printf("'%s' is not a valid savegame: Missing 'global.json'.\n", savename.GetChars());
return;
}
data = info->CacheLump();
if (!arc.OpenReader((const char *)data, info->LumpSize, true))
{
Printf("Failed to access savegame info\n");
delete resfile;
return;
}
// Read intermission data for hubs // Read intermission data for hubs
G_ReadHubInfo(png); G_SerializeHub(arc);
bglobal.RemoveAllBots (true); bglobal.RemoveAllBots (true);
text = M_GetPNGText (png, "Important CVARs"); arc("importantcvars", map);
if (text != NULL) if (!map.IsEmpty())
{ {
BYTE *vars_p = (BYTE *)text; BYTE *vars_p = (BYTE *)map.GetChars();
C_ReadCVars (&vars_p); C_ReadCVars (&vars_p);
delete[] text;
} }
DWORD time[2] = { 0,1 };
arc("ticrate", time[0])
("leveltime", time[1]);
// dearchive all the modifications // dearchive all the modifications
if (M_FindPNGChunk (png, MAKE_ID('p','t','I','c')) == 8) level.time = Scale (time[1], TICRATE, time[0]);
{
DWORD time[2];
fread (&time, 8, 1, stdfile);
time[0] = BigLong((unsigned int)time[0]);
time[1] = BigLong((unsigned int)time[1]);
level.time = Scale (time[1], TICRATE, time[0]);
}
else
{ // No ptIc chunk so we don't know how long the user was playing
level.time = 0;
}
G_ReadSnapshots (png); //G_ReadSnapshots(png);
// load a base level // load a base level
savegamerestore = true; // Use the player actors in the savegame savegamerestore = true; // Use the player actors in the savegame
@ -1960,31 +1973,24 @@ void G_DoLoadGame ()
delete[] map; delete[] map;
savegamerestore = false; savegamerestore = false;
STAT_Read(png); STAT_Serialize(arc);
FRandom::StaticReadRNGState(png); FRandom::StaticReadRNGState(arc);
P_ReadACSDefereds(png); P_ReadACSDefereds(arc);
P_ReadACSVars(png); P_ReadACSVars(arc);
NextSkill = -1; NextSkill = -1;
if (M_FindPNGChunk (png, MAKE_ID('s','n','X','t')) == 1) arc("nextskill", NextSkill);
{
BYTE next;
fread (&next, 1, 1, stdfile);
NextSkill = next;
}
level.info->Snapshot.Clean(); level.info->Snapshot.Clean();
BackupSaveName = savename; BackupSaveName = savename;
delete png; delete resfile;
fclose (stdfile);
// At this point, the GC threshold is likely a lot higher than the // At this point, the GC threshold is likely a lot higher than the
// amount of memory in use, so bring it down now by starting a // amount of memory in use, so bring it down now by starting a
// collection. // collection.
GC::StartCollection(); GC::StartCollection();
#endif
} }

View file

@ -1630,83 +1630,71 @@ void G_WriteVisited(FSerializer &arc)
// //
//========================================================================== //==========================================================================
void G_ReadSnapshots (PNGHandle *png) void G_ReadSnapshots(PNGHandle *png)
{ {
DWORD chunkLen; DWORD chunkLen;
FString MapName; FString MapName;
level_info_t *i; level_info_t *i;
G_ClearSnapshots (); G_ClearSnapshots();
chunkLen = (DWORD)M_FindPNGChunk (png, SNAP_ID); chunkLen = (DWORD)M_FindPNGChunk(png, SNAP_ID);
while (chunkLen != 0) while (chunkLen != 0)
{ {
FPNGChunkArchive arc (png->File->GetFile(), SNAP_ID, chunkLen); #if 0
FPNGChunkArchive arc(png->File->GetFile(), SNAP_ID, chunkLen);
DWORD snapver; DWORD snapver;
arc << snapver; arc << snapver;
arc << MapName; arc << MapName;
i = FindLevelInfo (MapName); i = FindLevelInfo(MapName);
#if 0
i->snapshot = new FCompressedMemFile; i->snapshot = new FCompressedMemFile;
i->snapshot->Serialize (arc); i->snapshot->Serialize(arc);
chunkLen = (DWORD)M_NextPNGChunk(png, SNAP_ID);
#endif #endif
chunkLen = (DWORD)M_NextPNGChunk (png, SNAP_ID);
} }
chunkLen = (DWORD)M_FindPNGChunk (png, DSNP_ID); chunkLen = (DWORD)M_FindPNGChunk(png, DSNP_ID);
if (chunkLen != 0) if (chunkLen != 0)
{ {
FPNGChunkArchive arc (png->File->GetFile(), DSNP_ID, chunkLen); #if 0
FPNGChunkArchive arc(png->File->GetFile(), DSNP_ID, chunkLen);
DWORD snapver; DWORD snapver;
arc << snapver; arc << snapver;
arc << MapName; arc << MapName;
#if 0
TheDefaultLevelInfo.snapshot = new FCompressedMemFile; TheDefaultLevelInfo.snapshot = new FCompressedMemFile;
TheDefaultLevelInfo.snapshot->Serialize (arc); TheDefaultLevelInfo.snapshot->Serialize(arc);
#endif #endif
} }
}
chunkLen = (DWORD)M_FindPNGChunk (png, VIST_ID); void G_ReadVisited(FSerializer &arc)
if (chunkLen != 0) {
if (arc.BeginArray("visited"))
{ {
FPNGChunkArchive arc (png->File->GetFile(), VIST_ID, chunkLen); for (int s = arc.ArraySize(); s > 0; s--)
while (arc << MapName, MapName.Len() > 0)
{ {
i = FindLevelInfo(MapName); FString str;
i->flags |= LEVEL_VISITED; arc(nullptr, str);
auto i = FindLevelInfo(str);
if (i != nullptr) i->flags |= LEVEL_VISITED;
} }
arc.EndArray();
} }
chunkLen = (DWORD)M_FindPNGChunk (png, RCLS_ID); arc.Array("randomclasses", SinglePlayerClass, MAXPLAYERS);
if (chunkLen != 0)
if (arc.BeginObject("playerclasses"))
{ {
FPNGChunkArchive arc (png->File->GetFile(), PCLS_ID, chunkLen); for (int i = 0; i < MAXPLAYERS; ++i)
SBYTE cnum;
for (DWORD j = 0; j < chunkLen; ++j)
{ {
arc << cnum; FString key;
SinglePlayerClass[j] = cnum; key.Format("%d", i);
arc(key, players[i].cls);
} }
arc.EndObject();
} }
chunkLen = (DWORD)M_FindPNGChunk (png, PCLS_ID);
if (chunkLen != 0)
{
FPNGChunkArchive arc (png->File->GetFile(), RCLS_ID, chunkLen);
BYTE pnum;
arc << pnum;
while (pnum != 255)
{
arc.UserReadClass (players[pnum].cls);
arc << pnum;
}
}
png->File->ResetFilePtr();
} }
//========================================================================== //==========================================================================
@ -1749,8 +1737,7 @@ void P_WriteACSDefereds (FSerializer &arc)
{ {
if (wi.deferred.Size() > 0 && arc.BeginObject(nullptr)) if (wi.deferred.Size() > 0 && arc.BeginObject(nullptr))
{ {
arc(wi.MapName, wi.deferred) arc(wi.MapName, wi.deferred);
.EndObject();
} }
} }
} }
@ -1763,30 +1750,28 @@ void P_WriteACSDefereds (FSerializer &arc)
// //
//========================================================================== //==========================================================================
void P_ReadACSDefereds (PNGHandle *png) void P_ReadACSDefereds (FSerializer &arc)
{ {
#if 0
FString MapName; FString MapName;
size_t chunklen; size_t chunklen;
P_RemoveDefereds (); P_RemoveDefereds ();
if ((chunklen = M_FindPNGChunk (png, ACSD_ID)) != 0) if (arc.BeginObject("deferred"))
{ {
FPNGChunkArchive arc (png->File->GetFile(), ACSD_ID, chunklen); const char *key;
while (arc << MapName, MapName.Len() > 0) while ((key = arc.GetKey()))
{ {
level_info_t *i = FindLevelInfo(MapName); level_info_t *i = FindLevelInfo(key);
if (i == NULL) if (i == NULL)
{ {
I_Error("Unknown map '%s' in savegame", MapName.GetChars()); I_Error("Unknown map '%s' in savegame", key);
} }
arc << i->deferred; arc(key, i->deferred);
} }
arc.EndObject();
} }
png->File->ResetFilePtr();
#endif
} }

View file

@ -536,6 +536,7 @@ struct PNGHandle;
void G_ReadSnapshots (PNGHandle *png); void G_ReadSnapshots (PNGHandle *png);
void G_WriteSnapshots (TArray<FString> &, TArray<FCompressedBuffer> &); void G_WriteSnapshots (TArray<FString> &, TArray<FCompressedBuffer> &);
void G_WriteVisited(FSerializer &arc); void G_WriteVisited(FSerializer &arc);
void G_ReadVisited(FSerializer &arc);
void G_ClearHubInfo(); void G_ClearHubInfo();
enum ESkillProperty enum ESkillProperty

View file

@ -326,54 +326,36 @@ void FRandom::StaticWriteRNGState (FSerializer &arc)
// //
//========================================================================== //==========================================================================
void FRandom::StaticReadRNGState (PNGHandle *png) void FRandom::StaticReadRNGState(FSerializer &arc)
{ {
#if 0
FRandom *rng; FRandom *rng;
size_t len = M_FindPNGChunk (png, RAND_ID); arc("rngseed", rng);
if (arc.BeginArray("rngs"))
if (len != 0)
{ {
const size_t sizeof_rng = sizeof(rng->NameCRC) + sizeof(rng->idx) + sizeof(rng->sfmt.u); int count = arc.ArraySize();
const int rngcount = (int)((len-4) / sizeof_rng);
int i;
DWORD crc;
FPNGChunkArchive arc (png->File->GetFile(), RAND_ID, len); for (int i = 0; i < count; i++)
arc << rngseed;
FRandom::StaticClearRandom ();
for (i = rngcount; i; --i)
{ {
arc << crc; if (arc.BeginObject(nullptr))
for (rng = FRandom::RNGList; rng != NULL; rng = rng->Next)
{ {
if (rng->NameCRC == crc) uint32_t crc;
arc("crc", crc);
for (rng = FRandom::RNGList; rng != NULL; rng = rng->Next)
{ {
arc << rng->idx; if (rng->NameCRC == crc)
for (int i = 0; i < SFMT::N32; ++i)
{ {
arc << rng->sfmt.u[i]; arc("index", rng->idx)
.Array("u", rng->sfmt.u, SFMT::N32);
break;
} }
break;
}
}
if (rng == NULL)
{ // The RNG was removed. Skip it.
int idx;
DWORD sfmt;
arc << idx;
for (int i = 0; i < SFMT::N32; ++i)
{
arc << sfmt;
} }
arc.EndObject();
} }
arc.EndArray();
} }
png->File->ResetFilePtr();
} }
#endif
} }
//========================================================================== //==========================================================================

View file

@ -175,7 +175,7 @@ public:
// Static interface // Static interface
static void StaticClearRandom (); static void StaticClearRandom ();
static DWORD StaticSumSeeds (); static DWORD StaticSumSeeds ();
static void StaticReadRNGState (PNGHandle *png); static void StaticReadRNGState (FSerializer &arc);
static void StaticWriteRNGState (FSerializer &file); static void StaticWriteRNGState (FSerializer &file);
static FRandom *StaticFindRNG(const char *name); static FRandom *StaticFindRNG(const char *name);

View file

@ -722,47 +722,42 @@ void ACSStringPool::FindFirstFreeEntry(unsigned base)
// //
//============================================================================ //============================================================================
void ACSStringPool::ReadStrings(PNGHandle *png, DWORD id) void ACSStringPool::ReadStrings(FSerializer &file, const char *key)
{ {
Clear(); Clear();
size_t len = M_FindPNGChunk(png, id); int32_t i, j, poolsize;
if (len != 0)
file("poolsize", poolsize);
Pool.Resize(poolsize);
for (auto &p : Pool)
{ {
FPNGChunkArchive arc(png->File->GetFile(), id, len); p.Next = FREE_ENTRY;
int32_t i, j, poolsize; p.LockCount = 0;
unsigned int h, bucketnum; }
char *str = NULL; if (file.BeginArray("pool"))
{
arc << poolsize; j = file.ArraySize();
for (int i = 0; i < j; i++)
Pool.Resize(poolsize);
i = 0;
j = arc.ReadCount();
while (j >= 0)
{ {
// Mark skipped entries as free if (file.BeginObject(nullptr))
for (; i < j; ++i)
{ {
Pool[i].Next = FREE_ENTRY; i = -1;
Pool[i].LockCount = 0; file("index", i);
if (i >= 0 && i < Pool.Size())
{
file("string", Pool[i].Str)
("lockcount", Pool[i].LockCount);
unsigned h = SuperFastHash(Pool[i].Str, Pool[i].Str.Len());
unsigned bucketnum = h % NUM_BUCKETS;
Pool[i].Hash = h;
Pool[i].Next = PoolBuckets[bucketnum];
PoolBuckets[bucketnum] = i;
}
file.EndObject();
} }
arc << str;
h = SuperFastHash(str, strlen(str));
bucketnum = h % NUM_BUCKETS;
Pool[i].Str = str;
Pool[i].Hash = h;
Pool[i].LockCount = arc.ReadCount();
Pool[i].Next = PoolBuckets[bucketnum];
PoolBuckets[bucketnum] = i;
i++;
j = arc.ReadCount();
} }
if (str != NULL)
{
delete[] str;
}
FindFirstFreeEntry(0);
} }
} }
@ -982,29 +977,10 @@ static void WriteVars (FSerializer &file, SDWORD *vars, size_t count, const char
// //
//============================================================================ //============================================================================
static void ReadVars (PNGHandle *png, SDWORD *vars, size_t count, DWORD id) static void ReadVars (FSerializer &arc, SDWORD *vars, size_t count, const char *key)
{ {
size_t len = M_FindPNGChunk (png, id); memset(&vars[0], 0, count * 4);
size_t used = 0; arc.Array(key, vars, count);
if (len != 0)
{
DWORD var;
size_t i;
FPNGChunkArchive arc (png->File->GetFile(), id, len);
used = len / 4;
for (i = 0; i < used; ++i)
{
arc << var;
vars[i] = var;
}
png->File->ResetFilePtr();
}
if (used < count)
{
memset (&vars[used], 0, (count-used)*4);
}
} }
//============================================================================ //============================================================================
@ -1060,37 +1036,32 @@ static void WriteArrayVars (FSerializer &file, FWorldGlobalArray *vars, unsigned
// //
//============================================================================ //============================================================================
static void ReadArrayVars (PNGHandle *png, FWorldGlobalArray *vars, size_t count, DWORD id) static void ReadArrayVars (FSerializer &file, FWorldGlobalArray *vars, size_t count, const char *key)
{ {
size_t len = M_FindPNGChunk (png, id);
unsigned int i, k;
for (i = 0; i < count; ++i) for (i = 0; i < count; ++i)
{ {
vars[i].Clear (); vars[i].Clear();
} }
if (len != 0) if (file.BeginObject(key))
{ {
DWORD max, size; const char *arraykey;
FPNGChunkArchive arc (png->File->GetFile(), id, len); while ((arraykey = file.GetKey()))
i = arc.ReadCount ();
max = arc.ReadCount ();
for (; i <= max; ++i)
{ {
size = arc.ReadCount (); int i = (int)strtol(arraykey, nullptr, 10);
for (k = 0; k < size; ++k) if (file.BeginObject(arraykey))
{ {
SDWORD key, val; while ((arraykey = file.GetKey()))
key = arc.ReadCount(); {
int k = (int)strtol(arraykey, nullptr, 10);
val = arc.ReadCount(); int val;
vars[i].Insert (key, val); file(arraykey, val);
vars[i].Insert(k, val);
}
file.EndObject();
} }
} }
png->File->ResetFilePtr(); file.EndObject();
} }
} }
@ -1100,13 +1071,13 @@ static void ReadArrayVars (PNGHandle *png, FWorldGlobalArray *vars, size_t count
// //
//============================================================================ //============================================================================
void P_ReadACSVars(PNGHandle *png) void P_ReadACSVars(FSerializer &arc)
{ {
ReadVars (png, ACS_WorldVars, NUM_WORLDVARS, MAKE_ID('w','v','A','r')); ReadVars (arc, ACS_WorldVars, NUM_WORLDVARS, "acsworldvars");
ReadVars (png, ACS_GlobalVars, NUM_GLOBALVARS, MAKE_ID('g','v','A','r')); ReadVars (arc, ACS_GlobalVars, NUM_GLOBALVARS, "acsglobalvars");
ReadArrayVars (png, ACS_WorldArrays, NUM_WORLDVARS, MAKE_ID('w','a','R','r')); ReadArrayVars (arc, ACS_WorldArrays, NUM_WORLDVARS, "acsworldarrays");
ReadArrayVars (png, ACS_GlobalArrays, NUM_GLOBALVARS, MAKE_ID('g','a','R','r')); ReadArrayVars (arc, ACS_GlobalArrays, NUM_GLOBALVARS, "acsglobalarrays");
GlobalACSStrings.ReadStrings(png, MAKE_ID('a','s','T','r')); GlobalACSStrings.ReadStrings(arc, "acsglobalstrings");
} }
//============================================================================ //============================================================================

View file

@ -96,7 +96,7 @@ public:
void PurgeStrings(); void PurgeStrings();
void Clear(); void Clear();
void Dump() const; void Dump() const;
void ReadStrings(PNGHandle *png, DWORD id); void ReadStrings(FSerializer &file, const char *key);
void WriteStrings(FSerializer &file, const char *key) const; void WriteStrings(FSerializer &file, const char *key) const;
private: private:
@ -122,7 +122,7 @@ private:
extern ACSStringPool GlobalACSStrings; extern ACSStringPool GlobalACSStrings;
void P_CollectACSGlobalStrings(); void P_CollectACSGlobalStrings();
void P_ReadACSVars(PNGHandle *); void P_ReadACSVars(FSerializer &);
void P_WriteACSVars(FSerializer &); void P_WriteACSVars(FSerializer &);
void P_ClearACSVars(bool); void P_ClearACSVars(bool);

View file

@ -42,7 +42,7 @@ class FSerializer;
// Also see farchive.(h|cpp) // Also see farchive.(h|cpp)
void P_DestroyThinkers(bool hubLoad); void P_DestroyThinkers(bool hubLoad);
void P_ReadACSDefereds (PNGHandle *png); void P_ReadACSDefereds (FSerializer &);
void P_WriteACSDefereds (FSerializer &); void P_WriteACSDefereds (FSerializer &);
void G_SerializeLevel(FSerializer &arc, bool hubLoad); void G_SerializeLevel(FSerializer &arc, bool hubLoad);

View file

@ -730,7 +730,7 @@ const char *FSerializer::GetKey()
void FSerializer::WriteObjects() void FSerializer::WriteObjects()
{ {
if (isWriting()) if (isWriting() && w->mDObjects.Size())
{ {
BeginArray("objects"); BeginArray("objects");
// we cannot use the C++11 shorthand syntax here because the array may grow while being processed. // we cannot use the C++11 shorthand syntax here because the array may grow while being processed.
@ -769,6 +769,7 @@ void FSerializer::WriteObjects()
const char *FSerializer::GetOutput(unsigned *len) const char *FSerializer::GetOutput(unsigned *len)
{ {
if (isReading()) return nullptr; if (isReading()) return nullptr;
WriteObjects();
EndObject(); EndObject();
if (len != nullptr) if (len != nullptr)
{ {
@ -787,6 +788,7 @@ FCompressedBuffer FSerializer::GetCompressedOutput()
{ {
if (isReading()) return{ 0,0,0,0,0,nullptr }; if (isReading()) return{ 0,0,0,0,0,nullptr };
FCompressedBuffer buff; FCompressedBuffer buff;
WriteObjects();
EndObject(); EndObject();
buff.mSize = (unsigned)w->mOutString.GetSize(); buff.mSize = (unsigned)w->mOutString.GetSize();
buff.mZipFlags = 0; buff.mZipFlags = 0;

View file

@ -111,6 +111,8 @@ public:
if (BeginArray(key)) if (BeginArray(key))
{ {
int max = ArraySize();
if (max < count) count = max;
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
{ {
Serialize(*this, nullptr, obj[i], (T*)nullptr); Serialize(*this, nullptr, obj[i], (T*)nullptr);