Merge remote-tracking branch 'gzdoom/master' into qzdoom

This commit is contained in:
Magnus Norddahl 2016-09-24 09:37:18 +02:00
commit 5ef46d1730
208 changed files with 21902 additions and 6688 deletions

View file

@ -81,10 +81,10 @@
#include "a_sharedglobal.h"
#include "a_strifeglobal.h"
#include "r_data/colormaps.h"
#include "farchive.h"
#include "r_renderer.h"
#include "r_utility.h"
#include "p_spec.h"
#include "serializer.h"
#include "gi.h"
@ -93,7 +93,7 @@
void STAT_StartNewGame(const char *lev);
void STAT_ChangeLevel(const char *newl);
EXTERN_CVAR(Bool, save_formatted)
EXTERN_CVAR (Float, sv_gravity)
EXTERN_CVAR (Float, sv_aircontrol)
EXTERN_CVAR (Int, disableautosave)
@ -822,7 +822,7 @@ void G_DoCompleted (void)
}
else
{ // Make sure we don't have a snapshot lying around from before.
level.info->ClearSnapshot();
level.info->Snapshot.Clean();
}
}
else
@ -1477,135 +1477,6 @@ void G_AirControlChanged ()
}
}
//==========================================================================
//
//
//==========================================================================
void gl_SerializeGlobals(FArchive &arc);
void G_SerializeLevel (FArchive &arc, bool hubLoad)
{
int i = level.totaltime;
Renderer->StartSerialize(arc);
if (arc.IsLoading()) P_DestroyThinkers(hubLoad);
gl_SerializeGlobals(arc);
arc << level.flags
<< level.flags2
<< level.fadeto
<< level.found_secrets
<< level.found_items
<< level.killed_monsters
<< level.gravity
<< level.aircontrol
<< level.teamdamage
<< level.maptime
<< i;
// Hub transitions must keep the current total time
if (!hubLoad)
level.totaltime = i;
arc << level.skytexture1 << level.skytexture2;
if (arc.IsLoading())
{
sky1texture = level.skytexture1;
sky2texture = level.skytexture2;
R_InitSkyMap();
}
G_AirControlChanged ();
BYTE t;
// Does this level have scrollers?
if (arc.IsStoring ())
{
t = level.Scrolls ? 1 : 0;
arc << t;
}
else
{
arc << t;
if (level.Scrolls)
{
delete[] level.Scrolls;
level.Scrolls = NULL;
}
if (t)
{
level.Scrolls = new FSectorScrollValues[numsectors];
memset (level.Scrolls, 0, sizeof(level.Scrolls)*numsectors);
}
}
FBehavior::StaticSerializeModuleStates (arc);
if (arc.IsLoading()) interpolator.ClearInterpolations();
P_SerializeWorld(arc);
P_SerializeThinkers (arc, hubLoad);
P_SerializeWorldActors(arc); // serializing actor pointers in the world data must be done after SerializeWorld has restored the entire sector state, otherwise LinkToWorld may fail.
P_SerializePolyobjs (arc);
P_SerializeSubsectors(arc);
StatusBar->Serialize (arc);
arc << level.total_monsters << level.total_items << level.total_secrets;
// Does this level have custom translations?
FRemapTable *trans;
WORD w;
if (arc.IsStoring ())
{
for (unsigned int i = 0; i < translationtables[TRANSLATION_LevelScripted].Size(); ++i)
{
trans = translationtables[TRANSLATION_LevelScripted][i];
if (trans != NULL && !trans->IsIdentity())
{
w = WORD(i);
arc << w;
trans->Serialize(arc);
}
}
w = 0xffff;
arc << w;
}
else
{
while (arc << w, w != 0xffff)
{
trans = translationtables[TRANSLATION_LevelScripted].GetVal(w);
if (trans == NULL)
{
trans = new FRemapTable;
translationtables[TRANSLATION_LevelScripted].SetVal(w, trans);
}
trans->Serialize(arc);
}
}
// This must be saved, too, of course!
FCanvasTextureInfo::Serialize (arc);
AM_SerializeMarkers(arc);
P_SerializePlayers (arc, hubLoad);
P_SerializeSounds (arc);
if (arc.IsLoading())
{
for (i = 0; i < numsectors; i++)
{
P_Recalculate3DFloors(&sectors[i]);
}
for (i = 0; i < MAXPLAYERS; ++i)
{
if (playeringame[i] && players[i].mo != NULL)
{
players[i].mo->SetupWeaponSlots();
}
}
}
Renderer->EndSerialize(arc);
}
//==========================================================================
//
// Archives the current level
@ -1614,19 +1485,18 @@ void G_SerializeLevel (FArchive &arc, bool hubLoad)
void G_SnapshotLevel ()
{
if (level.info->snapshot)
delete level.info->snapshot;
level.info->Snapshot.Clean();
if (level.info->isValid())
{
level.info->snapshotVer = SAVEVER;
level.info->snapshot = new FCompressedMemFile;
level.info->snapshot->Open ();
FSerializer arc;
FArchive arc (*level.info->snapshot);
SaveVersion = SAVEVER;
G_SerializeLevel (arc, false);
if (arc.OpenWriter(save_formatted))
{
SaveVersion = SAVEVER;
G_SerializeLevel(arc, false);
level.info->Snapshot = arc.GetCompressedOutput();
}
}
}
@ -1639,18 +1509,15 @@ void G_SnapshotLevel ()
void G_UnSnapshotLevel (bool hubLoad)
{
if (level.info->snapshot == NULL)
if (level.info->Snapshot.mBuffer == nullptr)
return;
if (level.info->isValid())
{
SaveVersion = level.info->snapshotVer;
level.info->snapshot->Reopen ();
FArchive arc (*level.info->snapshot);
if (hubLoad)
arc.SetHubTravel ();
FSerializer arc;
if (!arc.OpenReader(&level.info->Snapshot)) return;
G_SerializeLevel (arc, hubLoad);
arc.Close ();
level.FromSnapshot = true;
TThinkerIterator<APlayerPawn> it;
@ -1680,7 +1547,7 @@ void G_UnSnapshotLevel (bool hubLoad)
}
}
// No reason to keep the snapshot around once the level's been entered.
level.info->ClearSnapshot();
level.info->Snapshot.Clean();
if (hubLoad)
{
// Unlock ACS global strings that were locked when the snapshot was made.
@ -1693,10 +1560,28 @@ void G_UnSnapshotLevel (bool hubLoad)
//
//==========================================================================
static void writeSnapShot (FArchive &arc, level_info_t *i)
void G_WriteSnapshots(TArray<FString> &filenames, TArray<FCompressedBuffer> &buffers)
{
arc << i->snapshotVer << i->MapName;
i->snapshot->Serialize (arc);
unsigned int i;
FString filename;
for (i = 0; i < wadlevelinfos.Size(); i++)
{
if (wadlevelinfos[i].Snapshot.mCompressedSize > 0)
{
filename.Format("%s.map.json", wadlevelinfos[i].MapName.GetChars());
filename.ToLower();
filenames.Push(filename);
buffers.Push(wadlevelinfos[i].Snapshot);
}
}
if (TheDefaultLevelInfo.Snapshot.mCompressedSize > 0)
{
filename.Format("%s.mapd.json", TheDefaultLevelInfo.MapName.GetChars());
filename.ToLower();
filenames.Push(filename);
buffers.Push(TheDefaultLevelInfo.Snapshot);
}
}
//==========================================================================
@ -1704,70 +1589,39 @@ static void writeSnapShot (FArchive &arc, level_info_t *i)
//
//==========================================================================
void G_WriteSnapshots (FILE *file)
void G_WriteVisited(FSerializer &arc)
{
unsigned int i;
for (i = 0; i < wadlevelinfos.Size(); i++)
if (arc.BeginArray("visited"))
{
if (wadlevelinfos[i].snapshot)
// Write out which levels have been visited
for (auto & wi : wadlevelinfos)
{
FPNGChunkArchive arc (file, SNAP_ID);
writeSnapShot (arc, (level_info_t *)&wadlevelinfos[i]);
}
}
if (TheDefaultLevelInfo.snapshot != NULL)
{
FPNGChunkArchive arc (file, DSNP_ID);
writeSnapShot(arc, &TheDefaultLevelInfo);
}
FPNGChunkArchive *arc = NULL;
// Write out which levels have been visited
for (i = 0; i < wadlevelinfos.Size(); ++i)
{
if (wadlevelinfos[i].flags & LEVEL_VISITED)
{
if (arc == NULL)
if (wi.flags & LEVEL_VISITED)
{
arc = new FPNGChunkArchive (file, VIST_ID);
arc.AddString(nullptr, wi.MapName);
}
(*arc) << wadlevelinfos[i].MapName;
}
}
if (arc != NULL)
{
FString empty = "";
(*arc) << empty;
delete arc;
arc.EndArray();
}
// Store player classes to be used when spawning a random class
if (multiplayer)
{
FPNGChunkArchive arc2 (file, RCLS_ID);
for (i = 0; i < MAXPLAYERS; ++i)
{
SBYTE cnum = SinglePlayerClass[i];
arc2 << cnum;
}
arc.Array("randomclasses", SinglePlayerClass, MAXPLAYERS);
}
// Store player classes that are currently in use
FPNGChunkArchive arc3 (file, PCLS_ID);
for (i = 0; i < MAXPLAYERS; ++i)
if (arc.BeginObject("playerclasses"))
{
BYTE pnum;
if (playeringame[i])
for (int i = 0; i < MAXPLAYERS; ++i)
{
pnum = i;
arc3 << pnum;
arc3.UserWriteClass (players[i].cls);
if (playeringame[i])
{
FString key;
key.Format("%d", i);
arc(key, players[i].cls);
}
}
pnum = 255;
arc3 << pnum;
arc.EndObject();
}
}
@ -1776,95 +1630,89 @@ void G_WriteSnapshots (FILE *file)
//
//==========================================================================
void G_ReadSnapshots (PNGHandle *png)
void G_ReadSnapshots(FResourceFile *resf)
{
DWORD chunkLen;
FString MapName;
level_info_t *i;
G_ClearSnapshots ();
G_ClearSnapshots();
chunkLen = (DWORD)M_FindPNGChunk (png, SNAP_ID);
while (chunkLen != 0)
for (unsigned j = 0; j < resf->LumpCount(); j++)
{
FPNGChunkArchive arc (png->File->GetFile(), SNAP_ID, chunkLen);
DWORD snapver;
arc << snapver;
arc << MapName;
i = FindLevelInfo (MapName);
i->snapshotVer = snapver;
i->snapshot = new FCompressedMemFile;
i->snapshot->Serialize (arc);
chunkLen = (DWORD)M_NextPNGChunk (png, SNAP_ID);
}
chunkLen = (DWORD)M_FindPNGChunk (png, DSNP_ID);
if (chunkLen != 0)
{
FPNGChunkArchive arc (png->File->GetFile(), DSNP_ID, chunkLen);
DWORD snapver;
arc << snapver;
arc << MapName;
TheDefaultLevelInfo.snapshotVer = snapver;
TheDefaultLevelInfo.snapshot = new FCompressedMemFile;
TheDefaultLevelInfo.snapshot->Serialize (arc);
}
chunkLen = (DWORD)M_FindPNGChunk (png, VIST_ID);
if (chunkLen != 0)
{
FPNGChunkArchive arc (png->File->GetFile(), VIST_ID, chunkLen);
while (arc << MapName, MapName.Len() > 0)
FResourceLump * resl = resf->GetLump(j);
if (resl != nullptr)
{
i = FindLevelInfo(MapName);
i->flags |= LEVEL_VISITED;
auto ptr = strstr(resl->FullName, ".map.json");
if (ptr != nullptr)
{
ptrdiff_t maplen = ptr - resl->FullName.GetChars();
FString mapname(resl->FullName.GetChars(), (size_t)maplen);
i = FindLevelInfo(mapname);
if (i != nullptr)
{
i->Snapshot = resl->GetRawData();
}
}
else
{
auto ptr = strstr(resl->FullName, ".mapd.json");
if (ptr != nullptr)
{
ptrdiff_t maplen = ptr - resl->FullName.GetChars();
FString mapname(resl->FullName.GetChars(), (size_t)maplen);
TheDefaultLevelInfo.Snapshot = resl->GetRawData();
}
}
}
}
chunkLen = (DWORD)M_FindPNGChunk (png, RCLS_ID);
if (chunkLen != 0)
{
FPNGChunkArchive arc (png->File->GetFile(), PCLS_ID, chunkLen);
SBYTE cnum;
for (DWORD j = 0; j < chunkLen; ++j)
{
arc << cnum;
SinglePlayerClass[j] = cnum;
}
}
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();
}
//==========================================================================
//
//
//==========================================================================
void G_ReadVisited(FSerializer &arc)
{
if (arc.BeginArray("visited"))
{
for (int s = arc.ArraySize(); s > 0; s--)
{
FString str;
arc(nullptr, str);
auto i = FindLevelInfo(str);
if (i != nullptr) i->flags |= LEVEL_VISITED;
}
arc.EndArray();
}
arc.Array("randomclasses", SinglePlayerClass, MAXPLAYERS);
if (arc.BeginObject("playerclasses"))
{
for (int i = 0; i < MAXPLAYERS; ++i)
{
FString key;
key.Format("%d", i);
arc(key, players[i].cls);
}
arc.EndObject();
}
}
//==========================================================================
//
//
//==========================================================================
CCMD(listsnapshots)
{
for (unsigned i = 0; i < wadlevelinfos.Size(); ++i)
{
FCompressedMemFile *snapshot = wadlevelinfos[i].snapshot;
if (snapshot != NULL)
FCompressedBuffer *snapshot = &wadlevelinfos[i].Snapshot;
if (snapshot->mBuffer != nullptr)
{
unsigned int comp, uncomp;
snapshot->GetSizes(comp, uncomp);
Printf("%s (%u -> %u bytes)\n", wadlevelinfos[i].MapName.GetChars(), comp, uncomp);
Printf("%s (%u -> %u bytes)\n", wadlevelinfos[i].MapName.GetChars(), snapshot->mCompressedSize, snapshot->mSize);
}
}
}
@ -1874,38 +1722,32 @@ CCMD(listsnapshots)
//
//==========================================================================
static void writeDefereds (FArchive &arc, level_info_t *i)
void P_WriteACSDefereds (FSerializer &arc)
{
arc << i->MapName << i->defered;
}
bool found = false;
//==========================================================================
//
//
//==========================================================================
void P_WriteACSDefereds (FILE *file)
{
FPNGChunkArchive *arc = NULL;
for (unsigned int i = 0; i < wadlevelinfos.Size(); i++)
// only write this stuff if needed
for (auto &wi : wadlevelinfos)
{
if (wadlevelinfos[i].defered)
if (wi.deferred.Size() > 0)
{
if (arc == NULL)
found = true;
break;
}
}
if (found && arc.BeginObject("deferred"))
{
for (auto &wi : wadlevelinfos)
{
if (wi.deferred.Size() > 0)
{
arc = new FPNGChunkArchive (file, ACSD_ID);
if (wi.deferred.Size() > 0)
{
arc(wi.MapName, wi.deferred);
}
}
writeDefereds (*arc, (level_info_t *)&wadlevelinfos[i]);
}
}
if (arc != NULL)
{
// Signal end of defereds
FString empty = "";
(*arc) << empty;
delete arc;
arc.EndObject();
}
}
@ -1914,28 +1756,27 @@ void P_WriteACSDefereds (FILE *file)
//
//==========================================================================
void P_ReadACSDefereds (PNGHandle *png)
void P_ReadACSDefereds (FSerializer &arc)
{
FString MapName;
size_t chunklen;
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)
{
I_Error("Unknown map '%s' in savegame", MapName.GetChars());
I_Error("Unknown map '%s' in savegame", key);
}
arc << i->defered;
arc(nullptr, i->deferred);
}
arc.EndObject();
}
png->File->ResetFilePtr();
}
@ -1947,9 +1788,9 @@ void P_ReadACSDefereds (PNGHandle *png)
void FLevelLocals::Tick ()
{
// Reset carry sectors
if (Scrolls != NULL)
if (Scrolls.Size() > 0)
{
memset (Scrolls, 0, sizeof(*Scrolls)*numsectors);
memset (&Scrolls[0], 0, sizeof(Scrolls[0])*Scrolls.Size());
}
}
@ -1964,10 +1805,10 @@ void FLevelLocals::AddScroller (int secnum)
{
return;
}
if (Scrolls == NULL)
if (Scrolls.Size() == 0)
{
Scrolls = new FSectorScrollValues[numsectors];
memset (Scrolls, 0, sizeof(*Scrolls)*numsectors);
Scrolls.Resize(numsectors);
memset (&Scrolls[0], 0, sizeof(Scrolls[0])*numsectors);
}
}