diff --git a/source/common/engine/serializer.h b/source/common/engine/serializer.h index e1f54d36e..7442edd2e 100644 --- a/source/common/engine/serializer.h +++ b/source/common/engine/serializer.h @@ -238,6 +238,12 @@ FSerializer &Serialize(FSerializer &arc, const char *key, TArray &value, return arc; } +template +FSerializer& Serialize(FSerializer& arc, const char* key, FixedBitArray& value, FixedBitArray* def) +{ + return arc.Array(key, value.Storage(), def ? def->Storage() : nullptr, value.StorageSize()); +} + template<> FSerializer& Serialize(FSerializer& arc, const char* key, PClass*& clst, PClass** def); template<> FSerializer& Serialize(FSerializer& arc, const char* key, FFont*& font, FFont** def); template<> FSerializer &Serialize(FSerializer &arc, const char *key, Dictionary *&dict, Dictionary **def); diff --git a/source/common/utility/tarray.h b/source/common/utility/tarray.h index 7bafeb9ee..ebe83f984 100644 --- a/source/common/utility/tarray.h +++ b/source/common/utility/tarray.h @@ -1527,6 +1527,16 @@ public: { memset(&bytes[0], on ? -1 : 0, sizeof(bytes)); } + + // These are for utilities that need access to the raw storage. The serializer needs this to do its work, for example. + uint8_t* Storage() + { + return bytes; + } + unsigned StorageSize() const + { + return sizeof(bytes); + } }; // A wrapper to externally stored data. diff --git a/source/core/gamestruct.h b/source/core/gamestruct.h index cf63cef3f..1d6457200 100644 --- a/source/core/gamestruct.h +++ b/source/core/gamestruct.h @@ -77,8 +77,9 @@ struct GameInterface virtual void DrawCenteredTextScreen(const DVector2& origin, const char* text, int position, bool withbg = true); virtual double SmallFontScale() { return 1; } virtual void DrawMenuCaption(const DVector2& origin, const char* text) {} - virtual bool SaveGame(FSaveGameNode*) { return false; } - virtual bool LoadGame(FSaveGameNode*) { return false; } + virtual bool SaveGame(FSaveGameNode*) { return true; } + virtual bool LoadGame(FSaveGameNode*) { return true; } + virtual void SerializeGameState(FSerializer& arc) {} virtual bool CleanupForLoad() { return true; } virtual void DrawPlayerSprite(const DVector2& origin, bool onteam) {} virtual void QuitToTitle() {} diff --git a/source/core/savegamehelp.cpp b/source/core/savegamehelp.cpp index 0e2a36242..45ecec0dc 100644 --- a/source/core/savegamehelp.cpp +++ b/source/core/savegamehelp.cpp @@ -96,6 +96,20 @@ bool OpenSaveGameForRead(const char *name) if (savereader != nullptr) { + auto file = ReadSavegameChunk("info.json"); + if (!file.isOpen()) + { + FinishSavegameRead(); + delete savereader; + return false; + } + if (G_ValidateSavegame(file, nullptr, false) <= 0) + { + FinishSavegameRead(); + delete savereader; + return false; + } + FResourceLump* info = savereader->FindLump("session.json"); if (info == nullptr) { @@ -114,20 +128,7 @@ bool OpenSaveGameForRead(const char *name) // Load system-side data from savegames. SerializeSession(arc); LoadEngineState(); - - auto file = ReadSavegameChunk("info.json"); - if (!file.isOpen()) - { - FinishSavegameRead(); - delete savereader; - return false; - } - if (G_ValidateSavegame(file, nullptr, false) <= 0) - { - FinishSavegameRead(); - delete savereader; - return false; - } + gi->SerializeGameState(arc); } return savereader != nullptr; } @@ -220,10 +221,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. savegamesession.OpenWriter(save_formatted); SerializeSession(savegamesession); + SaveEngineState(); + gi->SerializeGameState(savegamesession); buff = savegamesession.GetCompressedOutput(); AddCompressedSavegameChunk("session.json", buff); - SaveEngineState(); auto picfile = WriteSavegameChunk("savepic.png"); WriteSavePic(picfile, 240, 180); return true; @@ -494,6 +496,7 @@ void SaveEngineState() sv_prespriteextsave(); fw->Write(spriteext, sizeof(spriteext_t) * MAXSPRITES); fw->Write(wallext, sizeof(wallext_t) * MAXWALLS); + fw->Write(&randomseed, sizeof(randomseed)); sv_postspriteext(); WriteMagic(fw); @@ -556,6 +559,7 @@ void LoadEngineState() fr.Read(&Numsprites, sizeof(Numsprites)); fr.Read(spriteext, sizeof(spriteext_t) * MAXSPRITES); fr.Read(wallext, sizeof(wallext_t) * MAXWALLS); + fr.Read(&randomseed, sizeof(randomseed)); sv_postspriteext(); CheckMagic(fr); diff --git a/source/games/duke/src/duke3d.h b/source/games/duke/src/duke3d.h index 8787dd085..1e705c496 100644 --- a/source/games/duke/src/duke3d.h +++ b/source/games/duke/src/duke3d.h @@ -54,8 +54,7 @@ struct GameInterface : ::GameInterface void DrawCenteredTextScreen(const DVector2& origin, const char* text, int position, bool bg) override; double SmallFontScale() override { return isRR() ? 0.5 : 1.; } void DrawMenuCaption(const DVector2& origin, const char* text) override; - bool SaveGame(FSaveGameNode*) override; - bool LoadGame(FSaveGameNode*) override; + void SerializeGameState(FSerializer& arc) override; void QuitToTitle() override; FString GetCoordString() override; bool CheatAllowed(bool printmsg) override; diff --git a/source/games/duke/src/savegame.cpp b/source/games/duke/src/savegame.cpp index 0c8bae4da..9c4cdee95 100644 --- a/source/games/duke/src/savegame.cpp +++ b/source/games/duke/src/savegame.cpp @@ -328,7 +328,7 @@ FSerializer& Serialize(FSerializer& arc, const char* keyname, weaponhit& w, weap } -void SerializeGlobals(FSerializer& arc) +void GameInterface::SerializeGameState(FSerializer& arc) { if (arc.isReading()) { @@ -340,7 +340,7 @@ void SerializeGlobals(FSerializer& arc) memset(ambienthitag, -1, sizeof(ambienthitag)); memset(ambientlotag, -1, sizeof(ambientlotag)); } - if (arc.BeginObject("globals")) + if (arc.BeginObject("duke.gamestate")) { arc("multimode", ud.multimode); if (ud.multimode > 1) arc.Array("frags", &frags[0][0], MAXPLAYERS * MAXPLAYERS); @@ -505,16 +505,4 @@ void SerializeGlobals(FSerializer& arc) } } -bool GameInterface::LoadGame(FSaveGameNode* sv) -{ - return 0; -} - -bool GameInterface::SaveGame(FSaveGameNode* sv) -{ - return 0; -} - - - END_DUKE_NS