mirror of
https://github.com/ZDoom/raze-gles.git
synced 2024-12-24 10:40:46 +00:00
- transitioned all JSON-based savegame code to FSerializer and removed sjson.
Now everything is in place to transition the rest of the savegame code as well.
This commit is contained in:
parent
1b6b43291b
commit
985e441d80
21 changed files with 212 additions and 2821 deletions
|
@ -653,7 +653,6 @@ set (PCH_SOURCES
|
|||
glbackend/hw_draw2d.cpp
|
||||
|
||||
thirdparty/src/base64.cpp
|
||||
thirdparty/src/sjson.cpp
|
||||
thirdparty/src/fix16.cpp
|
||||
thirdparty/src/fix16_str.cpp
|
||||
thirdparty/src/md4.cpp
|
||||
|
|
|
@ -61,6 +61,7 @@ void CompositeSavegameWriter::AddCompressedElement(const char* filename, FCompre
|
|||
subbuffers.Push(buffer);
|
||||
buffer = {};
|
||||
subfiles.Push(nullptr);
|
||||
isCompressed.Push(true);
|
||||
}
|
||||
|
||||
FCompressedBuffer CompositeSavegameWriter::CompressElement(BufferWriter *bw, bool compress)
|
||||
|
|
|
@ -44,7 +44,6 @@
|
|||
#include "v_draw.h"
|
||||
#include "files.h"
|
||||
#include "resourcefile.h"
|
||||
#include "sjson.h"
|
||||
#include "savegamehelp.h"
|
||||
#include "i_specialpaths.h"
|
||||
#include "../../platform/win32/i_findfile.h" // This is a temporary direct path. Needs to be fixed when stuff gets cleaned up.
|
||||
|
|
|
@ -44,7 +44,6 @@
|
|||
#include "v_draw.h"
|
||||
#include "files.h"
|
||||
#include "resourcefile.h"
|
||||
#include "sjson.h"
|
||||
#include "cmdlib.h"
|
||||
#include "files.h"
|
||||
#include "savegamehelp.h"
|
||||
|
@ -52,6 +51,7 @@
|
|||
#include "c_dispatch.h"
|
||||
#include "i_system.h"
|
||||
#include "build.h"
|
||||
#include "serializer.h"
|
||||
|
||||
|
||||
FSavegameManager savegameManager;
|
||||
|
@ -378,50 +378,49 @@ unsigned FSavegameManager::ExtractSaveData(int index)
|
|||
// this should not happen because the file has already been verified.
|
||||
return index;
|
||||
}
|
||||
auto fr = info->NewReader();
|
||||
auto data = fr.ReadPadded(1);
|
||||
fr.Close();
|
||||
sjson_context* ctx = sjson_create_context(0, 0, NULL);
|
||||
if (ctx)
|
||||
|
||||
void* data = info->Get();
|
||||
FSerializer arc;
|
||||
if (!arc.OpenReader((const char*)data, info->LumpSize))
|
||||
{
|
||||
sjson_node* root = sjson_decode(ctx, (const char*)data.Data());
|
||||
return index;
|
||||
}
|
||||
|
||||
FString comment, fcomment, ncomment, mtime;
|
||||
|
||||
FString comment = sjson_get_string(root, "Creation Time", "");
|
||||
FString fcomment = sjson_get_string(root, "Map Label", "");
|
||||
FString ncomment = sjson_get_string(root, "Map Name", "");
|
||||
FString mtime = sjson_get_string(root, "Map Time", "");
|
||||
comment.AppendFormat("\n%s - %s\n%s", fcomment.GetChars(), ncomment.GetChars(), mtime.GetChars());
|
||||
SaveCommentString = comment;
|
||||
arc("Creation Time", comment)
|
||||
("Map Label", fcomment)
|
||||
("Map Name", ncomment)
|
||||
("Map Time", mtime);
|
||||
|
||||
// Extract pic (todo: let the renderer write a proper PNG file instead of a raw canvas dunp of the software renderer - and make it work for all games.)
|
||||
FResourceLump *pic = resf->FindLump("savepic.png");
|
||||
if (pic != nullptr)
|
||||
comment.AppendFormat("\n%s - %s\n%s", fcomment.GetChars(), ncomment.GetChars(), mtime.GetChars());
|
||||
SaveCommentString = comment;
|
||||
|
||||
FResourceLump *pic = resf->FindLump("savepic.png");
|
||||
if (pic != nullptr)
|
||||
{
|
||||
FileReader picreader;
|
||||
|
||||
picreader.OpenMemoryArray([=](TArray<uint8_t> &array)
|
||||
{
|
||||
FileReader picreader;
|
||||
|
||||
picreader.OpenMemoryArray([=](TArray<uint8_t> &array)
|
||||
auto cache = pic->Lock();
|
||||
array.Resize(pic->LumpSize);
|
||||
memcpy(&array[0], cache, pic->LumpSize);
|
||||
pic->Unlock();
|
||||
return true;
|
||||
});
|
||||
PNGHandle *png = M_VerifyPNG(picreader);
|
||||
if (png != nullptr)
|
||||
{
|
||||
SavePic = PNGTexture_CreateFromFile(png, node->Filename);
|
||||
delete png;
|
||||
if (SavePic && SavePic->GetWidth() == 1 && SavePic->GetHeight() == 1)
|
||||
{
|
||||
auto cache = pic->Lock();
|
||||
array.Resize(pic->LumpSize);
|
||||
memcpy(&array[0], cache, pic->LumpSize);
|
||||
pic->Unlock();
|
||||
return true;
|
||||
});
|
||||
PNGHandle *png = M_VerifyPNG(picreader);
|
||||
if (png != nullptr)
|
||||
{
|
||||
SavePic = PNGTexture_CreateFromFile(png, node->Filename);
|
||||
delete png;
|
||||
if (SavePic && SavePic->GetWidth() == 1 && SavePic->GetHeight() == 1)
|
||||
{
|
||||
delete SavePic;
|
||||
SavePic = nullptr;
|
||||
SavePicData.Clear();
|
||||
}
|
||||
delete SavePic;
|
||||
SavePic = nullptr;
|
||||
SavePicData.Clear();
|
||||
}
|
||||
}
|
||||
sjson_destroy_context(ctx);
|
||||
}
|
||||
delete resf;
|
||||
}
|
||||
|
|
|
@ -50,10 +50,9 @@
|
|||
#include "c_dispatch.h"
|
||||
#include "gamecontrol.h"
|
||||
#include "filereadermusicinterface.h"
|
||||
#include "savegamehelp.h"
|
||||
#include "sjson.h"
|
||||
#include "v_text.h"
|
||||
#include "mapinfo.h"
|
||||
#include "serializer.h"
|
||||
|
||||
MusPlayingInfo mus_playing;
|
||||
MusicAliasMap MusicAliases;
|
||||
|
@ -707,61 +706,27 @@ void Mus_SetPaused(bool on)
|
|||
else S_ResumeMusic();
|
||||
}
|
||||
|
||||
void MUS_Save()
|
||||
void Mus_Serialize(FSerializer &arc)
|
||||
{
|
||||
FString music = mus_playing.name;
|
||||
if (music.IsEmpty()) music = mus_playing.LastSong;
|
||||
|
||||
sjson_context* ctx = sjson_create_context(0, 0, NULL);
|
||||
if (!ctx)
|
||||
if (arc.BeginObject("music"))
|
||||
{
|
||||
return;
|
||||
if (arc.isWriting())
|
||||
{
|
||||
FString music = mus_playing.name;
|
||||
if (music.IsEmpty()) music = mus_playing.LastSong;
|
||||
|
||||
arc.AddString("music", music);
|
||||
}
|
||||
else arc("music", mus_playing.LastSong);
|
||||
|
||||
arc("baseorder", mus_playing.baseorder)
|
||||
("loop", mus_playing.loop)
|
||||
.EndObject();
|
||||
|
||||
// this is to prevent scripts from resetting the music after it has been loaded from the savegame.
|
||||
if (arc.isReading()) mus_blocked = true;
|
||||
// Actual music resuming cannot be performed here, it must be done in the game code.
|
||||
}
|
||||
sjson_node* root = sjson_mkobject(ctx);
|
||||
sjson_put_string(ctx, root, "music", music);
|
||||
sjson_put_int(ctx, root, "baseorder", mus_playing.baseorder);
|
||||
sjson_put_bool(ctx, root, "loop", mus_playing.loop);
|
||||
|
||||
char* encoded = sjson_stringify(ctx, root, " ");
|
||||
|
||||
FileWriter* fil = WriteSavegameChunk("music.json");
|
||||
if (!fil)
|
||||
{
|
||||
sjson_destroy_context(ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
fil->Write(encoded, strlen(encoded));
|
||||
|
||||
sjson_free_string(ctx, encoded);
|
||||
sjson_destroy_context(ctx);
|
||||
}
|
||||
|
||||
bool MUS_Restore()
|
||||
{
|
||||
auto fil = ReadSavegameChunk("music.json");
|
||||
if (!fil.isOpen())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto text = fil.ReadPadded(1);
|
||||
fil.Close();
|
||||
|
||||
if (text.Size() == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
sjson_context* ctx = sjson_create_context(0, 0, NULL);
|
||||
sjson_node* root = sjson_decode(ctx, (const char*)text.Data());
|
||||
mus_playing.LastSong = sjson_get_string(root, "music", "");
|
||||
mus_playing.baseorder = sjson_get_int(root, "baseorder", 0);
|
||||
mus_playing.loop = sjson_get_bool(root, "loop", true);
|
||||
sjson_destroy_context(ctx);
|
||||
mus_blocked = true; // this is to prevent scripts from resetting the music after it has been loaded from the savegame.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Mus_ResumeSaved()
|
||||
|
|
|
@ -71,9 +71,6 @@ extern MusPlayingInfo mus_playing;
|
|||
|
||||
extern float relative_volume, saved_relative_volume;
|
||||
|
||||
void MUS_Save();
|
||||
bool MUS_Restore();
|
||||
|
||||
// Note for later when the OPL player is ported.
|
||||
// DN3D and related games use "d3dtimbr.tmb"
|
||||
|
||||
|
|
|
@ -12,3 +12,5 @@ void Mus_Fade(double seconds);
|
|||
void Mus_SetPaused(bool on);
|
||||
void Mus_ResumeSaved();
|
||||
FString G_SetupFilenameBasedMusic(const char* fileName, const char *defaultfn);
|
||||
class FSerializer;
|
||||
void Mus_Serialize(FSerializer& arc);
|
||||
|
|
|
@ -12,6 +12,8 @@ enum
|
|||
MAXQUOTES = 16384,
|
||||
};
|
||||
|
||||
class FSerializer;
|
||||
|
||||
class Quotes
|
||||
{
|
||||
FString quotes[MAXQUOTES];
|
||||
|
@ -55,11 +57,9 @@ public:
|
|||
}
|
||||
|
||||
void AppendQuote(int dst, int src, int len = -1);
|
||||
void AppendExQuote(int dst, int src, int len = -1);
|
||||
void FormatQuote(int dst, const char* fmt, ...);
|
||||
void Substitute(int num, const char* text, const char* replc);
|
||||
void ReadFromSavegame();
|
||||
void WriteToSavegame();
|
||||
void Serialize(FSerializer &arc);
|
||||
};
|
||||
|
||||
extern Quotes quoteMgr;
|
||||
|
|
|
@ -37,7 +37,8 @@
|
|||
|
||||
#include "quotemgr.h"
|
||||
#include "savegamehelp.h"
|
||||
#include "sjson.h"
|
||||
#include "serializer.h"
|
||||
#include "printf.h"
|
||||
|
||||
|
||||
void Quotes::MakeStringLabel(FString "e)
|
||||
|
@ -72,15 +73,6 @@ void Quotes::AppendQuote(int dst, int src, int len)
|
|||
else quotes[dst] += FString(GStrings.localize(quotes[src]), len);
|
||||
}
|
||||
|
||||
void Quotes::AppendExQuote(int dst, int src, int len)
|
||||
{
|
||||
// This needs to apply the localization because the combined string is not localizable anymore.
|
||||
if (quotes[dst][0] == '$') quotes[dst] = GStrings.localize(quotes[dst]);
|
||||
if (len < 0) quotes[dst] << GStrings.localize(exquotes[src]);
|
||||
else quotes[dst] += FString(GStrings.localize(exquotes[src]), len);
|
||||
}
|
||||
|
||||
|
||||
void Quotes::FormatQuote(int dst, const char* fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
@ -95,88 +87,20 @@ void Quotes::Substitute(int dst, const char* text, const char* replc)
|
|||
}
|
||||
|
||||
|
||||
void Quotes::ReadFromSavegame()
|
||||
void Quotes::Serialize(FSerializer &arc)
|
||||
{
|
||||
for (auto& q : quotes) q = "";
|
||||
for (auto& q : exquotes) q = "";
|
||||
|
||||
auto fil = ReadSavegameChunk("quotes.json");
|
||||
if (!fil.isOpen())
|
||||
// This only saves the regular quotes. The ExQuotes array is immutable once initialized.
|
||||
if (arc.BeginObject("quotes"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto text = fil.ReadPadded(1);
|
||||
fil.Close();
|
||||
|
||||
if (text.Size() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
sjson_context* ctx = sjson_create_context(0, 0, NULL);
|
||||
sjson_node* root = sjson_decode(ctx, (const char*)text.Data());
|
||||
|
||||
auto qs = sjson_find_member(root, "quotes");
|
||||
auto xs = sjson_find_member(root, "exquotes");
|
||||
|
||||
sjson_node* q;
|
||||
sjson_foreach(q, qs)
|
||||
{
|
||||
int index = (int)strtoll(q->key, nullptr, 10);
|
||||
quotes[index] = q->string_;
|
||||
}
|
||||
sjson_foreach(q, xs)
|
||||
{
|
||||
int index = (int)strtoll(q->key, nullptr, 10);
|
||||
exquotes[index] = q->string_;
|
||||
}
|
||||
sjson_destroy_context(ctx);
|
||||
}
|
||||
|
||||
void Quotes::WriteToSavegame()
|
||||
{
|
||||
sjson_context* ctx = sjson_create_context(0, 0, NULL);
|
||||
if (!ctx)
|
||||
{
|
||||
return;
|
||||
}
|
||||
sjson_node* root = sjson_mkobject(ctx);
|
||||
sjson_node* qs = sjson_mkobject(ctx);
|
||||
sjson_node* xs = sjson_mkobject(ctx);
|
||||
|
||||
for (unsigned i = 0; i < MAXQUOTES; i++)
|
||||
{
|
||||
if (quotes[i].IsNotEmpty())
|
||||
for (int i = 0; i < MAXQUOTES; i++)
|
||||
{
|
||||
char buff[10];
|
||||
snprintf(buff, 10, "%d", i);
|
||||
sjson_append_member(ctx, qs, buff, sjson_mkstring(ctx, quotes[i]));
|
||||
}
|
||||
if (exquotes[i].IsNotEmpty())
|
||||
{
|
||||
char buff[10];
|
||||
snprintf(buff, 10, "%d", i);
|
||||
sjson_append_member(ctx, xs, buff, sjson_mkstring(ctx, exquotes[i]));
|
||||
char buf[10];
|
||||
mysnprintf(buf, 10, "%d", i);
|
||||
FString nulstr;
|
||||
arc(buf, quotes[i], nulstr);
|
||||
}
|
||||
arc.EndObject();
|
||||
}
|
||||
sjson_append_member(ctx, root, "quotes", qs);
|
||||
sjson_append_member(ctx, root, "exquotes", xs);
|
||||
|
||||
char* encoded = sjson_stringify(ctx, root, " ");
|
||||
FileWriter* fil = WriteSavegameChunk("quotes.json");
|
||||
if (!fil)
|
||||
{
|
||||
sjson_destroy_context(ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
fil->Write(encoded, strlen(encoded));
|
||||
|
||||
sjson_free_string(ctx, encoded);
|
||||
sjson_destroy_context(ctx);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
Quotes quoteMgr;
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
|
||||
#include "compositesaveame.h"
|
||||
#include "savegamehelp.h"
|
||||
#include "sjson.h"
|
||||
#include "baselayer.h"
|
||||
#include "gstrings.h"
|
||||
#include "i_specialpaths.h"
|
||||
|
@ -43,7 +42,6 @@
|
|||
#include "filesystem/filesystem.h"
|
||||
#include "statistics.h"
|
||||
#include "secrets.h"
|
||||
#include "s_music.h"
|
||||
#include "quotemgr.h"
|
||||
#include "mapinfo.h"
|
||||
#include "v_video.h"
|
||||
|
@ -51,6 +49,7 @@
|
|||
#include "m_argv.h"
|
||||
#include "serializer.h"
|
||||
#include "version.h"
|
||||
#include "z_music.h"
|
||||
|
||||
static CompositeSavegameWriter savewriter;
|
||||
static FResourceFile *savereader;
|
||||
|
@ -59,6 +58,20 @@ void SaveEngineState();
|
|||
|
||||
CVAR(String, cl_savedir, "", CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
static void SerializeSession(FSerializer& arc)
|
||||
{
|
||||
SerializeStatistics(arc);
|
||||
SECRET_Serialize(arc);
|
||||
Mus_Serialize(arc);
|
||||
quoteMgr.Serialize(arc);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// This is for keeping my sanity while working with the horrible mess
|
||||
|
@ -80,12 +93,21 @@ bool OpenSaveGameForRead(const char *name)
|
|||
|
||||
if (savereader != nullptr)
|
||||
{
|
||||
FResourceLump* info = savereader->FindLump("session.json");
|
||||
if (info == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
FSerializer arc;
|
||||
void* data = info->Get();
|
||||
if (!arc.OpenReader((const char*)data, info->LumpSize))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Load system-side data from savegames.
|
||||
ReadStatistics();
|
||||
SECRET_Load();
|
||||
MUS_Restore();
|
||||
quoteMgr.ReadFromSavegame();
|
||||
SerializeSession(arc);
|
||||
LoadEngineState();
|
||||
|
||||
auto file = ReadSavegameChunk("info.json");
|
||||
|
@ -152,7 +174,6 @@ bool OpenSaveGameForWrite(const char* filename, const char *name)
|
|||
FSerializer savegameengine; // saved play state.
|
||||
|
||||
savegameinfo.OpenWriter(true);
|
||||
savegamesession.OpenWriter(save_formatted);
|
||||
savegameengine.OpenWriter(save_formatted);
|
||||
|
||||
char buf[100];
|
||||
|
@ -192,10 +213,11 @@ bool OpenSaveGameForWrite(const char* filename, const char *name)
|
|||
|
||||
|
||||
// Handle system-side modules that need to persist data in savegames here, in a central place.
|
||||
SaveStatistics();
|
||||
SECRET_Save();
|
||||
MUS_Save();
|
||||
quoteMgr.WriteToSavegame();
|
||||
savegamesession.OpenWriter(save_formatted);
|
||||
SerializeSession(savegamesession);
|
||||
buff = savegamesession.GetCompressedOutput();
|
||||
AddCompressedSavegameChunk("session.json", buff);
|
||||
|
||||
SaveEngineState();
|
||||
auto picfile = WriteSavegameChunk("savepic.png");
|
||||
screen->WriteSavePic(picfile, 240, 180);
|
||||
|
@ -270,84 +292,75 @@ static bool G_CheckSaveGameWads (const char *gamegrp, const char *mapgrp, bool p
|
|||
|
||||
int G_ValidateSavegame(FileReader &fr, FString *savetitle, bool formenu)
|
||||
{
|
||||
#if 0
|
||||
FSerializer arc(nullptr);
|
||||
if (!arc.OpenReader((const char*)data, info->LumpSize))
|
||||
auto data = fr.Read();
|
||||
FSerializer arc;
|
||||
if (!arc.OpenReader((const char*)data.Data(), data.Size()))
|
||||
{
|
||||
LoadGameError("TXT_FAILEDTOREADSG");
|
||||
return;
|
||||
return -2;
|
||||
}
|
||||
#endif
|
||||
|
||||
auto data = fr.ReadPadded(1);
|
||||
|
||||
sjson_context* ctx = sjson_create_context(0, 0, NULL);
|
||||
if (ctx)
|
||||
int savever;
|
||||
FString engine, gamegrp, mapgrp, title, filename;
|
||||
|
||||
arc("Save Version", savever)
|
||||
("Engine", engine)
|
||||
("Game Resource", gamegrp)
|
||||
("Map Resource", mapgrp)
|
||||
("Title", title)
|
||||
("Map File", filename);
|
||||
|
||||
auto savesig = gi->GetSaveSig();
|
||||
|
||||
if (savetitle) *savetitle = title;
|
||||
if (engine.Compare(savesig.savesig) != 0 || savever > savesig.currentsavever)
|
||||
{
|
||||
sjson_node* root = sjson_decode(ctx, (const char*)data.Data());
|
||||
|
||||
|
||||
int savever = sjson_get_int(root, "Save Version", -1);
|
||||
FString engine = sjson_get_string(root, "Engine", "");
|
||||
FString gamegrp = sjson_get_string(root, "Game Resource", "");
|
||||
FString mapgrp = sjson_get_string(root, "Map Resource", "");
|
||||
FString title = sjson_get_string(root, "Title", "");
|
||||
FString filename = sjson_get_string(root, "Map File", "");
|
||||
auto savesig = gi->GetSaveSig();
|
||||
|
||||
sjson_destroy_context(ctx);
|
||||
|
||||
if (savetitle) *savetitle = title;
|
||||
if (engine.Compare(savesig.savesig) != 0 || savever > savesig.currentsavever)
|
||||
// different engine or newer version:
|
||||
// not our business. Leave it alone.
|
||||
return 0;
|
||||
}
|
||||
|
||||
MapRecord *curLevel = nullptr;
|
||||
|
||||
if (strncmp(filename, "file://", 7) != 0)
|
||||
{
|
||||
for (auto& mr : mapList)
|
||||
{
|
||||
// different engine or newer version:
|
||||
// not our business. Leave it alone.
|
||||
if (mr.fileName.Compare(filename) == 0)
|
||||
{
|
||||
curLevel = &mr;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
curLevel = &userMapRecord;
|
||||
if (!formenu)
|
||||
{
|
||||
userMapRecord.name = "";
|
||||
userMapRecord.SetFileName(filename);
|
||||
}
|
||||
}
|
||||
if (!curLevel) return 0;
|
||||
if (!formenu) currentLevel = curLevel;
|
||||
|
||||
|
||||
if (savever < savesig.minsavever)
|
||||
{
|
||||
// old, incompatible savegame. List as not usable.
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto ggfn = ExtractFileBase(fileSystem.GetResourceFileName(1), true);
|
||||
if (gamegrp.CompareNoCase(ggfn) == 0)
|
||||
{
|
||||
return G_CheckSaveGameWads(gamegrp, mapgrp, false) ? 1 : -2;
|
||||
}
|
||||
else
|
||||
{
|
||||
// different game. Skip this.
|
||||
return 0;
|
||||
}
|
||||
|
||||
MapRecord *curLevel = nullptr;
|
||||
|
||||
if (strncmp(filename, "file://", 7) != 0)
|
||||
{
|
||||
for (auto& mr : mapList)
|
||||
{
|
||||
if (mr.fileName.Compare(filename) == 0)
|
||||
{
|
||||
curLevel = &mr;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
curLevel = &userMapRecord;
|
||||
if (!formenu)
|
||||
{
|
||||
userMapRecord.name = "";
|
||||
userMapRecord.SetFileName(filename);
|
||||
}
|
||||
}
|
||||
if (!curLevel) return 0;
|
||||
if (!formenu) currentLevel = curLevel;
|
||||
|
||||
|
||||
if (savever < savesig.minsavever)
|
||||
{
|
||||
// old, incompatible savegame. List as not usable.
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto ggfn = ExtractFileBase(fileSystem.GetResourceFileName(1), true);
|
||||
if (gamegrp.CompareNoCase(ggfn) == 0)
|
||||
{
|
||||
return G_CheckSaveGameWads(gamegrp, mapgrp, false) ? 1 : -2;
|
||||
}
|
||||
else
|
||||
{
|
||||
// different game. Skip this.
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -6,8 +6,7 @@
|
|||
#include "c_cvars.h"
|
||||
#include "v_font.h"
|
||||
#include "v_draw.h"
|
||||
#include "sjson.h"
|
||||
#include "savegamehelp.h"
|
||||
#include "serializer.h"
|
||||
#include "mapinfo.h"
|
||||
|
||||
// Unlike in GZDoom we have to maintain this list here, because we got different game frontents that all store this info differently.
|
||||
|
@ -109,54 +108,13 @@ CCMD(secret)
|
|||
}
|
||||
}
|
||||
|
||||
void SECRET_Save()
|
||||
void SECRET_Serialize(FSerializer &arc)
|
||||
{
|
||||
sjson_context* ctx = sjson_create_context(0, 0, NULL);
|
||||
if (!ctx)
|
||||
if (arc.BeginObject("secrets"))
|
||||
{
|
||||
return;
|
||||
arc("secrets", discovered_secrets)
|
||||
.EndObject();
|
||||
}
|
||||
sjson_node* root = sjson_mkobject(ctx);
|
||||
sjson_put_ints(ctx, root, "secrets", discovered_secrets.Data(), discovered_secrets.Size());
|
||||
|
||||
char* encoded = sjson_stringify(ctx, root, " ");
|
||||
|
||||
FileWriter* fil = WriteSavegameChunk("secrets.json");
|
||||
if (!fil)
|
||||
{
|
||||
sjson_destroy_context(ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
fil->Write(encoded, strlen(encoded));
|
||||
|
||||
sjson_free_string(ctx, encoded);
|
||||
sjson_destroy_context(ctx);
|
||||
}
|
||||
|
||||
bool SECRET_Load()
|
||||
{
|
||||
auto fil = ReadSavegameChunk("secrets.json");
|
||||
if (!fil.isOpen())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto text = fil.ReadPadded(1);
|
||||
fil.Close();
|
||||
|
||||
if (text.Size() == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
sjson_context* ctx = sjson_create_context(0, 0, NULL);
|
||||
sjson_node* root = sjson_decode(ctx, (const char*)text.Data());
|
||||
discovered_secrets.Resize(1000); // Retarted interface alert
|
||||
int realsize = sjson_get_ints(discovered_secrets.Data(), 1000, root, "secrets");
|
||||
discovered_secrets.Resize(realsize);
|
||||
sjson_destroy_context(ctx);
|
||||
return true;
|
||||
}
|
||||
|
||||
void SECRET_SetMapName(const char *filename, const char *_maptitle)
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#pragma once
|
||||
#include "files.h"
|
||||
|
||||
void SECRET_Save();
|
||||
bool SECRET_Load();
|
||||
class FSerializer;
|
||||
void SECRET_Serialize(FSerializer &arc);
|
||||
void SECRET_SetMapName(const char *filename, const char *maptitle);
|
||||
void SECRET_Trigger(int num);
|
||||
|
||||
|
|
|
@ -51,6 +51,8 @@
|
|||
#include "printf.h"
|
||||
#include "s_soundinternal.h"
|
||||
|
||||
bool save_full = false;
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// This will double-encode already existing UTF-8 content.
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include "s_music.h"
|
||||
#include "z_music.h"
|
||||
#include "gamecvars.h"
|
||||
#include "gamecontrol.h"
|
||||
#include <zmusic.h>
|
||||
|
||||
EXTERN_CVAR (Float, snd_sfxvolume)
|
||||
|
@ -70,8 +71,6 @@ CVAR(String, snd_backend, DEF_BACKEND, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
|||
CVAR (Bool, snd_pitched, false, CVAR_ARCHIVE)
|
||||
|
||||
SoundRenderer *GSnd;
|
||||
bool nosound;
|
||||
bool nosfx;
|
||||
|
||||
void I_CloseSound ();
|
||||
|
||||
|
@ -248,12 +247,9 @@ public:
|
|||
void I_InitSound ()
|
||||
{
|
||||
FModule_SetProgDir(progdir);
|
||||
/* Get command line options: */
|
||||
nosound = !!Args->CheckParm ("-nosound");
|
||||
nosfx = !!Args->CheckParm ("-nosfx");
|
||||
|
||||
GSnd = NULL;
|
||||
if (nosound)
|
||||
if (userConfig.nosound)
|
||||
{
|
||||
GSnd = new NullSoundRenderer;
|
||||
return;
|
||||
|
|
|
@ -159,8 +159,6 @@ public:
|
|||
};
|
||||
|
||||
extern SoundRenderer *GSnd;
|
||||
extern bool nosfx;
|
||||
extern bool nosound;
|
||||
|
||||
void I_InitSound ();
|
||||
void I_CloseSound();
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "name.h"
|
||||
#include "filesystem.h"
|
||||
#include "cmdlib.h"
|
||||
#include "gamecontrol.h"
|
||||
|
||||
|
||||
enum
|
||||
|
@ -382,7 +383,7 @@ FSoundChan *SoundEngine::StartSound(int type, const void *source,
|
|||
FVector3 pos, vel;
|
||||
FRolloffInfo *rolloff;
|
||||
|
||||
if (sound_id <= 0 || volume <= 0 || nosfx || nosound )
|
||||
if (sound_id <= 0 || volume <= 0 || userConfig.nosound )
|
||||
return NULL;
|
||||
|
||||
// prevent crashes.
|
||||
|
|
|
@ -45,8 +45,7 @@
|
|||
#include "c_cvars.h"
|
||||
#include "sc_man.h"
|
||||
#include "baselayer.h"
|
||||
#include "savegamehelp.h"
|
||||
#include "sjson.h"
|
||||
#include "serializer.h"
|
||||
#include "gstrings.h"
|
||||
#include "version.h"
|
||||
|
||||
|
@ -468,112 +467,31 @@ void STAT_Cancel()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void SaveOneLevel(sjson_context *ctx, sjson_node *lev, OneLevel& l)
|
||||
FSerializer& Serialize(FSerializer& arc, const char* key, OneLevel& l, OneLevel* def)
|
||||
{
|
||||
sjson_put_int(ctx, lev, "totalkills", l.totalkills);
|
||||
sjson_put_int(ctx, lev, "kills", l.killcount);
|
||||
sjson_put_int(ctx, lev, "totalsecrets", l.totalsecrets);
|
||||
sjson_put_int(ctx, lev, "secrets", l.secretcount);
|
||||
sjson_put_int(ctx, lev, "leveltime", l.leveltime);
|
||||
sjson_put_string(ctx, lev, "levelname", l.Levelname);
|
||||
if (arc.BeginObject(key))
|
||||
{
|
||||
arc("totalkills", l.totalkills)
|
||||
("killcount", l.killcount)
|
||||
("totalsecrets", l.totalsecrets)
|
||||
("secretcount", l.secretcount)
|
||||
("leveltime", l.leveltime)
|
||||
("levelname", l.Levelname)
|
||||
.EndObject();
|
||||
}
|
||||
return arc;
|
||||
}
|
||||
|
||||
void ReadOneLevel(sjson_node *lev, OneLevel& l)
|
||||
void SerializeStatistics(FSerializer &arc)
|
||||
{
|
||||
|
||||
l.totalkills = sjson_get_int(lev, "totalkills", 0);
|
||||
l.killcount = sjson_get_int(lev, "kills", 0);
|
||||
l.totalsecrets = sjson_get_int(lev, "totalsecrets", 0);
|
||||
l.secretcount = sjson_get_int(lev, "secrets", 0);
|
||||
l.leveltime = sjson_get_int(lev, "leveltime", 0);
|
||||
l.Levelname = sjson_get_string(lev, "levelname", "");
|
||||
}
|
||||
|
||||
void SaveStatistics()
|
||||
{
|
||||
sjson_context* ctx = sjson_create_context(0, 0, NULL);
|
||||
if (!ctx)
|
||||
if (arc.BeginObject("statistics"))
|
||||
{
|
||||
return;
|
||||
arc("levelname", LevelName)
|
||||
("episode", StartEpisode)
|
||||
("skill", StartSkill)
|
||||
("levels", LevelData)
|
||||
.EndObject();
|
||||
}
|
||||
sjson_node* root = sjson_mkobject(ctx);
|
||||
|
||||
sjson_put_string(ctx, root, "levelname", LevelName);
|
||||
sjson_put_string(ctx, root, "episode", StartEpisode);
|
||||
sjson_put_int(ctx, root, "skill", StartSkill);
|
||||
|
||||
sjson_node* levels = sjson_mkarray(ctx);
|
||||
for (auto& lev : LevelData)
|
||||
{
|
||||
sjson_node* levj = sjson_mkobject(ctx);
|
||||
SaveOneLevel(ctx, levj, lev);
|
||||
sjson_append_element(levels, levj);
|
||||
}
|
||||
sjson_append_member(ctx, root, "levels", levels);
|
||||
|
||||
char errmsg[256];
|
||||
if (!sjson_check(root, errmsg))
|
||||
{
|
||||
buildprint(errmsg, "\n");
|
||||
sjson_destroy_context(ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
char* encoded = sjson_stringify(ctx, root, " ");
|
||||
|
||||
FileWriter* fil = WriteSavegameChunk("statistics.json");
|
||||
if (!fil)
|
||||
{
|
||||
sjson_destroy_context(ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
fil->Write(encoded, strlen(encoded));
|
||||
|
||||
sjson_free_string(ctx, encoded);
|
||||
sjson_destroy_context(ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
bool ReadStatistics()
|
||||
{
|
||||
auto fil = ReadSavegameChunk("statistics.json");
|
||||
if (!fil.isOpen())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto text = fil.ReadPadded(1);
|
||||
fil.Close();
|
||||
|
||||
if (text.Size() == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
sjson_context* ctx = sjson_create_context(0, 0, NULL);
|
||||
sjson_node* root = sjson_decode(ctx, (const char*)text.Data());
|
||||
|
||||
LevelName = sjson_get_string(root, "levelname", "");
|
||||
StartEpisode = sjson_get_string(root, "episode", "");
|
||||
StartSkill = sjson_get_int(root, "skill", -1);
|
||||
sjson_node* levels = sjson_find_member(root, "levels");
|
||||
|
||||
if (LevelName.Len() == 0 || StartEpisode.Len() == 0 || StartSkill == -1 || levels == nullptr)
|
||||
{
|
||||
sjson_destroy_context(ctx);
|
||||
return true; // do not error out on this.
|
||||
}
|
||||
|
||||
int numlevels = sjson_child_count(levels);
|
||||
LevelData.Resize(numlevels);
|
||||
int i = 0;
|
||||
for (auto& lev : LevelData)
|
||||
{
|
||||
ReadOneLevel(sjson_find_element(levels, i++), lev);
|
||||
}
|
||||
sjson_destroy_context(ctx);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -6,6 +6,6 @@ void STAT_NewLevel(const char* mapname);
|
|||
void STAT_Update(bool endofgame);
|
||||
void STAT_Cancel();
|
||||
|
||||
class FSerializer;
|
||||
void InitStatistics();
|
||||
void SaveStatistics();
|
||||
bool ReadStatistics();
|
||||
void SerializeStatistics(FSerializer &);
|
||||
|
|
|
@ -66,17 +66,17 @@ const char *GetVersionString();
|
|||
#define SAVESIG_SW GAMENAME ".ShadowWarrior"
|
||||
#define SAVESIG_PS GAMENAME ".Exhumed"
|
||||
|
||||
#define MINSAVEVER_DN3D 3
|
||||
#define MINSAVEVER_BLD 3
|
||||
#define MINSAVEVER_RR 3
|
||||
#define MINSAVEVER_SW 2
|
||||
#define MINSAVEVER_PS 2
|
||||
#define MINSAVEVER_DN3D 4
|
||||
#define MINSAVEVER_BLD 4
|
||||
#define MINSAVEVER_RR 4
|
||||
#define MINSAVEVER_SW 3
|
||||
#define MINSAVEVER_PS 3
|
||||
|
||||
#define SAVEVER_DN3D 3
|
||||
#define SAVEVER_BLD 3
|
||||
#define SAVEVER_RR 3
|
||||
#define SAVEVER_SW 2
|
||||
#define SAVEVER_PS 2
|
||||
#define SAVEVER_DN3D 4
|
||||
#define SAVEVER_BLD 4
|
||||
#define SAVEVER_RR 4
|
||||
#define SAVEVER_SW 3
|
||||
#define SAVEVER_PS 3
|
||||
|
||||
#if defined(__APPLE__) || defined(_WIN32)
|
||||
#define GAME_DIR GAMENAME
|
||||
|
|
2376
source/thirdparty/include/sjson.h
vendored
2376
source/thirdparty/include/sjson.h
vendored
File diff suppressed because it is too large
Load diff
5
source/thirdparty/src/sjson.cpp
vendored
5
source/thirdparty/src/sjson.cpp
vendored
|
@ -1,5 +0,0 @@
|
|||
|
||||
#include "compat.h"
|
||||
|
||||
#define SJSON_IMPLEMENT
|
||||
#include "sjson.h"
|
Loading…
Reference in a new issue